File Coverage

blib/lib/HTML/FormFu/Role/FormAndBlockMethods.pm
Criterion Covered Total %
statement 24 95 25.2
branch 3 40 7.5
condition 2 25 8.0
subroutine 7 16 43.7
pod 0 2 0.0
total 36 178 20.2


line stmt bran cond sub pod time code
1 404     404   214929 use strict;
  404         1093  
  404         21343  
2              
3             package HTML::FormFu::Role::FormAndBlockMethods;
4             # ABSTRACT: role for form and block methods
5             $HTML::FormFu::Role::FormAndBlockMethods::VERSION = '2.07';
6 404     404   2474 use Moose::Role;
  404         923  
  404         2697  
7              
8 404     404   2088741 use HTML::FormFu::Util qw( _merge_hashes );
  404         1072  
  404         20793  
9 404     404   2655 use Carp qw( croak );
  404         917  
  404         22881  
10 404     404   2808 use List::Util 1.33 qw( none );
  404         10464  
  404         566076  
11              
12             sub default_args {
13 2036     2036 0 6028 my ( $self, $defaults ) = @_;
14              
15 2036   100     10795 $self->{default_args} ||= {};
16              
17 2036 100       6527 if ($defaults) {
18              
19 111         487 my @valid_types = qw(
20             elements deflators
21             filters constraints
22             inflators validators
23             transformers output_processors
24             );
25              
26 111         397 for my $type ( keys %$defaults ) {
27             croak "not a valid type for default_args: '$type'"
28 131 50   429   932 if none { $type eq $_ } @valid_types;
  429         1099  
29             }
30              
31             $self->{default_args}
32 111         545 = _merge_hashes( $self->{default_args}, $defaults );
33             }
34              
35 2036         7255 return $self->{default_args};
36             }
37              
38             sub constraints_from_dbic {
39 0     0 0   my ( $self, $source, $map ) = @_;
40              
41 0 0 0       if ( 2 == @_ && 'ARRAY' eq ref $source ) {
42 0           ( $source, $map ) = @$source;
43             }
44              
45 0   0       $map ||= {};
46              
47 0           $source = _result_source($source);
48              
49 0           for my $col ( $source->columns ) {
50 0           _add_constraints( $self, $col, $source->column_info($col) );
51             }
52              
53 0           for my $col ( keys %$map ) {
54 0           my $source = _result_source( $map->{$col} );
55              
56 0           _add_constraints( $self, $col, $source->column_info($col) );
57             }
58              
59 0           return $self;
60             }
61              
62             sub _result_source {
63 0     0     my ($source) = @_;
64              
65 0 0         if ( blessed $source ) {
66 0           $source = $source->result_source;
67             }
68              
69 0           return $source;
70             }
71              
72             sub _add_constraints {
73 0     0     my ( $self, $col, $info ) = @_;
74              
75             # We need to ensure we're only using this Block's children,
76             # as far as 'nested_name' is concerned.
77             # But we can't use get_elements() in case the fields are in sub-Blocks
78             # that don't have 'nested_name' set.
79              
80 0           my $parent = $self;
81 0           my @parent_names;
82              
83 0           do {
84 0           my $nested_name = $parent->nested_name;
85 0 0 0       if ( defined $nested_name && length $nested_name ) {
86 0           push @parent_names, $nested_name;
87             }
88             } while ( $parent = $parent->parent );
89              
90 0           my $fields = $self->get_fields($col);
91 0 0         return if !@$fields;
92              
93 0 0         if (@parent_names) {
94 0           my $pre = join ".", reverse @parent_names;
95 0           @$fields = grep { $_->nested_name eq "$pre." . $_->name } @$fields;
  0            
96             }
97             else {
98 0           @$fields = grep { $_->nested_name eq $_->name } @$fields;
  0            
99             }
100              
101 0 0         return if !@$fields;
102              
103 0 0         return if !defined $info->{data_type};
104              
105 0           my $type = lc $info->{data_type};
106              
107 0 0 0       if ( $type =~ /(char|text|binary)\z/ && defined $info->{size} ) {
    0 0        
    0          
    0          
    0          
108              
109             # char, varchar, *text, binary, varbinary
110 0           _add_constraint_max_length( $self, $fields, $info );
111             }
112             elsif ( $type =~ /int/ ) {
113 0           _add_constraint_integer( $self, $fields, $info );
114              
115 0 0         if ( $info->{extra}{unsigned} ) {
116 0           _add_constraint_unsigned( $self, $fields, $info );
117             }
118             }
119             elsif ( $type =~ /enum|set/ && defined $info->{extra}{list} ) {
120 0           _add_constraint_set( $self, $fields, $info );
121             }
122             elsif ( $type =~ /bool/ ) {
123 0           _add_constraint_bool( $self, $fields, $info );
124             }
125             elsif ( $type =~ /decimal/ ) {
126 0           _add_constraint_decimal( $self, $fields, $info );
127             }
128             }
129              
130             sub _add_constraint_max_length {
131 0     0     my ( $self, $fields, $info ) = @_;
132              
133 0           map { $_->constraint( { type => 'MaxLength', max => $info->{size}, } ) }
  0            
134             @$fields;
135             }
136              
137             sub _add_constraint_integer {
138 0     0     my ( $self, $fields, $info ) = @_;
139              
140 0           map { $_->constraint( { type => 'Integer', } ) } @$fields;
  0            
141             }
142              
143             sub _add_constraint_unsigned {
144 0     0     my ( $self, $fields, $info ) = @_;
145              
146 0           map { $_->constraint( { type => 'Range', min => 0, } ) } @$fields;
  0            
147             }
148              
149             sub _add_constraint_set {
150 0     0     my ( $self, $fields, $info ) = @_;
151              
152 0           map { $_->constraint( { type => 'Set', set => $info->{extra}{list}, } ) }
  0            
153             @$fields;
154             }
155              
156             sub _add_constraint_bool {
157 0     0     my ( $self, $fields, $info ) = @_;
158              
159 0           map { $_->constraint( { type => 'Set', set => [ 0, 1 ] } ) } @$fields;
  0            
160             }
161              
162             sub _add_constraint_decimal {
163 0     0     my ( $self, $fields, $info ) = @_;
164              
165 0           my $size = $info->{size};
166 0           my $regex;
167              
168 0 0         if ( defined $size ) {
169 0 0 0       if ( 'ARRAY' eq ref $size && 2 == @$size ) {
    0 0        
    0          
    0          
170 0           my ( $i, $j ) = @$size;
171 0           $i -= $j;
172 0           $regex = qr/^ [0-9]{0,$i} (?: \. [0-9]{0,$j} )? \z/x;
173             }
174             elsif ( 'ARRAY' eq ref $size && 1 == @$size ) {
175 0           my ($i) = @$size;
176 0           $regex = qr/^ [0-9]{0,$i} \z/x;
177             }
178             elsif ( 0 == $size ) {
179 0           $regex = qr/^ [0-9]+ \z/x;
180             }
181             elsif ( $size =~ /^[0-9]+\z/ ) {
182 0           $regex = qr/^ [0-9]{0,$size} \z/x;
183             }
184             }
185              
186 0   0       $regex ||= qr/^ [0-9]+ (?: \. [0-9]+ )? \z/x;
187              
188 0           map { $_->constraint( { type => 'Regex', regex => $regex } ) } @$fields;
  0            
189             }
190              
191             1;
192              
193             __END__
194              
195             =pod
196              
197             =encoding UTF-8
198              
199             =head1 NAME
200              
201             HTML::FormFu::Role::FormAndBlockMethods - role for form and block methods
202              
203             =head1 VERSION
204              
205             version 2.07
206              
207             =head1 AUTHOR
208              
209             Carl Franks <cpan@fireartist.com>
210              
211             =head1 COPYRIGHT AND LICENSE
212              
213             This software is copyright (c) 2018 by Carl Franks.
214              
215             This is free software; you can redistribute it and/or modify it under
216             the same terms as the Perl 5 programming language system itself.
217              
218             =cut