File Coverage

blib/lib/HTML/FormFu/ObjectUtil.pm
Criterion Covered Total %
statement 155 164 94.5
branch 47 62 75.8
condition 13 20 65.0
subroutine 28 31 90.3
pod 0 11 0.0
total 243 288 84.3


line stmt bran cond sub pod time code
1             package HTML::FormFu::ObjectUtil;
2              
3 401     401   1533 use strict;
  401         538  
  401         14306  
4 401     401   2334 use warnings;
  401         450  
  401         17524  
5              
6             our $VERSION = '2.05'; # VERSION
7              
8 401     401   1367 use Exporter qw( import );
  401         2182  
  401         12709  
9              
10 401         23002 use HTML::FormFu::Util qw(
11             _parse_args require_class
12             _get_elements
13             _filter_components _merge_hashes
14 401     401   2284 );
  401         1351  
15 401     401   148817 use Clone ();
  401         777550  
  401         11750  
16 401     401   160222 use Config::Any;
  401         2575457  
  401         16722  
17 401     401   177110 use Data::Visitor::Callback;
  401         23193456  
  401         14015  
18 401     401   2796 use File::Spec;
  401         549  
  401         13202  
19 401     401   1501 use Scalar::Util qw( refaddr weaken blessed );
  401         1434  
  401         26552  
20 401     401   1740 use Carp qw( croak );
  401         2411  
  401         607404  
21              
22             our @EXPORT_OK = ( qw(
23             deflator
24             load_config_file load_config_filestem
25             form
26             get_parent
27             insert_before insert_after
28             clone
29             name
30             stash
31             constraints_from_dbic
32             parent
33             nested_name nested_names
34             remove_element
35             _string_equals _object_equals
36             _load_file
37             ),
38             );
39              
40             sub load_config_file {
41 140     140 0 1033 my ( $self, @files ) = @_;
42              
43 140         245 my $use_stems = 0;
44              
45 140         569 return _load_config( $self, $use_stems, @files );
46             }
47              
48             sub load_config_filestem {
49 1     1 0 8 my ( $self, @files ) = @_;
50              
51 1         2 my $use_stems = 1;
52              
53 1         4 return _load_config( $self, $use_stems, @files );
54             }
55              
56             sub _load_config {
57 141     141   292 my ( $self, $use_stems, @filenames ) = @_;
58              
59 141 100 66     1013 if ( scalar @filenames == 1 && ref $filenames[0] eq 'ARRAY' ) {
60 1         3 @filenames = @{ $filenames[0] };
  1         3  
61             }
62              
63 141         633 my $config_callback = $self->config_callback;
64 141         205 my $data_visitor;
65              
66 141 100       415 if ( defined $config_callback ) {
67 2         77 $data_visitor = Data::Visitor::Callback->new( %$config_callback,
68             ignore_return_values => 1, );
69             }
70              
71 141 100       915 my $config_any_arg = $use_stems ? 'stems' : 'files';
72 141 100       379 my $config_any_method = $use_stems ? 'load_stems' : 'load_files';
73              
74 141         188 my @config_file_path;
75              
76 141 100       535 if ( my $config_file_path = $self->config_file_path ) {
77              
78 4 100       12 if ( ref $config_file_path eq 'ARRAY' ) {
79 3         11 push @config_file_path, @$config_file_path;
80             }
81             else {
82 1         3 push @config_file_path, $config_file_path;
83             }
84             }
85             else {
86 137         1503 push @config_file_path, File::Spec->curdir;
87             }
88              
89 141         484 for my $file (@filenames) {
90 142         210 my $loaded = 0;
91 142         612 my $fullpath;
92              
93 142         10378 foreach my $config_file_path (@config_file_path) {
94              
95 149 50 33     2046 if ( defined $config_file_path
96             && !File::Spec->file_name_is_absolute($file) )
97             {
98 149         1989 $fullpath = File::Spec->catfile( $config_file_path, $file );
99             }
100             else {
101 0         0 $fullpath = $file;
102             }
103              
104 149         2630 my $config = Config::Any->$config_any_method( {
105             $config_any_arg => [$fullpath],
106             use_ext => 1,
107             driver_args => { General => { -UTF8 => 1 }, },
108             } );
109              
110 149 100       1378966 next if !@$config;
111              
112 141         317 $loaded = 1;
113 141         214 my ( $filename, $filedata ) = %{ $config->[0] };
  141         562  
114              
115 141         574 _load_file( $self, $data_visitor, $filedata );
116 141         1610 last;
117             }
118 142 100       805 croak "config file '$file' not found" if !$loaded;
119             }
120              
121 140         1204 return $self;
122             }
123              
124             sub _load_file {
125 141     141   267 my ( $self, $data_visitor, $data ) = @_;
126              
127 141 100       500 if ( defined $data_visitor ) {
128 2         12 $data_visitor->visit($data);
129             }
130              
131 141 100       5565 for my $config ( ref $data eq 'ARRAY' ? @$data : $data ) {
132 142         4171 $self->populate( Clone::clone($config) );
133             }
134              
135 141         362 return;
136             }
137              
138             sub form {
139 29767     29767 0 23452 my ($self) = @_;
140              
141             # micro optimization! this method's called a lot, so access
142             # parent hashkey directly, instead of calling parent()
143 29767         48525 while ( defined( my $parent = $self->{parent} ) ) {
144 50876         72222 $self = $parent;
145             }
146              
147 29767         546429 return $self;
148             }
149              
150             sub clone {
151 2     2 0 402 my ($self) = @_;
152              
153 2         25 my %new = %$self;
154              
155 2         5 $new{_elements} = [ map { $_->clone } @{ $self->_elements } ];
  2         24  
  2         93  
156 2         9 $new{attributes} = Clone::clone( $self->attributes );
157 2         9 $new{tt_args} = Clone::clone( $self->tt_args );
158 2         10 $new{model_config} = Clone::clone( $self->model_config );
159              
160 2 50       11 if ( $self->can('_plugins') ) {
161 2         2 $new{_plugins} = [ map { $_->clone } @{ $self->_plugins } ];
  0         0  
  2         66  
162             }
163              
164             $new{languages}
165 2 50       48 = ref $self->languages
166             ? Clone::clone( $self->languages )
167             : $self->languages;
168              
169 2         6 $new{default_args} = $self->default_args;
170              
171 2         6 my $obj = bless \%new, ref $self;
172              
173 2         3 map { $_->parent($obj) } @{ $new{_elements} };
  2         5  
  2         5  
174              
175 2         5 return $obj;
176             }
177              
178             sub name {
179 111     111 0 2294 my $self = shift;
180              
181 111 50       171 croak 'cannot use name() as a setter' if @_;
182              
183 111         147 return $self->parent->name;
184             }
185              
186             sub nested_name {
187 1187     1187 0 1181 my $self = shift;
188              
189 1187 50       2071 croak 'cannot use nested_name() as a setter' if @_;
190              
191 1187         1904 return $self->parent->nested_name;
192             }
193              
194             sub nested_names {
195 0     0 0 0 my $self = shift;
196              
197 0 0       0 croak 'cannot use nested_names() as a setter' if @_;
198              
199 0         0 return $self->parent->nested_names;
200             }
201              
202             sub stash {
203 5125     5125 0 5306 my $self = shift;
204              
205 5125 100       10845 $self->{stash} = {} if not exists $self->{stash};
206 5125 100       12426 return $self->{stash} if !@_;
207              
208 3306 50       5946 my %attrs = ( @_ == 1 ) ? %{ $_[0] } : @_;
  3306         5587  
209              
210 3306         5324 $self->{stash}->{$_} = $attrs{$_} for keys %attrs;
211              
212 3306         4794 return $self;
213             }
214              
215             sub constraints_from_dbic {
216 2     2 0 61280 my ( $self, $source, $map ) = @_;
217              
218 2   100     10 $map ||= {};
219              
220 2         8 $source = _result_source($source);
221              
222 2         62 for my $col ( $source->columns ) {
223 8         645 _add_constraints( $self, $col, $source->column_info($col) );
224             }
225              
226 2         9 for my $col ( keys %$map ) {
227 1         3 my $source = _result_source( $map->{$col} );
228              
229 1         68 _add_constraints( $self, $col, $source->column_info($col) );
230             }
231              
232 2         8 return $self;
233             }
234              
235             sub _result_source {
236 3     3   6 my ($source) = @_;
237              
238 3 100       12 if ( blessed $source ) {
239 1         4 $source = $source->result_source;
240             }
241              
242 3         116 return $source;
243             }
244              
245             sub _add_constraints {
246 9     9   279 my ( $self, $col, $info ) = @_;
247              
248 9 100       37 return if !defined $self->get_field($col);
249              
250 7 50       22 return if !defined $info->{data_type};
251              
252 7         18 my $type = lc $info->{data_type};
253              
254 7 100 66     83 if ( $type =~ /(char|text|binary)\z/ && defined $info->{size} ) {
    100 33        
    50          
255              
256             # char, varchar, *text, binary, varbinary
257 3         9 _add_constraint_max_length( $self, $col, $info );
258             }
259             elsif ( $type =~ /int/ ) {
260 2         9 _add_constraint_integer( $self, $col, $info );
261              
262 2 50       13 if ( $info->{extra}{unsigned} ) {
263 2         7 _add_constraint_unsigned( $self, $col, $info );
264             }
265              
266             }
267             elsif ( $type =~ /enum|set/ && defined $info->{extra}{list} ) {
268 2         9 _add_constraint_set( $self, $col, $info );
269             }
270             }
271              
272             sub _add_constraint_max_length {
273 3     3   4 my ( $self, $col, $info ) = @_;
274              
275             $self->constraint( {
276             type => 'MaxLength',
277             name => $col,
278             max => $info->{size},
279 3         27 } );
280             }
281              
282             sub _add_constraint_integer {
283 2     2   5 my ( $self, $col, $info ) = @_;
284              
285 2         14 $self->constraint( {
286             type => 'Integer',
287             name => $col,
288             } );
289             }
290              
291             sub _add_constraint_unsigned {
292 2     2   4 my ( $self, $col, $info ) = @_;
293              
294 2         15 $self->constraint( {
295             type => 'Range',
296             name => $col,
297             min => 0,
298             } );
299             }
300              
301             sub _add_constraint_set {
302 2     2   9 my ( $self, $col, $info ) = @_;
303              
304             $self->constraint( {
305             type => 'Set',
306             name => $col,
307             set => $info->{extra}{list},
308 2         18 } );
309             }
310              
311             sub parent {
312 16470     16470 0 15066 my $self = shift;
313              
314 16470 100       23225 if (@_) {
315 2468         3644 $self->{parent} = shift;
316              
317 2468         6587 weaken( $self->{parent} );
318              
319 2468         4547 return $self;
320             }
321              
322 14002         58209 return $self->{parent};
323             }
324              
325             sub get_parent {
326 70     70 0 56 my $self = shift;
327              
328 70 100       117 return $self->parent
329             if !@_;
330              
331 69         125 my %args = _parse_args(@_);
332              
333 69         114 while ( defined( my $parent = $self->parent ) ) {
334              
335 140         168 for my $name ( keys %args ) {
336 140         87 my $value;
337              
338 140 100 66     3171 if ( $parent->can($name)
      100        
339             && defined( $value = $parent->$name )
340             && $value eq $args{$name} )
341             {
342 67         216 return $parent;
343             }
344             }
345              
346 73         116 $self = $parent;
347             }
348              
349 2         7 return;
350             }
351              
352             sub _string_equals {
353 0     0     my ( $a, $b ) = @_;
354              
355 0 0         return blessed($b)
356             ? ( refaddr($a) eq refaddr($b) )
357             : ( "$a" eq "$b" );
358             }
359              
360             sub _object_equals {
361 0     0     my ( $a, $b ) = @_;
362              
363 0 0         return blessed($b)
364             ? ( refaddr($a) eq refaddr($b) )
365             : undef;
366             }
367              
368             1;