File Coverage

blib/lib/FormValidator/LazyWay.pm
Criterion Covered Total %
statement 268 319 84.0
branch 53 84 63.1
condition 30 50 60.0
subroutine 29 32 90.6
pod 1 4 25.0
total 381 489 77.9


line stmt bran cond sub pod time code
1             package FormValidator::LazyWay;
2              
3 26     26   1494013 use strict;
  26         78  
  26         2626  
4 26     26   143 use warnings;
  26         47  
  26         1535  
5              
6 26     26   359 use base qw/Class::Accessor::Fast/;
  26         212  
  26         24099  
7 26     26   175287 use FormValidator::LazyWay::Rule;
  26         91  
  26         247  
8 26     26   20800 use FormValidator::LazyWay::Message;
  26         104  
  26         271  
9 26     26   22597 use FormValidator::LazyWay::Fix;
  26         73  
  26         602  
10 26     26   18519 use FormValidator::LazyWay::Filter;
  26         72  
  26         274  
11 26     26   16791 use FormValidator::LazyWay::Utils;
  26         92  
  26         432  
12 26     26   17948 use FormValidator::LazyWay::Result;
  26         88  
  26         1694  
13 26     26   928 use UNIVERSAL::require;
  26         56  
  26         1489  
14 26     26   1170 use Carp;
  26         62  
  26         1699  
15 26     26   153 use Data::Dumper;
  26         1486  
  26         139173  
16              
17             our $VERSION = '0.20';
18              
19             __PACKAGE__->mk_accessors(qw/config unicode rule message fix filter result_class/);
20              
21             sub new {
22 41     41 1 471682 my $class = shift;
23              
24 41         102 my $args;
25 41 100       216 if ( ref $_[0] eq 'HASH' ) {
26 24         56 $args = shift;
27             }
28             else {
29 17         73 my %args = @_;
30 17         46 $args = \%args;
31             }
32              
33 41 50       253 croak 'you must set config' unless $args->{config};
34              
35 41         150 my $self = bless $args, $class;
36              
37              
38 41 100       389 if( $args->{result_class} ) {
39 1 50       7 $args->{result_class}->require or die $@;
40 1         220 $self->{result_class} = $args->{result_class};
41             }
42             else {
43 40         161 $self->{result_class} = 'FormValidator::LazyWay::Result';
44             }
45              
46 41 50 33     5613 if ( $self->unicode || $self->{config}->{unicode} ) {
47 0 0       0 Data::Visitor::Encode->require or die 'unicode option require Data::Visitor::Encode. Please Install it.';
48 0         0 my $dev = Data::Visitor::Encode->new();
49 0         0 $self->config( $dev->decode('utf8', $self->config) );
50             }
51              
52 41         1134 my $rule = FormValidator::LazyWay::Rule->new( config => $self->config );
53 41         207 my $fix = FormValidator::LazyWay::Fix->new( config => $self->config );
54 41         184 my $filter = FormValidator::LazyWay::Filter->new( config => $self->config );
55 41         171 my $message = FormValidator::LazyWay::Message->new(
56             config => $self->config,
57             rule => $rule
58             );
59              
60 41         121 $self->{rule} = $rule;
61 41         115 $self->{fix} = $fix;
62 41         105 $self->{filter} = $filter;
63 41         95 $self->{message} = $message;
64              
65 41         339 return $self;
66             }
67              
68             sub label {
69 0     0 0 0 my $self = shift;
70 0         0 my $lang = $self->message->lang;
71 0         0 return $self->message->labels->{ $lang } ;
72             }
73              
74             sub check {
75 40     40 0 102993 my $self = shift;
76 40         86 my $input = shift;
77 40 50       84 my %profile = %{ shift || {} };
  40         454  
78 40         475 my $storage = {
79             error_message => {} ,
80             valid => FormValidator::LazyWay::Utils::get_input_as_hash($input),
81             missing => [],
82             unknown => [],
83             invalid => {},
84             fixed => {},
85             };
86              
87 40         234 FormValidator::LazyWay::Utils::check_profile_syntax( \%profile );
88              
89 40         194 my @methods = (
90              
91             # profileを扱いやすい型にコンバート
92             '_conv_profile',
93              
94             '_set_dependencies',
95              
96             '_set_dependency_groups',
97              
98             # langをプロフィールにセット
99             '_set_lang',
100              
101             # デフォルトセット
102             '_set_default',
103              
104             # 空のフィールドのキーを消去
105             '_remove_empty_fields',
106              
107             # マージが設定された項目を storage にセット
108             '_merge',
109              
110             # 未定義のフィールドをセット、そしてvalidから消去
111             '_set_unknown',
112              
113             # filter ループ
114             '_filter',
115              
116             # missingのフィールドをセット、そしてvalidから消去
117             '_check_required_fields',
118              
119             # invalidチェックループ
120             '_validation_block',
121              
122             # fiexed ループ
123             '_fixed',
124              
125             );
126              
127 40         90 for my $method (@methods) {
128 480         2687 $self->$method( $storage, \%profile );
129             }
130              
131 40 100       77 $storage->{has_missing} = scalar @{$storage->{missing}} ? 1 : 0 ;
  40         185  
132 40 100       68 $storage->{has_invalid} = scalar keys %{$storage->{invalid}} ? 1 : 0 ;
  40         226  
133 40 100 100     310 $storage->{has_error} = ( $storage->{has_missing} || $storage->{has_invalid} ) ? 1 : 0 ;
134 40 100 100     309 $storage->{success} = ( $storage->{has_missing} || $storage->{has_invalid} ) ? 0 : 1 ;
135              
136 40         173 return $self->result_class->new( $storage );
137             }
138              
139             sub _set_error_message_for_display {
140 41     41   94 my $self = shift;
141 41         63 my $storage = shift;
142 41         68 my $error_messages = shift;
143 41         74 my $lang = shift;
144 41         81 my $result = {};
145              
146 41         61 foreach my $field ( keys %{$error_messages} ) {
  41         158  
147              
148 14         31 local $" = ',';
149 14         27 my $tmp = "@{$error_messages->{$field}}";
  14         64  
150 14   66     54 my $label = $self->message->labels->{ $lang }{ $field } || $field;
151 14         204 my $mes = $self->message->base_message->{ $lang }{invalid} ;
152 14         196 $mes =~ s/__rule__/$tmp/g;
153 14         73 $mes =~ s/__field__/$label/g;
154              
155 14         64 $result->{$field} = $mes;
156             }
157              
158             # setting missing error message
159 41 100       72 if ( scalar @{ $storage->{missing} } ) {
  41         179  
160 10         21 for my $field ( @{ $storage->{missing} } ) {
  10         36  
161 11   66     73 my $label = $self->message->labels->{ $lang }{ $field } || $field;
162 11         148 my $mes = $self->message->base_message->{ $lang }{missing} ;
163 11         152 $mes =~ s/__field__/$label/g;
164 11         48 $result->{$field} = $mes;
165             }
166             }
167              
168 41         206 $storage->{error_message} = $result;
169              
170             }
171              
172             sub _append_error_message {
173 16     16   86 my $self = shift;
174 16         32 my $lang = shift;
175 16         200 my $level = shift;
176 16         29 my $field = shift;
177 16         26 my $storage = shift;
178 16         551 my $label = shift;
179 16         210 my $error_messages = shift;
180 16         35 my $regex = shift;
181              
182 16         270 $storage->{invalid}{$field}{$label} = 1;
183              
184 16 100       71 unless ( exists $error_messages->{$field} ) {
185 14         50 $error_messages->{$field} = [];
186             }
187              
188 16   66     265 my $key = $regex || $field ;
189 16         26 push @{ $error_messages->{$field} },
  16         304  
190             $self->message->get(
191             { lang => $lang, field => $key , label => $label, level => $level }
192             );
193              
194             }
195              
196             sub _merge {
197 40     40   64 my $self = shift;
198 40         65 my $storage = shift;
199 40         129 my $profile = shift;
200              
201 40         70 my @fields = keys %{ $storage->{valid} } ;
  40         162  
202              
203 40 100       179 return unless $self->config->{setting}->{merge};
204              
205 1         8 for my $key ( keys %{$profile->{required}}, keys %{$profile->{optional}} ) {
  1         3  
  1         4  
206 1         3 my $field = $self->config->{setting}->{merge}->{$key};
207 1 50 33     19 if ( ref $field eq 'HASH'
      33        
208             && $field->{format}
209             && $field->{fields} ) {
210 1         2 my @values = map { $storage->{valid}->{$_} } @{ $field->{fields} };
  3         11  
  1         4  
211 1         14 $storage->{valid}->{$key} = sprintf($field->{format}, @values);
212             }
213             }
214             }
215              
216             sub _filter {
217 40     40   61 my $self = shift;
218 40         68 my $storage = shift;
219 40         61 my $profile = shift;
220              
221 40         60 my @fields = keys %{ $storage->{valid} } ;
  40         147  
222              
223 40         92 for my $field (@fields) {
224 65   50     382 my $level = $profile->{level}{$field} || 'strict';
225 65         238 ($storage->{valid}{$field} ) = $self->filter->parse($storage->{valid}{$field}, $level, $field);
226             }
227             }
228              
229             sub _fixed {
230 40     40   70 my $self = shift;
231 40         70 my $storage = shift;
232 40         73 my $profile = shift;
233              
234 40         75 my @fields = keys %{ $storage->{valid} } ;
  40         141  
235              
236 40         96 for my $field (@fields) {
237 52   50     337 my $level = $profile->{level}{$field} || 'strict';
238              
239 52         193 my ( $v , $modified ) = $self->fix->parse($storage->{valid}{$field}, $level, $field);
240 52 100 100     236 if( $profile->{use_fixed_method} && $profile->{use_fixed_method}{$field} ) {
241 1         3 my $fixed_field_name = $profile->{use_fixed_method}{$field};
242 1         6 $storage->{fixed}{$fixed_field_name} = $v;
243             }
244             else {
245 51         236 $storage->{valid}{$field} = $v;
246             }
247              
248             }
249             }
250              
251             sub _validation_block {
252 40     40   71 my $self = shift;
253 40         60 my $storage = shift;
254 40         60 my $profile = shift;
255 40         80 my $error_messages = {};
256              
257 40         61 my @fields = keys %{ $profile->{required} } ;
  40         154  
258 40         65 push @fields , keys %{ $profile->{optional} } ;
  40         128  
259              
260 40         102 for my $field (@fields) {
261 77         110 my $is_invalid = 0;
262 77   50     375 my $level = $profile->{level}{$field} || 'strict';
263              
264             # missing , empty optional
265 77 100       235 next unless exists $storage->{valid}{$field};
266              
267             # bad logic... $level may change to regex_map
268 65         229 my $validators = $self->_get_validator_methods( $field, \$level );
269 65         137 VALIDATE:
270 65         90 for my $validator ( @{$validators} ) {
271              
272 82         330 my $stash = $profile->{stash}->{$field};
273              
274 82 50       404 if ( ref $storage->{valid}{$field} eq 'ARRAY' ) {
275              
276 0         0 CHECK_ARRAYS:
277 0         0 for my $value ( @{ $storage->{valid}{$field} } ) {
278 0 0       0 if ( $validator->{method}->($value, $stash) ) {
279             # OK
280 0         0 next CHECK_ARRAYS;
281             }
282             else {
283 0         0 $self->_append_error_message( $profile->{lang},
284             $level, $field, $storage,
285             $validator->{label},
286             $error_messages , $validator->{_regex} );
287 0         0 $is_invalid++;
288 0         0 last CHECK_ARRAYS;
289             }
290             }
291              
292             # 配列をやめる。
293 0 0       0 if ( !$profile->{want_array}{ $field } ) {
294 0         0 $storage->{valid}{$field} = $storage->{valid}{$field}[0];
295 0         0 last VALIDATE;
296             }
297              
298             }
299             else {
300 82         167 my $value = $storage->{valid}{$field};
301 82 100       495 if ( $validator->{method}->( $value, $stash ) ) {
302             # return alwasy array ref when want_array is seted.
303 67 50       323 if ( $profile->{want_array}{$field} ) {
304 0         0 $storage->{valid}{$field} = [];
305 0         0 push @{ $storage->{valid}{$field} }, $value;
  0         0  
306              
307             }
308             }
309             else {
310 15         261 $self->_append_error_message( $profile->{lang}, $level, $field, $storage, $validator->{label}, $error_messages , $validator->{_regex} );
311 15         232 $is_invalid++;
312             }
313             }
314              
315             }
316 65 100       392 delete $storage->{valid}{$field} if $is_invalid;
317             }
318              
319 40         214 $self->_set_error_message_for_display( $storage, $error_messages , $profile->{lang} );
320             }
321              
322             sub _get_validator_methods {
323 67     67   210 my $self = shift;
324 67         93 my $field = shift;
325 67         90 my $level = shift;
326              
327 67         207 my $validators = $self->rule->setting->{$$level}{$field};
328              
329 67 100       675 if ( !defined $validators ) {
330              
331             # 正規表現にfieldがマッチしたら適応
332 10         19 my @validators = ();
333 10         15 foreach my $regexp ( keys %{ $self->rule->setting->{regex_map} } )
  10         33  
334             {
335 14 50       314 if ( $field =~ qr/$regexp/ ) {
336 14         23 my @tmp = map { { %$_,_regex => $regexp } } @{$self->rule->setting->{regex_map}{$regexp}};
  14         1806  
  14         45  
337 14         24 push @validators,@tmp;
338 14         54 $$level = 'regex_map';
339             }
340             }
341 10 50       34 if (scalar @validators) { $validators = \@validators }
  10         19  
342              
343             # 検証モジュールがセットされてないよ。
344 10 50       27 croak 'you should set ' . $$level . ':' . $field . ' validate method'
345             unless $validators;
346             }
347              
348 67         222 return $validators;
349             }
350              
351             sub _set_dependencies {
352 40     40   87 my $self = shift;
353 40         68 my $storage = shift;
354 40         67 my $profile = shift;
355 40 100       172 return 1 unless defined $profile->{dependencies};
356              
357 8         14 foreach my $field ( keys %{$profile->{dependencies}} ) {
  8         28  
358 8         19 my $deps = $profile->{dependencies}{$field};
359 8 50       26 if (defined $storage->{valid}{$field} ) {
360 8 50       54 if (ref($deps) eq 'HASH') {
    0          
361 8         26 for my $key (keys %$deps) {
362             # Handle case of a key with a single value given as an arrayref
363             # There is probably a better, more general solution to this problem.
364 8         16 my $val_to_compare;
365 8 50 33     41 if ((ref $storage->{valid}{$field} eq 'ARRAY') and (scalar @{ $storage->{valid}{$field} } == 1)) {
  0         0  
366 0         0 $val_to_compare = $storage->{valid}{$field}->[0];
367             }
368             else {
369 8         29 $val_to_compare = $storage->{valid}{$field};
370             }
371              
372 8 100       40 if($val_to_compare eq $key){
373 6         105 for my $dep (FormValidator::LazyWay::Utils::arrayify($deps->{$key})){
374 10         149 $profile->{required}{$dep} = 1;
375             }
376             }
377             }
378             }
379             elsif (ref $deps eq "CODE") {
380 0         0 for my $val (FormValidator::LazyWay::Utils::arrayify( $storage->{valid}{$field} )) {
381 0         0 my $returned_deps = $deps->($self, $val);
382              
383 0         0 for my $dep (FormValidator::LazyWay::Utils::arrayify($returned_deps)) {
384 0         0 $profile->{required}{$dep} = 1;
385             }
386             }
387             }
388             else {
389 0         0 for my $dep (FormValidator::LazyWay::Utils::arrayify($deps)){
390 0         0 $profile->{required}{$dep} = 1;
391             }
392             }
393             }
394             }
395             }
396              
397             sub __set_dependencies {
398 0     0   0 my $self = shift;
399 0         0 my $storage = shift;
400 0         0 my $profile = shift;
401 0 0       0 return 1 unless defined $profile->{dependencies};
402              
403 0         0 foreach my $field ( keys %{ $profile->{dependencies} } ) {
  0         0  
404 0 0       0 if ( $storage->{valid}{$field} ) {
405 0         0 for my $dependency ( @{ $profile->{dependencies}{$field} } ) {
  0         0  
406 0         0 $profile->{required}{$dependency} = 1;
407             }
408             }
409             }
410              
411 0         0 return 1;
412             }
413             sub _set_dependency_groups {
414 40     40   106 my $self = shift;
415 40         65 my $storage = shift;
416 40         73 my $profile = shift;
417 40 50       167 return 1 unless defined $profile->{dependency_groups};
418              
419              
420             # check dependency groups
421             # the presence of any member makes them all required
422 0         0 for my $group (values %{ $profile->{dependency_groups} }) {
  0         0  
423 0         0 my $require_all = 0;
424 0         0 for my $field ( FormValidator::LazyWay::Utils::arrayify($group)) {
425 0 0       0 $require_all = 1 if $storage->{valid}{$field};
426             }
427 0 0       0 if ($require_all) {
428 0         0 map { $profile->{required}{$_} = 1 } FormValidator::LazyWay::Utils::arrayify($group);
  0         0  
429             }
430             }
431              
432              
433              
434             }
435              
436             sub _check_required_fields {
437 41     41   92 my $self = shift;
438 41         63 my $storage = shift;
439 41         69 my $profile = shift;
440              
441 41         71 for my $field ( keys %{ $profile->{required} } ) {
  41         155  
442 75 100       257 push @{ $storage->{missing} }, $field
  11         28  
443             unless exists $storage->{valid}{$field};
444 75 100       270 delete $storage->{valid}{$field}
445             unless exists $storage->{valid}{$field};
446             }
447              
448 41         105 return 1;
449             }
450              
451             sub _set_lang {
452 40     40   79 my $self = shift;
453 40         128 my $storage = shift;
454 40         133 my $profile = shift;
455              
456 40   33     307 $profile->{lang} = $profile->{lang} || $self->message->lang;
457             }
458              
459             sub _conv_profile {
460 45     45   36220 my $self = shift;
461 45         408 my $storage = shift;
462 45         71 my $profile = shift;
463 45         128 my %new_profile = ();
464 45         234 %{ $new_profile{required} } = map { $_ => 1 }
  45         370  
  71         1411  
465             FormValidator::LazyWay::Utils::arrayify( $profile->{required} );
466 45         293 %{ $new_profile{optional} } = map { $_ => 1 }
  45         164  
  12         138  
467             FormValidator::LazyWay::Utils::arrayify( $profile->{optional} );
468 45         251 %{ $new_profile{want_array} } = map { $_ => 1 }
  45         143  
  2         30  
469             FormValidator::LazyWay::Utils::arrayify( $profile->{want_array} );
470              
471 45         176 $new_profile{stash} = $profile->{stash};
472              
473 45         89 %{$profile} = ( %{$profile}, %new_profile );
  45         240  
  45         221  
474              
475 45         192 return 1;
476             }
477              
478             sub _set_unknown {
479 42     42   88 my $self = shift;
480 42         63 my $storage = shift;
481 42         76 my $profile = shift;
482              
483 42   100     186 @{ $storage->{unknown} } = grep {
  78         486  
484 42         127 not( exists $profile->{optional}{$_}
485             or exists $profile->{required}{$_} )
486 42         80 } keys %{ $storage->{valid} };
487              
488             # and remove them from the list
489 42         83 for my $field ( @{ $storage->{unknown} } ) {
  42         120  
490 9         41 delete $storage->{valid}{$field};
491             }
492              
493 42         135 return 1;
494             }
495              
496             sub _set_default {
497 42     42   110 my $self = shift;
498 42         72 my $storage = shift;
499 42         70 my $profile = shift;
500              
501             # get from profile
502 42   100     259 my $defaults = $profile->{defaults} || {};
503 42         79 foreach my $field ( %{ $defaults } ) {
  42         389  
504 2 100       9 unless (defined $storage->{valid}{$field}) { $storage->{valid}{$field} = $defaults->{$field} }
  1         6  
505             }
506              
507             # get from config file
508 42 50       182 if ( defined $self->rule->defaults ) {
509 42         503 foreach my $field ( keys %{ $self->rule->defaults } ) {
  42         191  
510 2   66     37 $storage->{valid}{$field} ||= $self->rule->defaults->{$field};
511             }
512             }
513              
514              
515 42         399 return 1;
516             }
517              
518             sub _remove_empty_fields {
519 41     41   96 my $self = shift;
520 41         68 my $storage = shift;
521 41         192 $storage->{valid} = FormValidator::LazyWay::Utils::remove_empty_fields(
522             $storage->{valid} );
523              
524 41         92 return 1;
525             }
526              
527             sub add_custom_invalid {
528 0     0 0   my $self = shift;
529 0           my $form = shift;
530 0           my $key = shift;
531 0   0       my $message
532             = $self->{messages}{config}{messages}{ $form->lang }{custom_invalid}
533             {$key} || $key;
534 0           $form->custom_invalid( $key, $message );
535             }
536              
537             1;
538              
539             __END__