File Coverage

blib/lib/Data/FormValidator/Constraints/MethodsFactory.pm
Criterion Covered Total %
statement 83 83 100.0
branch 22 22 100.0
condition 5 6 83.3
subroutine 29 29 100.0
pod 12 12 100.0
total 151 152 99.3


line stmt bran cond sub pod time code
1             package Data::FormValidator::Constraints::MethodsFactory;
2              
3             ###############################################################################
4             # Required inclusions.
5             ###############################################################################
6 3     3   195265 use strict;
  3         9  
  3         107  
7 3     3   19 use warnings;
  3         7  
  3         157  
8              
9             ###############################################################################
10             # Version number.
11             ###############################################################################
12             our $VERSION = '0.02';
13              
14             ###############################################################################
15             # Allow our methods to be exported
16             ###############################################################################
17 3     3   15 use Exporter;
  3         12  
  3         126  
18 3     3   18 use base qw( Exporter );
  3         12  
  3         311  
19 3     3   17 use vars qw( @EXPORT_OK %EXPORT_TAGS );
  3         6  
  3         3858  
20             %EXPORT_TAGS = (
21             'set' => [qw( FV_set FV_set_num FV_set_word FV_set_cmp )],
22             'num' => [qw( FV_clamp FV_lt FV_gt FV_le FV_ge )],
23             'bool' => [qw( FV_not FV_or FV_and )],
24             );
25             @EXPORT_OK = map { @{$_} } values %EXPORT_TAGS;
26              
27             ###############################################################################
28             # Subroutine: FV_set($result, @set)
29             ###############################################################################
30             # Creates a constraint closure that will return the provided '$result' if the
31             # value is a member of the given '@set', or the negation of '$result'
32             # otherwise.
33             #
34             # The 'eq' operator is used for comparison.
35             ###############################################################################
36             sub FV_set {
37 10     10 1 708 my ($result, @set) = @_;
38             return sub {
39 9     9   906 my $dfv = shift;
40 9         30 my $val = $dfv->get_current_constraint_value();
41 9         43 foreach my $elem (@set) {
42 15 100       47 return $result if ($val eq $elem);
43             }
44 5         16 return !$result;
45             }
46 10         71 }
47              
48             ###############################################################################
49             # Subroutine: FV_set_num($result, @set)
50             ###############################################################################
51             # Creates a constraint closure that will return the provided '$result' if the
52             # value is a member of the given '@set', or the negation of '$result'
53             # otherwise.
54             #
55             # The '==' operator is used for comparison.
56             ###############################################################################
57             sub FV_set_num {
58 2     2 1 1184 my ($result, @set) = @_;
59             return sub {
60 2     2   512 my $dfv = shift;
61 2         6 my $val = $dfv->get_current_constraint_value();
62 2         14 foreach my $elem (@set) {
63 14 100       35 return $result if ($val == $elem);
64             }
65 1         5 return !$result;
66             }
67 2         17 }
68              
69             ###############################################################################
70             # Subroutine: FV_set_word($result, $set)
71             ###############################################################################
72             # Creates a constraint closure that will return the provided '$result' if the
73             # value is a word in the given '$set', or the negation of '$result' otherwise.
74             ###############################################################################
75             sub FV_set_word {
76 2     2 1 1054 my ($result, $set) = @_;
77             return sub {
78 2     2   1920 my $dfv = shift;
79 2         8 my $val = $dfv->get_current_constraint_value();
80 2 100       59 return ($set =~ /\b$val\b/i) ? $result : !$result;
81             }
82 2         18 }
83              
84             ###############################################################################
85             # Subroutine: FV_set_cmp($result, $cmp, @set)
86             ###############################################################################
87             # Creates a constraint closure that will return the provided '$result' if the
88             # value is a member of the given '@set', or the negation of '$result'
89             # otherwise.
90             #
91             # '$cmp' is a function which takes two arguments, and should return true if the
92             # two elements are considered equal, otherwise returning false.
93             ###############################################################################
94             sub FV_set_cmp {
95 2     2 1 997 my ($result, $cmp, @set) = @_;
96             return sub {
97 2     2   512 my $dfv = shift;
98 2         6 my $val = $dfv->get_current_constraint_value();
99 2         10 foreach my $elem (@set) {
100 5 100       26 return $result if ($cmp->($val,$elem));
101             }
102 1         7 return !$result;
103             }
104 2         19 }
105              
106             ###############################################################################
107             # Subroutine: FV_clamp($result, $low, $high)
108             ###############################################################################
109             # Creates a constraint closure that will return the provided '$result' if the
110             # value is numerically between the given '$low' and '$high' bounds, or the
111             # negation of '$result' otherwise.
112             ###############################################################################
113             sub FV_clamp {
114 3     3 1 19 my ($result, $low, $high) = @_;
115             return sub {
116 3     3   819 my $dfv = shift;
117 3         8 my $val = $dfv->get_current_constraint_value();
118 3 100 100     32 return (($val < $low) or ($val > $high)) ? !$result : $result;
119             }
120 3         27 }
121              
122             ###############################################################################
123             # Subroutine: FV_lt($result, $bound)
124             ###############################################################################
125             # Creates a constraint closure that will return the provided '$result' if the
126             # value is numerically less than the given '$bound', or the negation of
127             # '$result' otherwise.
128             ###############################################################################
129             sub FV_lt {
130 5     5 1 885 my ($result, $bound) = @_;
131             return sub {
132 5     5   497 my $dfv = shift;
133 5         13 my $val = $dfv->get_current_constraint_value();
134 5 100       38 return ($val < $bound) ? $result : !$result;
135             }
136 5         27 }
137              
138             ###############################################################################
139             # Subroutine: FV_gt($result, $bound)
140             ###############################################################################
141             # Creates a constraint closure that will return the provided '$result' if the
142             # value is numerically greater than the given '$bound', or the negation of
143             # '$result' otherwise.
144             ###############################################################################
145             sub FV_gt {
146 5     5 1 1639 my ($result, $bound) = @_;
147             return sub {
148 5     5   581 my $dfv = shift;
149 5         16 my $val = $dfv->get_current_constraint_value();
150 5 100       39 return ($val > $bound) ? $result : !$result;
151             }
152 5         28 }
153              
154             ###############################################################################
155             # Subroutine: FV_le($result, $bound)
156             ###############################################################################
157             # Creates a constraint closure that will return the provided '$result' if the
158             # value is numerically less than or equal to the given '$bound', or the
159             # negation of '$result' otherwise.
160             ###############################################################################
161             sub FV_le {
162 3     3 1 750 my ($result, $bound) = @_;
163             return sub {
164 3     3   549 my $dfv = shift;
165 3         10 my $val = $dfv->get_current_constraint_value();
166 3 100       49 return ($val <= $bound) ? $result : !$result;
167             }
168 3         18 }
169              
170             ###############################################################################
171             # Subroutine: FV_ge($result, $bound)
172             ###############################################################################
173             # Creates a constraint closure that will return the provided '$result' if the
174             # value is numerically greater than or equal to the given '$bound', or the
175             # negation of '$result' otherwise.
176             ###############################################################################
177             sub FV_ge {
178 3     3 1 857 my ($result, $bound) = @_;
179             return sub {
180 3     3   621 my $dfv = shift;
181 3         9 my $val = $dfv->get_current_constraint_value();
182 3 100       22 return ($val >= $bound) ? $result : !$result;
183             }
184 3         19 }
185              
186             ###############################################################################
187             # Subroutine: FV_not($constraint)
188             ###############################################################################
189             # Creates a constraint closure that will return the negation of the result of
190             # the given '$constraint'.
191             ###############################################################################
192             sub FV_not {
193 2     2 1 6 my $constraint = shift;
194 2     2   23 return sub { !$constraint->(@_) };
  2         854  
195             }
196              
197             ###############################################################################
198             # Subroutine: FV_or(@constraints)
199             ###############################################################################
200             # Creates a constraint closure that will return the result of the first
201             # constraint that returns a non-false result.
202             ###############################################################################
203             sub FV_or {
204 3     3 1 6 my @closures = @_;
205             return sub {
206 3     3   634 foreach my $c (@closures) {
207 5         24 my $res = $c->(@_);
208 5 100       19 return $res if $res;
209             }
210 1         3 return;
211             }
212 3         17 }
213              
214             ###############################################################################
215             # Subroutine: FV_and(@constraints)
216             ###############################################################################
217             # Creates a constraint closure that will return the result of the first
218             # constraint to return a non-false result, -IF- ALL of the constraints return
219             # non-false results.
220             ###############################################################################
221             sub FV_and {
222 2     2 1 5 my @closures = @_;
223 2         3 my $results;
224             return sub {
225 2     2   497 foreach my $c (@closures) {
226 4         11 my $res = $c->(@_);
227 4 100       12 return $res if (!$res);
228 3   66     15 $results ||= $res;
229             }
230 1         3 return $results;
231             }
232 2         13 }
233              
234             1;
235              
236             =head1 NAME
237              
238             Data::FormValidator::Constraints::MethodsFactory - Create constraints for Data::FormValidator
239              
240             =head1 SYNOPSIS
241              
242             use Data::FormValidator::Constraints::MethodsFactory qw(:set :num :bool);
243              
244             # SET constraints (:set)
245             constraint_methods => {
246             status => FV_set(1, qw(new active disabled)),
247             how_many => FV_set_num(1, (1 .. 20)),
248             province => FV_set_word(1, "AB QC ON TN NU"),
249             seen_before => FV_set_cmp(1, sub { $seen{$_[0]} }, qw(foo bar)),
250             }
251              
252             # NUMERIC constraints (:num)
253             constraint_methods => {
254             how_many => FV_clamp(1, 1, 10),
255             small_amount => FV_lt(1, 3),
256             large_amount => FV_gt(1, 10),
257             small_again => FV_le(1, 3),
258             large_again => FV_ge(1, 10),
259             }
260              
261             # BOOLEAN constraints (:bool)
262             constraint_methods => {
263             bad_status => FV_not(
264             FV_set(1, qw(new active disabled))
265             ),
266             email => FV_or(
267             FV_set(1,$current_value),
268             Data::FormValidator::Constraints::email(),
269             ),
270             password => FV_and(
271             FV_length_between(6,32),
272             my_password_validation_constraint(),
273             ),
274             }
275              
276              
277             =head1 DESCRIPTION
278              
279             C provides a variety of
280             functions that can be used to generate constraint closures for use with
281             C.
282              
283             The functions/constraints provided are based on those from
284             C, B are designed to be used as
285             "new-style" constraints (while C was
286             designed for use with "old-style" constraints). Functionally, this module
287             provides equivalents for all of the constraints that were in
288             C, but if you're trying to do things
289             with the new-style you'll want to use the versions from this module instead.
290              
291             The constraints provided by this module are broken up into three main
292             categories/sections:
293              
294             =over
295              
296             =item Set constraints (:set)
297              
298             Constraint methods for working with "sets" of data. Useful for when you want
299             to check and make sure that the provided value is from a list of valid choices.
300              
301             The following constraints are exported via the C<:set> tag:
302              
303             FV_set
304             FV_set_num
305             FV_set_word
306             FV_set_cmp
307              
308             =item Numeric constraints (:num)
309              
310             Constraint methods for working with numbers. Useful when you want to check and
311             make sure that the provided value is within a specified range.
312              
313             The following constraints are exported via the C<:num> tag:
314              
315             FV_clamp
316             FV_lt
317             FV_gt
318             FV_le
319             FV_ge
320              
321             =item Boolean constraints (:bool)
322              
323             Constraint methods for working with boolean conditions. Useful when you want
324             to combine constraints together to create much more powerful constraints (e.g.
325             validating an e-mail address to make sure that it looks valid and has an
326             associated MX record, BUT only if the value actually changed from what we had
327             in the record previously).
328              
329             The following constraints are exported via the C<:bool> tag:
330              
331             FV_not
332             FV_or
333             FV_and
334              
335             =back
336              
337             =head1 METHODS
338              
339             =over
340              
341             =item FV_set($result, @set)
342              
343             Creates a constraint closure that will return the provided C<$result> if
344             the value is a member of the given C<@set>, or the negation of C<$result>
345             otherwise.
346              
347             The C operator is used for comparison.
348              
349             =item FV_set_num($result, @set)
350              
351             Creates a constraint closure that will return the provided C<$result> if
352             the value is a member of the given C<@set>, or the negation of C<$result>
353             otherwise.
354              
355             The C<==> operator is used for comparison.
356              
357             =item FV_set_word($result, $set)
358              
359             Creates a constraint closure that will return the provided C<$result> if
360             the value is a word in the given C<$set>, or the negation of C<$result>
361             otherwise.
362              
363             =item FV_set_cmp($result, $cmp, @set)
364              
365             Creates a constraint closure that will return the provided C<$result> if
366             the value is a member of the given C<@set>, or the negation of C<$result>
367             otherwise.
368              
369             C<$cmp> is a function which takes two arguments, and should return true if
370             the two elements are considered equal, otherwise returning false.
371              
372             =item FV_clamp($result, $low, $high)
373              
374             Creates a constraint closure that will return the provided C<$result> if
375             the value is numerically between the given C<$low> and C<$high> bounds, or
376             the negation of C<$result> otherwise.
377              
378             =item FV_lt($result, $bound)
379              
380             Creates a constraint closure that will return the provided C<$result> if
381             the value is numerically less than the given C<$bound>, or the negation of
382             C<$result> otherwise.
383              
384             =item FV_gt($result, $bound)
385              
386             Creates a constraint closure that will return the provided C<$result> if
387             the value is numerically greater than the given C<$bound>, or the negation
388             of C<$result> otherwise.
389              
390             =item FV_le($result, $bound)
391              
392             Creates a constraint closure that will return the provided C<$result> if
393             the value is numerically less than or equal to the given C<$bound>, or the
394             negation of C<$result> otherwise.
395              
396             =item FV_ge($result, $bound)
397              
398             Creates a constraint closure that will return the provided C<$result> if
399             the value is numerically greater than or equal to the given C<$bound>, or
400             the negation of C<$result> otherwise.
401              
402             =item FV_not($constraint)
403              
404             Creates a constraint closure that will return the negation of the result of
405             the given C<$constraint>.
406              
407             =item FV_or(@constraints)
408              
409             Creates a constraint closure that will return the result of the first
410             constraint that returns a non-false result.
411              
412             =item FV_and(@constraints)
413              
414             Creates a constraint closure that will return the result of the first
415             constraint to return a non-false result, -IF- ALL of the constraints return
416             non-false results.
417              
418             =back
419              
420             =head1 AUTHOR
421              
422             Graham TerMarsch (cpan@howlingfrog.com)
423              
424             =head1 COPYRIGHT
425              
426             Copyright (C) 2007, Graham TerMarsch. All Rights Reserved.
427              
428             This is free software; you can redistribute it and/or modify it under the same
429             license as Perl itself.
430              
431             =head1 SEE ALSO
432              
433             L.
434              
435             =cut