File Coverage

blib/lib/Data/FormValidator/ConstraintsFactory.pm
Criterion Covered Total %
statement 16 78 20.5
branch 0 22 0.0
condition 0 6 0.0
subroutine 5 29 17.2
pod 12 13 92.3
total 33 148 22.3


line stmt bran cond sub pod time code
1             #
2             # ConstraintsFactory.pm - Module to create constraints for Data::FormValidator.
3             #
4             # This file is part of Data::FormValidator.
5             #
6             # Author: Francis J. Lacoste
7             # Maintainer: Mark Stosberg
8             #
9             # Copyright (C) 2000 iNsu Innovations Inc.
10             #
11             # This program is free software; you can redistribute it and/or modify
12             # it under the terms as perl itself.
13             #
14 1     1   392 use strict;
  1         1  
  1         31  
15              
16             package Data::FormValidator::ConstraintsFactory;
17 1     1   4 use Exporter 'import';
  1         1  
  1         87  
18              
19             =pod
20              
21             =head1 NAME
22              
23             Data::FormValidator::ConstraintsFactory - Module to create constraints for HTML::FormValidator.
24              
25             =head1 DESCRIPTION
26              
27             This module contains functions to help generate complex constraints.
28              
29             If you are writing new code, take a look at L
30             instead. It's a modern alternative to what's here, offering improved names and syntax.
31              
32             =head1 SYNOPSIS
33              
34             use Data::FormValidator::ConstraintsFactory qw( :set :bool );
35              
36             constraints => {
37             param1 => make_or_constraint(
38             make_num_set_constraint( -1, ( 1 .. 10 ) ),
39             make_set_constraint( 1, ( 20 .. 30 ) ),
40             ),
41             province => make_word_set_constraint( 1, "AB QC ON TN NU" ),
42             bid => make_range_constraint( 1, 1, 10 ),
43             }
44              
45             =cut
46              
47             BEGIN {
48 1     1   1 our $VERSION = 4.85;
49 1         1 our @EXPORT = ();
50 1         2 our @EXPORT_OK = (qw/make_length_constraint/);
51              
52 1         3 our %EXPORT_TAGS =
53             (
54             bool => [ qw( make_not_constraint make_or_constraint
55             make_and_constraint ) ],
56             set => [ qw( make_set_constraint make_num_set_constraint
57             make_word_set_constraint make_cmp_set_constraint ) ],
58             num => [ qw( make_clamp_constraint make_lt_constraint
59             make_le_constraint make_gt_constraint
60             make_ge_constraint ) ],
61             );
62              
63 1         28 Exporter::export_ok_tags( 'bool' );
64 1         13 Exporter::export_ok_tags( 'set' );
65 1         528 Exporter::export_ok_tags( 'num' );
66              
67             }
68              
69             =pod
70              
71             =head1 BOOLEAN CONSTRAINTS
72              
73             Those constraints are available by using the C<:bool> tag.
74              
75             =head2 make_not_constraint( $c1 )
76              
77             This will create a constraint that will return the negation of the
78             result of constraint $c1.
79              
80             =cut
81              
82             sub make_not_constraint {
83 0     0 1 0 my $c1 = $_[0];
84             # Closure
85 0     0   0 return sub { ! $c1->( @_ ) };
  0         0  
86             }
87              
88             =head2 make_or_constraint( @constraints )
89              
90             This will create a constraint that will return the result of the first
91             constraint that return an non false result.
92              
93             =cut
94              
95             sub make_or_constraint {
96 0     0 1 0 my @c = @_;
97             # Closure
98             return sub {
99 0     0   0 my $res;
100 0         0 for my $c ( @c ) {
101 0         0 $res = $c->( @_ );
102 0 0       0 return $res if $res;
103             }
104 0         0 return $res;
105 0         0 };
106             }
107              
108             =head2 make_and_constraint( @constraints )
109              
110             This will create a constraint that will return the result of the first
111             constraint that return an non false result only if all constraints
112             returns a non-false results.
113              
114             =cut
115              
116             sub make_and_constraint {
117 0     0 1 0 my @c = @_;
118              
119             # Closure
120             return sub {
121 0     0   0 my $res;
122 0         0 for my $c ( @c ) {
123 0         0 $res = $c->( @_ );
124 0 0       0 return $res if ! $res;
125              
126 0   0     0 $res ||= $res;
127             }
128 0         0 return $res;
129 0         0 };
130             }
131              
132             =pod
133              
134             =head1 SET CONSTRAINTS
135              
136             Those constraints are available by using the C<:set> tag.
137              
138             =head2 make_set_constraint( $res, @elements )
139              
140             This will create a constraint that will return $res if the value
141             is one of the @elements set, or the negation of $res otherwise.
142              
143             The C operator is used for comparison.
144              
145             =cut
146              
147             sub make_set_constraint {
148 0     0 1 0 my $res = shift;
149 0         0 my @values = @_;
150              
151             # Closure
152             return sub {
153 0     0   0 my $v = $_[0];
154 0         0 for my $t ( @values ) {
155 0 0       0 return $res if $t eq $v;
156             }
157 0         0 return ! $res;
158             }
159 0         0 }
160              
161             =head2 make_num_set_constraint( $res, @elements )
162              
163             This will create a constraint that will return $res if the value
164             is one of the @elements set, or the negation of $res otherwise.
165              
166             The C<==> operator is used for comparison.
167              
168             =cut
169              
170             sub make_num_set_constraint {
171 0     0 1 0 my $res = shift;
172 0         0 my @values = @_;
173              
174             # Closure
175             return sub {
176 0     0   0 my $v = $_[0];
177 0         0 for my $t ( @values ) {
178 0 0       0 return $res if $t == $v;
179             }
180 0         0 return ! $res;
181             }
182 0         0 }
183              
184             =head2 make_word_set_constraint( $res, $set )
185              
186             This will create a constraint that will return $res if the value is
187             a word in $set, or the negation of $res otherwise.
188              
189             =cut
190              
191             sub make_word_set_constraint {
192 0     0 1 0 my ($res,$set) = @_;
193              
194             # Closure
195             return sub {
196 0     0   0 my $v = $_[0];
197 0 0       0 if ( $set =~ /\b$v\b/i ) {
198 0         0 return $res;
199             } else {
200 0         0 return ! $res;
201             }
202             }
203 0         0 }
204              
205             =head2 make_cmp_set_constraint( $res, $cmp, @elements )
206              
207             This will create a constraint that will return $res if the value
208             is one of the @elements set, or the negation of $res otherwise.
209              
210             $cmp is a function which takes two argument and should return true or false depending if the two elements are equal.
211              
212             =cut
213              
214             sub make_match_set_constraint {
215 0     0 0 0 my $res = shift;
216 0         0 my $cmp = shift;
217 0         0 my @values = @_;
218              
219             # Closure
220             return sub {
221 0     0   0 my $v = $_[0];
222 0         0 for my $t ( @values ) {
223 0 0       0 return $res if $cmp->($v, $t );
224             }
225 0         0 return ! $res;
226             }
227 0         0 }
228              
229             =pod
230              
231             =head1 NUMERICAL LOGICAL CONSTRAINTS
232              
233             Those constraints are available by using the C<:num> tag.
234              
235             =head2 make_clamp_constraint( $res, $low, $high )
236              
237             This will create a constraint that will return $res if the value
238             is between $low and $high bounds included or its negation otherwise.
239              
240             =cut
241              
242             sub make_clamp_constraint {
243 0     0 1 0 my ( $res, $low, $high ) = @_;
244              
245             return sub {
246 0     0   0 my $v = $_[0];
247 0 0 0     0 $v < $low || $v > $high ? ! $res : $res;
248             }
249 0         0 }
250              
251             =head2 make_lt_constraint( $res, $bound )
252              
253             This will create a constraint that will return $res if the value
254             is lower than $bound, or the negation of $res otherwise.
255              
256             =cut
257              
258             sub make_lt_constraint {
259 0     0 1 0 my ( $res, $bound ) = @_;
260              
261             return sub {
262 0 0   0   0 $_[0] < $bound ? $res : ! $res;
263             }
264 0         0 }
265              
266             =head2 make_le_constraint( $res, $bound )
267              
268             This will create a constraint that will return $res if the value
269             is lower or equal than $bound, or the negation of $res otherwise.
270              
271             =cut
272              
273             sub make_le_constraint {
274 0     0 1 0 my ( $res, $bound ) = @_;
275              
276             return sub {
277 0 0   0   0 $_[0] <= $bound ? $res : ! $res;
278             }
279 0         0 }
280              
281             =head2 make_gt_constraint( $res, $bound )
282              
283             This will create a constraint that will return $res if the value
284             is greater than $bound, or the negation of $res otherwise.
285              
286             =cut
287              
288             sub make_gt_constraint {
289 0     0 1 0 my ( $res, $bound ) = @_;
290              
291             return sub {
292 0 0   0   0 $_[0] >= $bound ? $res : ! $res;
293             }
294 0         0 }
295              
296             =head2 make_ge_constraint( $res, $bound )
297              
298             This will create a constraint that will return $res if the value
299             is greater or equal than $bound, or the negation of $res otherwise.
300              
301             =cut
302              
303             sub make_ge_constraint {
304 0     0 1 0 my ( $res, $bound ) = @_;
305              
306             return sub {
307 0 0   0   0 $_[0] >= $bound ? $res : ! $res;
308             }
309 0         0 }
310              
311             =head1 OTHER CONSTRAINTS
312              
313             =head2 make_length_constraint($max_length)
314              
315             This will create a constraint that will return true if the value
316             has a length of less than or equal to $max_length
317              
318             =cut
319              
320             sub make_length_constraint {
321 2     2 1 7 my $max_length = shift;
322 2     2   13 return sub { length(shift) <= $max_length };
  2         4  
323             }
324              
325             1;
326              
327              
328             __END__