File Coverage

blib/lib/Validation/Class/Directive/Multiples.pm
Criterion Covered Total %
statement 67 67 100.0
branch 18 22 81.8
condition 9 17 52.9
subroutine 9 9 100.0
pod 0 5 0.0
total 103 120 85.8


line stmt bran cond sub pod time code
1             # ABSTRACT: Multiples Directive for Validation Class Field Definitions
2              
3             package Validation::Class::Directive::Multiples;
4              
5 108     108   70700 use strict;
  108         203  
  108         2871  
6 108     108   534 use warnings;
  108         217  
  108         2920  
7              
8 108     108   531 use base 'Validation::Class::Directive';
  108         185  
  108         7604  
9              
10 108     108   576 use Validation::Class::Util;
  108         199  
  108         687  
11              
12             our $VERSION = '7.900057'; # VERSION
13              
14              
15             has 'mixin' => 0;
16             has 'field' => 1;
17             has 'multi' => 0;
18             has 'message' => '%s does not support multiple values';
19             # ensure most core directives execute before this one
20             has 'dependencies' => sub {{
21             normalization => [],
22             validation => [qw(
23             alias
24             between
25             depends_on
26             error
27             errors
28             filtering
29             filters
30             label
31             length
32             matches
33             max_alpha
34             max_digits
35             max_length
36             max_sum
37             min_alpha
38             min_digits
39             min_length
40             min_sum
41             mixin
42             mixin_field
43             name
44             options
45             pattern
46             readonly
47             required
48             toggle
49             )]
50             }};
51              
52             sub after_validation {
53              
54 555     555 0 928 my $self = shift;
55              
56 555         1614 my ($proto, $field, $param) = @_;
57              
58 555 100 66     3029 if (defined $field->{multiples} && defined $param) {
59              
60 515         1528 $self->after_validation_delete_clones($proto, $field, $param);
61              
62             }
63              
64 555         1816 return $self;
65              
66             }
67              
68             sub after_validation_delete_clones {
69              
70 515     515 0 780 my $self = shift;
71              
72 515         894 my ($proto, $field, $param) = @_;
73              
74 515         1503 my $name = $field->name;
75              
76             # this will add additional processing overhead which we hate, but is how we
77             # will currently prevent the reaping of strangely named fields that appear
78             # to be clones/clonable but are not in-fact ... so we'll check if the field
79             # is in the clones array
80 8 100       66 return unless grep { defined $_ and $name eq $_ }
81 515 100       944 @{$proto->stash->{'directive.validation.clones'}}
  515         1611  
82             ;
83              
84 4         26 my ($key, $index) = $name =~ /^(.*)\:(\d+)$/;
85              
86 4 50 33     26 if ($key && defined $index) {
87              
88 4         12 my $value = $proto->params->delete($name);
89              
90 4   100     15 $proto->params->{$key} ||= [];
91              
92 4         12 $proto->params->{$key}->[$index] = $value;
93              
94             # inherit errors from clone
95              
96 4 50 33     14 if ($proto->fields->has($key) && $proto->fields->has($name)) {
97              
98 4         13 $proto->fields->get($key)->errors->add(
99              
100             $proto->fields->get($name)->errors->list
101              
102             );
103              
104             }
105              
106             # remove clone permenantly
107              
108 4         17 $proto->fields->delete($name);
109              
110 4         12 delete $proto->stash->{'directive.validation.clones'}->[$index];
111              
112             }
113              
114 4         11 return $self;
115              
116             }
117              
118             sub before_validation {
119              
120 555     555 0 882 my $self = shift;
121              
122 555         1063 my ($proto, $field, $param) = @_;
123              
124 555 100 66     3023 if (defined $field->{multiples} && defined $param) {
125              
126 515         1547 $self->before_validation_create_clones($proto, $field, $param);
127              
128             }
129              
130 555         1975 return $self;
131              
132             }
133              
134             sub before_validation_create_clones {
135              
136 515     515 0 815 my $self = shift;
137              
138 515         934 my ($proto, $field, $param) = @_;
139              
140             # clone fields to handle parameters with multi-values
141              
142 515 100       1469 if (isa_arrayref($param)) {
143              
144             # is cloning allowed? .. in the U.S it is currently illegal :}
145              
146 3 100       358 return $self->error(@_) if ! $field->{multiples};
147              
148             # clone deterministically
149              
150 2         10 my $name = $field->name;
151              
152 2         5 for (my $i=0; $i < @{$param}; $i++) {
  6         22  
153              
154 4         13 my $clone = "$name:$i";
155              
156 4         13 $proto->params->add($clone => $param->[$i]);
157              
158 4   33     15 my $label = ($field->label || $name);
159 4         20 my $options = {label => "$label #".($i+1), multiples => 0};
160              
161 4         18 $proto->clone_field($name, $clone => $options);
162              
163             # add clones to field list to be validated
164 4         13 push @{$proto->stash->{'validation.fields'}}, $clone
165 4 50       5 if grep { $_ eq $name } @{$proto->stash->{'validation.fields'}}
  6         22  
  4         14  
166             ;
167              
168             # record clones (to be reaped later)
169 4         7 push @{$proto->stash->{'directive.validation.clones'}}, $clone;
  4         13  
170              
171             }
172              
173 2         9 $proto->params->delete($name);
174              
175             # remove the field the clones are based on from the fields list
176 2         360 @{$proto->stash->{'validation.fields'}} =
177 6         13 grep { $_ ne $name } @{$proto->stash->{'validation.fields'}}
  2         8  
178 2 50       4 if @{$proto->stash->{'validation.fields'}}
  2         6  
179             ;
180              
181             }
182              
183 514         1021 return $self;
184              
185             }
186              
187             sub normalize {
188              
189 1002     1002 0 1547 my $self = shift;
190              
191 1002         1754 my ($proto, $field, $param) = @_;
192              
193             # set a default value for the multiples directives
194             # ... the default policy is deny,allow
195              
196 1002 100       3041 $field->{multiples} = 0 if ! defined $field->{multiples};
197              
198 1002         2852 return $self;
199              
200             }
201              
202             1;
203              
204             __END__