add files
|
1 |
package Mojolicious::Validator::Validation; |
2 |
use Mojo::Base -base; |
|
3 | ||
4 |
use Carp 'croak'; |
|
5 |
use Scalar::Util 'blessed'; |
|
6 | ||
7 |
has [qw(input output)] => sub { {} }; |
|
8 |
has [qw(topic validator)]; |
|
9 | ||
10 |
sub AUTOLOAD { |
|
11 |
my $self = shift; |
|
12 | ||
13 |
my ($package, $method) = our $AUTOLOAD =~ /^([\w:]+)::(\w+)$/; |
|
14 |
croak "Undefined subroutine &${package}::$method called" |
|
15 |
unless blessed $self && $self->isa(__PACKAGE__); |
|
16 | ||
17 |
croak qq{Can't locate object method "$method" via package "$package"} |
|
18 |
unless $self->validator->checks->{$method}; |
|
19 |
return $self->check($method => @_); |
|
20 |
} |
|
21 | ||
22 |
sub DESTROY { } |
|
23 | ||
24 |
sub check { |
|
25 |
my ($self, $check) = (shift, shift); |
|
26 | ||
27 |
return $self unless $self->is_valid; |
|
28 | ||
29 |
my $cb = $self->validator->checks->{$check}; |
|
30 |
my $name = $self->topic; |
|
31 |
my $input = $self->input->{$name}; |
|
32 |
for my $value (ref $input eq 'ARRAY' ? @$input : $input) { |
|
33 |
next unless my $result = $self->$cb($name, $value, @_); |
|
34 |
delete $self->output->{$name}; |
|
35 |
$self->{error}{$name} = [$check, $result, @_]; |
|
36 |
last; |
|
37 |
} |
|
38 | ||
39 |
return $self; |
|
40 |
} |
|
41 | ||
42 |
sub error { shift->{error}{shift()} } |
|
43 | ||
44 |
sub has_data { !!keys %{shift->input} } |
|
45 | ||
46 |
sub has_error { $_[1] ? exists $_[0]{error}{$_[1]} : !!keys %{$_[0]{error}} } |
|
47 | ||
48 |
sub is_valid { exists $_[0]->output->{$_[1] // $_[0]->topic} } |
|
49 | ||
50 |
sub optional { |
|
51 |
my ($self, $name) = @_; |
|
52 | ||
53 |
my $input = $self->input->{$name}; |
|
54 |
my @input = ref $input eq 'ARRAY' ? @$input : $input; |
|
55 |
$self->output->{$name} = $input |
|
56 |
unless grep { !defined($_) || !length($_) } @input; |
|
57 | ||
58 |
return $self->topic($name); |
|
59 |
} |
|
60 | ||
61 |
sub param { |
|
62 |
my ($self, $name) = @_; |
|
63 | ||
64 |
# Multiple names |
|
65 |
return map { scalar $self->param($_) } @$name if ref $name eq 'ARRAY'; |
|
66 | ||
67 |
# List names |
|
68 |
return sort keys %{$self->output} unless defined $name; |
|
69 | ||
70 |
my $value = $self->output->{$name}; |
|
71 |
my @values = ref $value eq 'ARRAY' ? @$value : ($value); |
|
72 |
return wantarray ? @values : $values[0]; |
|
73 |
} |
|
74 | ||
75 |
sub required { |
|
76 |
my ($self, $name) = @_; |
|
77 |
$self->{error}{$name} = ['required'] unless $self->optional($name)->is_valid; |
|
78 |
return $self; |
|
79 |
} |
|
80 | ||
81 |
1; |
|
82 | ||
83 |
=encoding utf8 |
|
84 | ||
85 |
=head1 NAME |
|
86 | ||
87 |
Mojolicious::Validator::Validation - Perform validations |
|
88 | ||
89 |
=head1 SYNOPSIS |
|
90 | ||
91 |
use Mojolicious::Validator; |
|
92 |
use Mojolicious::Validator::Validation; |
|
93 | ||
94 |
my $validator = Mojolicious::Validator->new; |
|
95 |
my $validation |
|
96 |
= Mojolicious::Validator::Validation->new(validator => $validator); |
|
97 |
$validation->input({foo => 'bar'}); |
|
98 |
$validation->required('foo')->in(qw(bar baz)); |
|
99 |
say $validation->param('foo'); |
|
100 | ||
101 |
=head1 DESCRIPTION |
|
102 | ||
103 |
L<Mojolicious::Validator::Validation> performs L<Mojolicious::Validator> |
|
104 |
validation checks. |
|
105 | ||
106 |
=head1 ATTRIBUTES |
|
107 | ||
108 |
L<Mojolicious::Validator::Validation> implements the following attributes. |
|
109 | ||
110 |
=head2 input |
|
111 | ||
112 |
my $input = $validation->input; |
|
113 |
$validation = $validation->input({foo => 'bar', baz => [123, 'yada']}); |
|
114 | ||
115 |
Data to be validated. |
|
116 | ||
117 |
=head2 output |
|
118 | ||
119 |
my $output = $validation->output; |
|
120 |
$validation = $validation->output({}); |
|
121 | ||
122 |
Validated data. |
|
123 | ||
124 |
=head2 topic |
|
125 | ||
126 |
my $topic = $validation->topic; |
|
127 |
$validation = $validation->topic('foo'); |
|
128 | ||
129 |
Name of field currently being validated. |
|
130 | ||
131 |
=head2 validator |
|
132 | ||
133 |
my $validator = $validation->validator; |
|
134 |
$validation = $validation->validator(Mojolicious::Validator->new); |
|
135 | ||
136 |
L<Mojolicious::Validator> object this validation belongs to. |
|
137 | ||
138 |
=head1 METHODS |
|
139 | ||
140 |
L<Mojolicious::Validator::Validation> inherits all methods from L<Mojo::Base> |
|
141 |
and implements the following new ones. |
|
142 | ||
143 |
=head2 check |
|
144 | ||
145 |
$validation = $validation->check('size', 2, 7); |
|
146 | ||
147 |
Perform validation check on all values of the current L</"topic">, no more |
|
148 |
checks will be performend on them after the first one failed. |
|
149 | ||
150 |
=head2 error |
|
151 | ||
152 |
my $err = $validation->error('foo'); |
|
153 | ||
154 |
Return details about failed validation check, at any given time there can only |
|
155 |
be one per field. |
|
156 | ||
157 |
my ($check, $result, @args) = @{$validation->error('foo')}; |
|
158 | ||
159 |
=head2 has_data |
|
160 | ||
161 |
my $bool = $validation->has_data; |
|
162 | ||
163 |
Check if L</"input"> is available for validation. |
|
164 | ||
165 |
=head2 has_error |
|
166 | ||
167 |
my $bool = $validation->has_error; |
|
168 |
my $bool = $validation->has_error('foo'); |
|
169 | ||
170 |
Check if validation resulted in errors, defaults to checking all fields. |
|
171 | ||
172 |
=head2 is_valid |
|
173 | ||
174 |
my $bool = $validation->is_valid; |
|
175 |
my $bool = $validation->is_valid('foo'); |
|
176 | ||
177 |
Check if validation was successful and field has a value, defaults to checking |
|
178 |
the current L</"topic">. |
|
179 | ||
180 |
=head2 optional |
|
181 | ||
182 |
$validation = $validation->optional('foo'); |
|
183 | ||
184 |
Change validation L</"topic">. |
|
185 | ||
186 |
=head2 param |
|
187 | ||
188 |
my @names = $c->param; |
|
189 |
my $foo = $c->param('foo'); |
|
190 |
my @foo = $c->param('foo'); |
|
191 |
my ($foo, $bar) = $c->param(['foo', 'bar']); |
|
192 | ||
193 |
Access validated parameters, similar to L<Mojolicious::Controller/"param">. |
|
194 | ||
195 |
=head2 required |
|
196 | ||
197 |
$validation = $validation->required('foo'); |
|
198 | ||
199 |
Change validation L</"topic"> and make sure a value is present and not an |
|
200 |
empty string. |
|
201 | ||
202 |
=head1 CHECKS |
|
203 | ||
204 |
In addition to the methods above, you can also call validation checks provided |
|
205 |
by L<Mojolicious::Validator> on L<Mojolicious::Validator::Validation> objects, |
|
206 |
similar to L</"check">. |
|
207 | ||
208 |
$validation->required('foo')->size(2, 5)->like(qr/^[A-Z]/); |
|
209 |
$validation->optional('bar')->equal_to('foo'); |
|
210 |
$validation->optional('baz')->in(qw(test 123)); |
|
211 | ||
212 |
=head1 SEE ALSO |
|
213 | ||
214 |
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>. |
|
215 | ||
216 |
=cut |