File Coverage

blib/lib/Kossy/Validator.pm
Criterion Covered Total %
statement 95 104 91.3
branch 38 44 86.3
condition 12 17 70.5
subroutine 11 12 91.6
pod 0 1 0.0
total 156 178 87.6


line stmt bran cond sub pod time code
1             package Kossy::Validator;
2              
3 2     2   171146 use 5.008005;
  2         8  
  2         88  
4 2     2   13 use strict;
  2         5  
  2         62  
5 2     2   21 use warnings;
  2         2  
  2         59  
6 2     2   1696 use Hash::MultiValue;
  2         3073  
  2         3228  
7              
8             our $VERSION = "0.01";
9              
10             our %VALIDATOR = (
11             NOT_NULL => sub {
12             my ($req,$val) = @_;
13             return if not defined($val);
14             return if $val eq "";
15             return 1;
16             },
17             CHOICE => sub {
18             my ($req, $val, @args) = @_;
19             for my $c (@args) {
20             if ($c eq $val) {
21             return 1;
22             }
23             }
24             return;
25             },
26             INT => sub {
27             my ($req,$val) = @_;
28             return if not defined($val);
29             $val =~ /^\-?[\d]+$/;
30             },
31             UINT => sub {
32             my ($req,$val) = @_;
33             return if not defined($val);
34             $val =~ /^\d+$/;
35             },
36             NATURAL => sub {
37             my ($req,$val) = @_;
38             return if not defined($val);
39             $val =~ /^\d+$/ && $val > 0;
40             },
41             FLOAT => sub {
42             my ($req,$val) = @_;
43             return if not defined($val);
44             $val =~ /^\-?(\d+\.?\d*|\.\d+)(e[+-]\d+)?$/;
45             },
46             DOUBLE => sub {
47             my ($req,$val) = @_;
48             return if not defined($val);
49             $val =~ /^\-?(\d+\.?\d*|\.\d+)(e[+-]\d+)?$/;
50             },
51             REAL => sub {
52             my ($req,$val) = @_;
53             return if not defined($val);
54             $val =~ /^\-?(\d+\.?\d*|\.\d+)(e[+-]\d+)?$/;
55             },
56             '@SELECTED_NUM' => sub {
57             my ($req,$vals,@args) = @_;
58             my ($min,$max) = @args;
59             scalar(@$vals) >= $min && scalar(@$vals) <= $max
60             },
61             '@SELECTED_UNIQ' => sub {
62             my ($req,$vals) = @_;
63             my %vals;
64             $vals{$_} = 1 for @$vals;
65             scalar(@$vals) == scalar keys %vals;
66             },
67             );
68              
69             sub check {
70 18     18 0 34398 my $class = shift;
71              
72 18         22 my $req = shift;
73 18   50     44 my $rule = shift || [];
74              
75 18         19 my @errors;
76 18         89 my $valid = Hash::MultiValue->new;
77              
78 18         482 for ( my $i=0; $i < @$rule; $i = $i+2 ) {
79 21         88 my $param = $rule->[$i];
80 21         22 my $constraints;
81 21         22 my $param_name = $param;
82 21         40 $param_name =~ s!^@!!;
83 21         65 my @vals = $req->param($param_name);
84 21 100       3043 my $vals = ( $param =~ m!^@! ) ? \@vals : [$vals[-1]];
85              
86 21 100 66     124 if ( ref($rule->[$i+1]) && ref($rule->[$i+1]) eq 'HASH' ) {
87 5 100 100     27 if ( $param !~ m!^@! && !$VALIDATOR{NOT_NULL}->($req,$vals->[0]) && exists $rule->[$i+1]->{default} ) {
      66        
88 2         4 my $default = $rule->[$i+1]->{default};
89 2 100 66     14 $default = $default->() if ref($default) && ref($default) eq 'CODE';
90 2         7 $vals = [$default];
91             }
92 5         10 $constraints = $rule->[$i+1]->{rule};
93             }
94             else {
95 16         72 $constraints = $rule->[$i+1];
96             }
97              
98 21         24 my $error;
99 21         42 PARAM_CONSTRAINT: for my $constraint ( @$constraints ) {
100 29 100       72 if ( ref($constraint->[0]) eq 'ARRAY' ) {
    100          
101 11         15 my @constraint = @{$constraint->[0]};
  11         25  
102 11         19 my $constraint_name = shift @constraint;
103 11 100 66     36 if ( ref($constraint_name) && ref($constraint_name) eq 'CODE' ) {
104 2         5 for my $val ( @$vals ) {
105 3 100       13 if ( !$constraint_name->($req, $val, @constraint) ) {
106 2         15 push @errors, { param => $param_name, message => $constraint->[1] };
107 2         3 $error=1;
108 2         5 last PARAM_CONSTRAINT;
109             }
110             }
111 0         0 next PARAM_CONSTRAINT;
112             }
113 9 50       20 die "constraint:$constraint_name not found" if ! exists $VALIDATOR{$constraint_name};
114 9 100       20 if ( $constraint_name =~ m!^@! ) {
115 2 100       7 if ( !$VALIDATOR{$constraint_name}->($req,$vals,@constraint) ) {
116 1         4 push @errors, { param => $param_name, message => $constraint->[1] };
117 1         3 $error=1;
118 1         2 last PARAM_CONSTRAINT;
119             }
120             }
121             else {
122 7         12 for my $val ( @$vals ) {
123 9 100       25 if ( !$VALIDATOR{$constraint_name}->($req,$val,@constraint) ) {
124 3         10 push @errors, { param => $param_name, message => $constraint->[1] };
125 3         4 $error=1;
126 3         6 last PARAM_CONSTRAINT;
127             }
128             }
129             }
130             }
131             elsif ( ref($constraint->[0]) eq 'CODE' ) {
132 1         4 for my $val ( @$vals ) {
133 1 50       5 if ( !$constraint->[0]->($req, $val) ) {
134 1         9 push @errors, { param => $param_name, message => $constraint->[1] };
135 1         2 $error=1;
136 1         4 last PARAM_CONSTRAINT;
137             }
138             }
139             }
140             else {
141 17 50       46 die "constraint:".$constraint->[0]." not found" if ! exists $VALIDATOR{$constraint->[0]};
142 17 100       33 if ( $constraint->[0] =~ m!^@! ) {
143 1 50       4 if ( !$VALIDATOR{$constraint->[0]}->($req,$vals) ) {
144 1         5 push @errors, { param => $param_name, message => $constraint->[1] };
145 1         2 $error=1;
146 1         2 last PARAM_CONSTRAINT;
147             }
148             }
149             else {
150 16         25 for my $val ( @$vals ) {
151 19 100       42 if ( !$VALIDATOR{$constraint->[0]}->($req, $val) ) {
152 4         15 push @errors, { param => $param_name, message => $constraint->[1] };
153 4         4 $error=1;
154 4         10 last PARAM_CONSTRAINT;
155             }
156             }
157             }
158             }
159             }
160 21 100       94 $valid->add($param_name,@$vals) unless $error;
161             }
162            
163 18         256 Kossy::Validator::Result->new(\@errors,$valid);
164             }
165              
166             package Kossy::Validator::Result;
167              
168 2     2   16 use strict;
  2         4  
  2         68  
169 2     2   10 use warnings;
  2         4  
  2         723  
170              
171             sub new {
172 18     18   23 my $class = shift;
173 18         18 my $errors = shift;
174 18         18 my $valid = shift;
175 18         87 bless {errors=>$errors,valid=>$valid}, $class;
176             }
177              
178             sub has_error {
179 18     18   97 my $self = shift;
180 18 100       19 return 1 if @{$self->{errors}};
  18         81  
181 7         35 return;
182             }
183              
184             sub messages {
185 37     37   59 my $self = shift;
186 37         65 my @errors = map { $_->{message} } @{$self->{errors}};
  26         78  
  37         78  
187 37         219 \@errors;
188             }
189              
190             sub errors {
191 0     0   0 my $self = shift;
192 0         0 my %errors = map { $_->{param} => $_->{message} } @{$self->{errors}};
  0         0  
  0         0  
193 0         0 \%errors;
194             }
195              
196             sub valid {
197 21     21   1255 my $self = shift;
198 21 50       73 if ( @_ == 2 ) {
    50          
199 0         0 $self->{valid}->add(@_);
200 0         0 return $_[1];
201             }
202             elsif ( @_ == 1 ) {
203 21 100       103 return $self->{valid}->get($_[0]) if ! wantarray;
204 2         8 return $self->{valid}->get_all($_[0]);
205             }
206 0           $self->{valid};
207             }
208              
209              
210             1;
211             __END__