File Coverage

blib/lib/MongoDBx/Tiny/Validator.pm
Criterion Covered Total %
statement 18 77 23.3
branch 0 18 0.0
condition 0 19 0.0
subroutine 6 14 42.8
pod 8 8 100.0
total 32 136 23.5


line stmt bran cond sub pod time code
1             package MongoDBx::Tiny::Validator;
2 1     1   1644 use strict;
  1         2  
  1         34  
3 1     1   6 use warnings;
  1         2  
  1         34  
4              
5             =head1 NAME
6              
7             MongoDBx::Tiny::Validator - validation on insert and update.
8              
9             =cut
10              
11 1     1   6 use MongoDBx::Tiny::Util;
  1         2  
  1         91  
12 1     1   8 use Params::Validate qw(:all);
  1         23  
  1         277  
13 1     1   7 use Carp qw(confess);
  1         1  
  1         48  
14 1     1   6 use Data::Dumper;
  1         2  
  1         904  
15              
16             =head1 SUBROUTINES/METHODS
17              
18             =head2 new
19              
20             $validator = MongoDBx::Tiny::Validator->new(
21             $collection_name,
22             $document,
23             $tiny,
24             );
25              
26             =cut
27              
28             sub new {
29 0     0 1   my $class = shift;
30 0   0       my $c_name = shift || confess q/no collection name/;
31 0   0       my $document = shift || confess q/no document/;
32 0   0       my $tiny = shift || confess q/no tiny/;
33            
34 0           return bless {
35             document => $document,
36             collection_name => $c_name,
37             tiny => $tiny,
38             errors => [],
39             }, $class;
40             }
41              
42             =head2 document, collection_name, tiny
43              
44             # alias
45             $document = $validator->document;
46             $collection_name = $validator->collection_name;
47             $tiny = $validator->tiny;
48              
49             =cut
50              
51 0     0 1   sub document { shift->{document} }
52              
53 0     0 1   sub collection_name { shift->{collection_name} }
54              
55 0     0 1   sub tiny { shift->{tiny} }
56              
57             =head2 has_error
58              
59             $validator->has_error && die;
60              
61             =cut
62              
63 0     0 1   sub has_error { @{shift->{errors}} }
  0            
64              
65             =head2 set_error
66              
67             $validator->set_error(
68             $name => [
69             'error-code','message',
70             ]
71             );
72              
73             =cut
74              
75             sub set_error {
76 0     0 1   my $self = shift;
77 0           validate_pos(
78             @_,
79             1,
80             { type => ARRAYREF }
81             );
82 0           my $field = shift;
83 0           my $error = shift;
84 0           my ($code,$message) = @{$error};
  0            
85              
86 0   0       my %error = (
      0        
87             collection => $self->collection_name,
88             field => $field,
89             code => $code || 'nocode',
90             message => $message || (sprintf "fail: %s",$code)
91             );
92 0           push @{$self->{errors}},\%error;
  0            
93             }
94              
95             =head2 errors
96              
97             # erros: [{ field => 'field1', code => 'errorcode', message => 'message1' },,,]
98             @erros = $validator->erros;
99            
100             @fields = $validator->errors('field');
101             @error_code = $validator->errors('code');
102             @error_message = $validator->errors('message');
103              
104             =cut
105              
106             sub errors {
107 0     0 1   my $self = shift;
108 0           my $field = shift; # list field(field,code,message)
109 0 0         if ($field) {
110 0           return map { $_->{$field} } @{$self->{errors}};
  0            
  0            
111             }
112 0 0         return wantarray ? @{$self->{errors}} : $self->{errors};
  0            
113             }
114              
115             =head2 check
116              
117             # no_validate: bool
118             # state: [insert,update]
119             $validator->check($opt);
120              
121             =cut
122              
123             sub check {
124 0     0 1   my $self = shift;
125 0           my $opt = shift;
126              
127 0 0         return $self if $opt->{no_validate};
128              
129 0   0       my $c_class = util_document_class($self->collection_name, ref $self->tiny || $self->tiny );
130 0           my $document = $self->document;
131 0           my $field = $c_class->field;
132              
133 0           my $all_fields = { map { $_ => 1 } $field->list };
  0            
134 0           my @fail_fields = grep { ! $all_fields->{$_} } keys %{$document};
  0            
  0            
135 0           for (@fail_fields) {
136 0           $self->set_error(
137             $_ => ['not_field', (sprintf "%s is not field",$_)]
138             );
139             }
140              
141 0 0         if ($opt->{state} eq 'insert') {
142              
143 0           for my $name ($field->list('REQUIRED')) {
144 0 0         unless (exists $document->{$name}) {
145 0           $self->set_error(
146             $name => [
147             'required',(sprintf "%s is required",$name)
148             ]
149             );
150             }
151             }
152              
153 0           for my $name ($field->list) {
154 0 0         unless (exists $document->{$name}) {
155 0           $document->{$name} = undef;
156             }
157             }
158             }
159              
160 0           for my $name (keys %$document) {
161 0 0         for my $attr ( @{ $field->get($name) || [] } ) {
  0            
162 0           my $func = $attr->{callback};
163 0           my ($status,$ret) = $func->($document->{$name}, $self->tiny, $opt);
164 0   0       $ret ||= {};
165 0           validate_with(
166             params => $ret,
167             spec => {
168             message => 0,
169             target => 0,
170             }
171             );
172              
173 0 0         if (!$status) {
174 0           $self->set_error(
175             $name => [$attr->{name},$ret->{message}]
176             )
177             } else {
178 0 0         $document->{$name} = $ret->{target} if defined $ret->{target};
179             }
180             }
181             }
182 0           $self->{document} = $document;
183 0           return $self;
184             }
185              
186             1;
187             __END__
188              
189             =head1 AUTHOR
190              
191             Naoto ISHIKAWA, C<< <toona at seesaa.co.jp> >>
192              
193             =head1 LICENSE AND COPYRIGHT
194              
195             Copyright 2013 Naoto ISHIKAWA.
196              
197             This program is free software; you can redistribute it and/or modify it
198             under the terms of either: the GNU General Public License as published
199             by the Free Software Foundation; or the Artistic License.
200              
201             See http://dev.perl.org/licenses/ for more information.
202              
203              
204             =cut