File Coverage

blib/lib/Validator/Var.pm
Criterion Covered Total %
statement 75 84 89.2
branch 31 38 81.5
condition 4 7 57.1
subroutine 13 14 92.8
pod 7 7 100.0
total 130 150 86.6


line stmt bran cond sub pod time code
1             package Validator::Var;
2 2     2   19949 use 5.006;
  2         7  
  2         70  
3 2     2   10 use strict;
  2         3  
  2         56  
4 2     2   9 use warnings;
  2         9  
  2         64  
5 2     2   10 use Carp;
  2         2  
  2         1860  
6              
7              
8             =head1 NAME
9              
10             Validator::Var - variable validator with expandable list of checkers.
11              
12             =head1 VERSION
13              
14             Version 0.03
15              
16             =cut
17              
18             our $VERSION = '0.03';
19              
20              
21             =head1 SYNOPSIS
22              
23             use Validator::Var;
24             my $var;
25            
26             ...
27              
28             my $num_bitween = Validator::Var->new();
29             $foo->checker(Between, 0, 100);
30             unless ( $foo->is_valid( $var ) ) {
31             warn "variable is not bitween 0 an 100";
32             }
33              
34             my $number = Validator::Var->new();
35             $number->checker(Regexp, '^d+$');
36            
37             unless ( $bar->is_valid( $var ) ) {
38             warn "variable is not a number";
39             }
40            
41             my $ref_validator = Validator::Var->new();
42             $ref_validator->checker(Ref, qw(REF Foo Bar));
43             unless ( $bar->is_valid( $var ) ) {
44             warn "variable is not a number";
45             }
46              
47            
48             ...
49              
50             =cut
51              
52 1     1   109 sub _print { print @_; }
53 1     1   141 sub _warn { warn @_; }
54              
55 8     8   32 sub _Def { [undef, 'Def', 'var is defined' ] }
56              
57              
58             =head1 METHODS
59              
60             =head2 new( [$at_least_one] )
61              
62             Creates new variable validator.
63             If C is provided and it is true validation will be
64             passed if passed through at least one checker.
65              
66             =cut
67              
68             sub new
69             {
70 8     8 1 32 my $class = shift;
71 8   50     39 my $at_least_one = shift || 0;
72 8         46 my $self = bless {
73             'checkers'=>[],
74             'checkers_not_passed'=>[],
75             'at_least_one' => $at_least_one }, $class;
76 8         22 $self->checker(_Def);
77 8         38 return $self;
78             }
79              
80             =head2 is_empty
81              
82             Checks if variable validator has no any checker.
83              
84             =cut
85              
86             sub is_empty
87             {
88 2 100   2 1 6 return @{$_[0]->{'checkers'}} > 1 ? 0 : 1;
  2         20  
89             }
90              
91              
92             =head2 at_least_one( $bool )
93              
94             =cut
95              
96             sub at_least_one
97             {
98 1     1 1 3 $_[0]->{'at_least_one'} = $_[1];
99 1         3 return $_[0];
100             }
101              
102              
103              
104             =head2 checker( $checker[, $checker_args] )
105              
106             Set (append) new checker.
107              
108             =cut
109              
110             sub checker
111             {
112 21     21 1 42 my ($self, @args) = @_;
113 21 50       58 $self->{'checkers'} = [] unless defined $self->{'checkers'};
114 21         24 push @{$self->{'checkers'}}, \@args;
  21         47  
115 21         142 return $self;
116             }
117              
118              
119             =head2 checkers_not_passed
120              
121             =cut
122              
123             sub checkers_not_passed
124             {
125 0     0 1 0 my $self = shift;
126              
127 0         0 my @checkers_not_passed_spec = ();
128 0         0 foreach my $i ( @{$self->{'checkers_not_passed'}} ) {
  0         0  
129 0         0 my $checker = $self->{'checkers'}->[$i]->[0];
130 0         0 push @checkers_not_passed_spec, [ $checker->[1], $checker->[2] ];
131             }
132 0 0       0 return wantarray ? @checkers_not_passed_spec : \@checkers_not_passed_spec;
133             }
134              
135             =head2 is_valid( $var [, $do_trace] )
136              
137             Checks if variable value is valid according to specified checkers.
138             Trace data will be gathered if C is provided and it is true.
139              
140             =cut
141              
142             sub is_valid
143             {
144 17     17 1 73 my ($self, $val, $do_trace) = @_;
145 17 100       43 $do_trace = 0 unless defined $do_trace;
146              
147 17         36 $self->{'checkers_not_passed'} = [];
148              
149 17 100       42 unless ( defined $val ) {
150 1         2 push @{$self->{'checkers_not_passed'}}, 0;
  1         3  
151 1         17 return 0;
152             }
153              
154 16         23 for( my $i = 1; $i < @{$self->{'checkers'}}; $i++ ) {
  32         89  
155 21         33 my $checker_spec = $self->{'checkers'}->[$i];
156 21         563 my ($checker, @checker_args) = @{$checker_spec};
  21         102  
157              
158 21 100       92 unless( $checker->[0]->($val, @checker_args ) ) {
159            
160 10 100       20 if( $do_trace ) {
161 5 100       13 push @{$self->{'checkers_not_passed'}}, $i unless $self->{'at_least_one'};
  4         10  
162 5         15 next;
163             } else {
164 5 100       32 return 0 unless $self->{'at_least_one'};
165             }
166             }
167              
168 12 100       26 if( $do_trace ) {
169 1 50       4 push @{$self->{'checkers_not_passed'}}, $i if $self->{'at_least_one'};
  1         3  
170             } else {
171 11 100       43 return 1 if $self->{'at_least_one'}; # at least one checker has passed
172             }
173             }
174              
175 11 100       24 if( $do_trace ) {
176 2 100 66     7 $self->{'at_least_one'} && @{$self->{'checkers_not_passed'}} > 0 && return 1;
  1         11  
177 1 50       3 @{$self->{'checkers_not_passed'}} > 0 && return 0;
  1         8  
178 0         0 return 1;
179             }
180 9 50       62 return $self->{'at_least_one'} ? 0 : 1; # all checkers has passed or no one
181             }
182              
183              
184             =head2 print_trace( [$format] )
185              
186             Print trace of variable checking.
187             C specifies format string of trace messages.
188             Recognizes the following macro:
189              
190             =over 4
191              
192             =item %name%
193              
194             Replaced by checker's name.
195              
196             =item %args%
197              
198             Replaced by checker's arguments.
199              
200             =item %desc%
201              
202             Replaced by checker's description.
203              
204             =item %result%
205              
206             Replaced by 'passed' or 'failed'.
207              
208             =back
209              
210             Default format string is C<"Checker %name%(%args%) - %desc% ... %result%">.
211              
212             =cut
213              
214             sub print_trace
215             {
216 2     2 1 5 my $self = shift;
217 2   50     11 my $format = shift || 'Checker %name%(%args%) - %desc% ... %result%';
218              
219 2 50       2 if( @{$self->{'checkers_not_passed'}} == 0 ) {
  2         8  
220 0         0 carp 'no trace info, may be you forgot to make trace via is_valid whith trace flag enabled', "\n";
221             } else {
222 2 100       8 my $res_str = $self->{'at_least_one'} ? 'passed' : 'failed';
223 2 100       9 my $output = $self->{'at_least_one'} ? \&_print : \&_warn;
224 2         2 foreach ( @{$self->{'checkers_not_passed'}} ) {
  2         5  
225              
226 2         4 my $checker_spec = $self->{'checkers'}->[$_];
227 2         5 my ($checker, @checker_args) = @{$checker_spec};
  2         4  
228 2         7 my ($name, $desc, $args) = (
229             $checker->[1],
230             $checker->[2],
231             join ';', @checker_args
232             );
233              
234 2         3 my $msg = $format;
235 2         12 $msg =~ s/%name%/$name/;
236 2         8 $msg =~ s/%desc%/$desc/;
237 2         6 $msg =~ s/%args%/$args/;
238 2         6 $msg =~ s/%result%/$res_str/;
239 2         11 $output->( "$msg\n") ;
240             }
241             }
242             }
243              
244              
245             =head1 AUTHOR
246              
247             Fedor Semenov, C<< >>
248              
249             =head1 BUGS
250              
251             Please report any bugs or feature requests to C, or through
252             the web interface at L. I will be notified, and then you'll
253             automatically be notified of progress on your bug as I make changes.
254              
255             =head1 SUPPORT
256              
257             You can find documentation for this module with the perldoc command.
258              
259             perldoc Validator::Var
260              
261              
262             You can also look for information at:
263              
264             =over 4
265              
266             =item * RT: CPAN's request tracker (report bugs here)
267              
268             L
269              
270             =item * AnnoCPAN: Annotated CPAN documentation
271              
272             L
273              
274             =item * CPAN Ratings
275              
276             L
277              
278             =item * Search CPAN
279              
280             L
281              
282             =back
283              
284              
285             =head1 ACKNOWLEDGEMENTS
286              
287              
288             =head1 LICENSE AND COPYRIGHT
289              
290             Copyright 2011 Fedor Semenov.
291              
292             This program is free software; you can redistribute it and/or modify it
293             under the terms of either: the GNU General Public License as published
294             by the Free Software Foundation; or the Artistic License.
295              
296             See http://dev.perl.org/licenses/ for more information.
297              
298              
299             =cut
300              
301             1; # End of Validator::Var