File Coverage

blib/lib/MVC/Neaf/X/Form/Wildcard.pm
Criterion Covered Total %
statement 44 45 97.7
branch 8 12 66.6
condition n/a
subroutine 8 8 100.0
pod 3 3 100.0
total 63 68 92.6


line stmt bran cond sub pod time code
1             package MVC::Neaf::X::Form::Wildcard;
2              
3 3     3   70215 use strict;
  3         14  
  3         89  
4 3     3   13 use warnings;
  3         6  
  3         144  
5             our $VERSION = '0.29';
6              
7             =head1 NAME
8              
9             MVC::Neaf::X::Form::Wildcard - A special case form with unforeknown fields
10              
11             =head1 SYNOPSIS
12              
13             use MVC::Neaf::X::Form::Wildcard;
14              
15             # once during application setup phase
16             my $form = MVC::Neaf::X::Form::Wildcard->new(
17             [ [ qr/name\d+/ => qr/...*/ ], ... ] );
18              
19             # much later, multiple times
20             my $checked = $form->validate( {
21             name1 => 'foo',
22             surname2 => 'bar',
23             name5 => 'o'
24             } );
25              
26             $checked->fields; # ( 'name1', 'name5' )
27             # ONLY the matched fields
28             $checked->is_valid; # false
29             # because of next line
30             $checked->error; # { name5 => 'BAD_FORMAT' }
31              
32             $checked->data; # { name1 => 'foo' }
33             # Data that passed validation
34             $checked->raw; # { name1 => 'foo', name5 => 'o' }
35             # Semi-good data to send back to user for amendment,
36             # if needed
37              
38             # Note that surname2 did NOT affect anything at all.
39              
40             =head1 DESCRIPTION
41              
42             This module provides simple yet powerful validation method for plain hashes
43             in cases where the fields are not known beforehand.
44              
45             The validation rules come as tuples. A tuple containes name validation regexp,
46             value validation regexp, and possibly other fields (not implemented yet).
47              
48             All hash keys are filtered through name rules. In case of match, all other
49             rules are applied, resulting in either matching or non-matching field
50             that ends up in C or C hashes, respectively.
51              
52             A field that doesn't match anything is let through.
53              
54             =cut
55              
56 3     3   506 use parent qw(MVC::Neaf::X::Form);
  3         298  
  3         16  
57 3     3   194 use MVC::Neaf::X::Form::Data;
  3         7  
  3         62  
58 3     3   15 use MVC::Neaf::Util qw(rex);
  3         6  
  3         1339  
59              
60             =head2 new ( \@rules )
61              
62             Create a new validator from rules.
63              
64             More options may follow in the future, but now there are none.
65              
66             =cut
67              
68             sub new {
69 2     2 1 111 my ($class, $rules) = @_;
70              
71 2 50       8 $class->my_croak("Rule set must be arrayref")
72             unless ref $rules eq 'ARRAY';
73              
74 2         5 my $self = bless {}, $class;
75 2         8 foreach (@$rules) {
76 2         17 $self->add_rule( $_ );
77             };
78              
79 2         6 return $self;
80             };
81              
82             =head2 add_rule( \@tuple )
83              
84             =head2 add_rule( \%params )
85              
86              
87             =cut
88              
89             sub add_rule {
90 2     2 1 6 my ($self, $in) = @_;
91              
92 2         4 my $rule;
93 2 50       8 if (ref $in eq 'ARRAY') {
94 2         6 $rule = { re_name => $in->[0], re_value => $in->[1] };
95             } else {
96             # TODO 0.30 validate fields?
97 0         0 $rule = { %$in };
98             };
99              
100             $self->_croak( "re_name must be present in validation rule" )
101 2 50       9 unless $rule->{re_name};
102             $self->_croak( "re_value must be present in validation rule" )
103 2 50       6 unless $rule->{re_value};
104              
105 2         8 $rule->{re_name} = rex $rule->{re_name};
106 2         7 $rule->{re_value} = rex $rule->{re_value};
107              
108 2         6 push @{ $self->{rules} }, $rule;
  2         18  
109              
110 2         6 return $self;
111             };
112              
113             =head2 validate( \%user_input )
114              
115             Returns a L object with keys of \%user_input,
116             filtered by the rules.
117              
118             =cut
119              
120             sub validate {
121 2     2 1 13 my ($self, $input) = @_;
122              
123 2         4 my( %data, %error, %raw );
124 2         8 KEY: foreach my $key (keys %$input) {
125 7         12 RULE: foreach my $rule( @{ $self->{rules} } ) {
  7         13  
126 7 100       52 $key =~ $rule->{re_name} or next RULE;
127              
128 5         13 $raw{$key} = $input->{$key};
129 5 100       31 if ($raw{$key} =~ $rule->{re_value}) {
130 2         5 $data{$key} = $raw{$key};
131             } else {
132 3         6 $error{$key} = 'REGEX_NO_MATCH';
133             };
134              
135 5         23 next KEY;
136             };
137             };
138              
139 2         61 return MVC::Neaf::X::Form::Data->new(
140             data => \%data,
141             error => \%error,
142             raw => \%raw,
143             );
144             };
145              
146             =head1 LICENSE AND COPYRIGHT
147              
148             This module is part of L suite.
149              
150             Copyright 2016-2023 Konstantin S. Uvarin C.
151              
152             This program is free software; you can redistribute it and/or modify it
153             under the terms of either: the GNU General Public License as published
154             by the Free Software Foundation; or the Artistic License.
155              
156             See L for more information.
157              
158             =cut
159              
160             1;