File Coverage

blib/lib/Input/Validator.pm
Criterion Covered Total %
statement 131 134 97.7
branch 32 42 76.1
condition 17 22 77.2
subroutine 23 26 88.4
pod 14 15 93.3
total 217 239 90.7


line stmt bran cond sub pod time code
1             package Input::Validator;
2              
3 6     6   131620 use strict;
  6         13  
  6         474  
4 6     6   29 use warnings;
  6         10  
  6         467  
5              
6 6     6   33 use base 'Input::Validator::Base';
  6         8  
  6         3972  
7              
8             our $VERSION = '0.001005';
9              
10 6     6   3430 use Input::Validator::Bulk;
  6         62  
  6         362  
11 6     6   3918 use Input::Validator::Condition;
  6         19  
  6         198  
12 6     6   4121 use Input::Validator::Field;
  6         17  
  6         183  
13 6     6   3601 use Input::Validator::Group;
  6         15  
  6         9735  
14              
15             require Carp;
16              
17             sub BUILD {
18 14     14 0 26 my $self = shift;
19              
20 14         68 $self->{fields} = {};
21 14         84 $self->{conditions} = [];
22 14         32 $self->{groups} = [];
23 14   100     78 $self->{messages} ||= {};
24              
25 14 50       55 $self->{trim} = 1 unless defined $self->{trim};
26              
27 14   100     559 $self->{explicit} ||= 0;
28              
29 14         37 return $self;
30             }
31              
32 0 0   0 1 0 sub messages { @_ > 1 ? $_[0]->{messages} = $_[1] : $_[0]->{messages} }
33 0 0   0 1 0 sub trim { @_ > 1 ? $_[0]->{trim} = $_[1] : $_[0]->{trim} }
34 0 0   0 1 0 sub explicit { @_ > 1 ? $_[0]->{explicit} = $_[1] : $_[0]->{explicit} }
35              
36             sub field {
37 19     19 1 178 my $self = shift;
38              
39             # Return field if it is already created
40 19 100 66     213 return $self->{fields}->{$_[0]}
      100        
41             if @_ == 1 && ref($_[0]) ne 'ARRAY' && $self->{fields}->{$_[0]};
42              
43             # Accept array or arrayref
44 15 100 66     95 my @names = @_ == 1 && ref($_[0]) eq 'ARRAY' ? @{$_[0]} : @_;
  4         13  
45              
46 15         32 my $fields = [];
47 15         28 foreach my $name (@names) {
48 20         127 my $field = Input::Validator::Field->new(
49             name => $name,
50             messages => $self->{messages},
51             explicit => $self->{explicit},
52             );
53              
54 20         57 $self->{fields}->{$name} = $field;
55 20         63 push @$fields, $field;
56             }
57              
58 15 100       129 return $self->{fields}->{$names[0]} if @names == 1;
59              
60 4         36 return Input::Validator::Bulk->new(fields => $fields);
61             }
62              
63             sub when {
64 2     2 1 4 my $self = shift;
65              
66 2         19 my $cond = Input::Validator::Condition->new->when(@_);
67              
68 2         4 push @{$self->{conditions}}, $cond;
  2         7  
69              
70 2         20 return $cond;
71             }
72              
73             sub group {
74 3     3 1 831 my $self = shift;
75 3         4 my $name = shift;
76 3         4 my $fields = shift;
77              
78 3 100       11 if (my ($exists) = grep { $_->name eq $name } @{$self->{groups}}) {
  1         5  
  3         11  
79 1 50       6 Carp::croak("Fields of group '$name' already defined.") if $fields;
80 1         31 return $exists;
81             }
82              
83 2         3 $fields = [map { $self->{fields}->{$_} } @$fields];
  4         11  
84              
85 2         15 my $group = Input::Validator::Group->new(name => $name, fields => $fields);
86 2         2 push @{$self->{groups}}, $group;
  2         5  
87              
88 2         9 return $group;
89             }
90              
91             sub has_unknown_params {
92 2     2 1 4 my $self = shift;
93              
94 2         7 return $self->{has_unknown_params};
95             }
96              
97             sub has_errors {
98 31     31 1 46 my $self = shift;
99              
100 31         45 my $errors = $self->{errors};
101              
102 31 100 50     234 return 1 if $errors && scalar keys %$errors;
103              
104 17         130 return 0;
105             }
106              
107             sub error {
108 18     18 1 25 my $self = shift;
109 18         37 my ($name, $message) = @_;
110              
111 18   50     44 $self->{errors} ||= {};
112              
113 18         45 $self->{errors}->{$name} = $message;
114              
115 18         48 return $self;
116             }
117              
118             sub errors {
119 9     9 1 16 my $self = shift;
120              
121 9         46 return $self->{errors};
122             }
123              
124             sub clear_errors {
125 32     32 1 71 my $self = shift;
126              
127             # Clear field errors
128 32         40 foreach my $field (CORE::values %{$self->{fields}}) {
  32         112  
129 59         217 $field->error('');
130             }
131              
132             # Clear group errors
133 32         52 foreach my $group (@{$self->{groups}}) {
  32         79  
134 8         21 $group->error('');
135             }
136              
137 32         73 $self->{errors} = {};
138             }
139              
140             sub validate {
141 30     30 1 79 my $self = shift;
142 30         42 my $params = shift;
143              
144 30         42 while (1) {
145 32         75 $self->clear_errors;
146              
147 32         91 $self->_flag_unknown($params);
148              
149 32         91 $self->_populate_fields($params);
150              
151 32         90 $self->_validate_fields;
152 32         86 $self->_validate_groups;
153              
154 9 100       35 my @conditions =
155 32         69 grep { !$_->is_matched && $_->match($self->{fields}) }
156 32         52 @{$self->{conditions}};
157 32 100       96 last unless @conditions;
158              
159 2         12 foreach my $cond (@conditions) {
160 2         11 $cond->then->($self);
161             }
162             }
163              
164 30 100       79 return $self->has_errors ? 0 : 1;
165             }
166              
167             sub _flag_unknown {
168 32     32   45 my $self = shift;
169 32         38 my $params = shift;
170              
171 32         90 foreach my $param (keys %$params) {
172 43 100       148 if (!defined $self->{fields}->{$param}) {
173 3         9 $self->{has_unknown_params} = 1;
174              
175 3 100       13 if ($self->{explicit}) {
176 1   50     5 $self->error($param => $self->{messages}->{'NOT_SPECIFIED'}
177             || 'NOT_SPECIFIED');
178             }
179             }
180             }
181             }
182              
183             sub _populate_fields {
184 32     32   41 my $self = shift;
185 32         39 my $params = shift;
186              
187 32         41 foreach my $field (CORE::values %{$self->{fields}}) {
  32         141  
188 59         164 $field->clear_value;
189              
190 59         170 $field->value($params->{$field->name});
191             }
192             }
193              
194             sub _validate_fields {
195 32     32   43 my $self = shift;
196 32         40 my $params = shift;
197              
198 32         38 foreach my $field (CORE::values %{$self->{fields}}) {
  32         85  
199 59 100       164 next if $field->is_valid;
200              
201 14 50       55 $self->error($field->name => $field->error) if $field->error;
202             }
203             }
204              
205             sub _validate_groups {
206 32     32   38 my $self = shift;
207              
208 32         40 foreach my $group (@{$self->{groups}}) {
  32         81  
209 8 100       21 next if $group->is_valid;
210              
211 5 100       12 $self->error($group->name => $group->error) if $group->error;
212             }
213             }
214              
215             sub values {
216 8     8 1 14 my $self = shift;
217              
218 8         17 my $values = {};
219              
220 8         11 foreach my $field (CORE::values %{$self->{fields}}) {
  8         28  
221 13 100 100     39 $values->{$field->name} = $field->value
222             if defined $field->value && !$field->error;
223             }
224              
225 8         43 return $values;
226             }
227              
228             sub all_values {
229 1     1 1 10 my $self = shift;
230              
231 1         2 my $values = {};
232              
233 1         3 foreach my $field (CORE::values %{$self->{fields}}) {
  1         4  
234 2 50       7 $values->{$field->name} = $field->value
235             if defined $field->value;
236             }
237              
238 1         7 return $values;
239             }
240              
241             1;
242             __END__