Newer Older
216 lines | 5.201kb
add files
Yuki Kimoto authored on 2014-03-26
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