File Coverage

blib/lib/Data/MuForm/Field.pm
Criterion Covered Total %
statement 335 380 88.1
branch 164 210 78.1
condition 36 60 60.0
subroutine 76 85 89.4
pod 11 70 15.7
total 622 805 77.2


line stmt bran cond sub pod time code
1             package Data::MuForm::Field;
2             # ABSTRACT: Base field package
3 93     93   47668 use Moo;
  93         130  
  93         444  
4 93     93   21987 use Types::Standard -types;
  93         444433  
  93         954  
5 93     93   256854 use Try::Tiny;
  93         20154  
  93         4829  
6 93     93   387 use Scalar::Util ('blessed', 'weaken');
  93         108  
  93         3720  
7 93     93   9831 use Data::Clone ('data_clone');
  93         25858  
  93         3351  
8 93     93   9056 use Data::MuForm::Localizer;
  93         162  
  93         2206  
9 93     93   10094 use Data::MuForm::Merge ('merge');
  93         131  
  93         245096  
10             with 'Data::MuForm::Common';
11              
12             has 'name' => ( is => 'rw', required => 1 );
13             has 'id' => ( is => 'rw', lazy => 1, builder => 'build_id' );
14             sub build_id {
15 82     82 1 6219 my $self = shift;
16 82 100 33     201 if ( my $meth = $self->get_method('build_id') ) {
    50          
17 3         11 return $meth->($self, @_);
18             }
19             elsif ( $self->form && $self->form->can('build_field_id') ) {
20 0         0 return $self->form->build_field_id($self);
21             }
22 79         2857 return $self->prefixed_name;
23             }
24             has 'prefixed_name' => ( is => 'rw', lazy => 1, builder => 'build_prefixed_name');
25             sub build_prefixed_name {
26 80     80 0 5368 my $self = shift;
27 80 50 33     1127 my $prefix = ( $self->form && $self->form->field_prefix ) ? $self->field_prefix. "." : '';
28 80         2204 return $prefix . $self->full_name;
29             }
30             has 'form' => ( is => 'rw', weak_ref => 1, predicate => 'has_form' );
31             has 'type' => ( is => 'ro', required => 1, default => 'Text' );
32             has 'default' => ( is => 'rw' );
33             has 'input' => ( is => 'rw', predicate => 'has_input', clearer => 'clear_input' );
34             has 'input_without_param' => ( is => 'rw', predicate => 'has_input_without_param' );
35             has 'value' => ( is => 'rw', predicate => 'has_value', clearer => 'clear_value' );
36             has 'init_value' => ( is => 'rw', predicate => 'has_init_value', clearer => 'clear_init_value' );
37             has 'no_value_if_empty' => ( is => 'rw' );
38             has 'input_param' => ( is => 'rw' );
39             has 'filled_from' => ( is => 'rw', clearer => 'clear_filled_from' );
40             has 'password' => ( is => 'rw', default => 0 );
41             has 'accessor' => ( is => 'rw', lazy => 1, builder => 'build_accessor' );
42             sub build_accessor {
43 443     443 0 18929 my $self = shift;
44 443         792 my $accessor = $self->name;
45 443 50       894 $accessor =~ s/^(.*)\.//g if ( $accessor =~ /\./ );
46 443         2123 return $accessor;
47             }
48             has 'custom' => ( is => 'rw' );
49             has 'parent' => ( is => 'rw', predicate => 'has_parent', weak_ref => 1 );
50             has 'source' => ( is => 'rw' );
51             has 'errors' => ( is => 'rw', isa => ArrayRef, default => sub {[]} );
52 663     663 0 12024 sub has_errors { my $self = shift; return scalar @{$self->errors}; }
  663         503  
  663         10639  
53 18     18 0 595 sub all_errors { my $self = shift; return @{$self->errors}; }
  18         15  
  18         278  
54 750     750 0 4250 sub clear_errors { $_[0]->{errors} = [] }
55       343 0   sub clear_error_fields { }
56              
57             # this is a permanent setting of active
58             has 'active' => ( is => 'rw', default => 1 );
59             # this is a temporary active set on the process call, cleared on clear_data
60             has '_active' => ( is => 'rw', predicate => '_has_active', clearer => '_clear_active' );
61 1     1 0 11 sub clear_inactive { $_[0]->active(1) }
62 0 0   0 1 0 sub inactive { return ( shift->active ? 0 : 1 ) }
63             sub is_active {
64 4969     4969 1 3492 my $self = shift;
65 4969 100       8058 return $self->_active if $self->_has_active;
66 4957         15284 return $self->active;
67             }
68       418 0   sub multiple { }
69 2     2 1 14 sub is_inactive { ! $_[0]->is_active }
70             has 'disabled' => ( is => 'rw', default => 0 );
71             has 'no_update' => ( is => 'rw', default => 0 );
72             has 'writeonly' => ( is => 'rw', default => 0 );
73             has 'is_contains' => ( is => 'rw' );
74             has 'apply' => ( is => 'rw', default => sub {[]} ); # for field defnitions
75 0     0 0 0 sub has_apply { return scalar @{$_[0]->{apply}} }
  0         0  
76             has 'base_apply' => ( is => 'rw', builder => 'build_base_apply' ); # for field classes
77 638     638 0 12166 sub build_base_apply {[]}
78 0     0 0 0 sub has_base_apply { return scalar @{$_[0]->{base_apply}} }
  0         0  
79             has 'trim' => ( is => 'rw', default => sub { *default_trim } );
80             sub default_trim {
81 525     525 0 573 my $value = shift;
82 525 100       798 return unless defined $value;
83 523 100       1721 my @values = ref $value eq 'ARRAY' ? @$value : ($value);
84 523         766 for (@values) {
85 561 100 100     1897 next if ref $_ or !defined;
86 478         840 s/^\s+//;
87 478         910 s/\s+$//;
88             }
89 523 100       1790 return ref $value eq 'ARRAY' ? \@values : $values[0];
90             }
91       2103 0   sub has_fields { } # compound fields will override
92             has 'methods' => ( is => 'rw', isa => HashRef, builder => 'build_methods', trigger => 1 );
93 642     642 0 18638 sub build_methods {{}}
94             sub _trigger_methods {
95 6     6   179 my ( $self, $new_methods ) = @_;
96 6         20 my $base_methods = $self->build_methods;
97 6         25 my $methods = merge($new_methods, $base_methods);
98 6         100 $self->{methods} = $methods;
99              
100             }
101             sub get_method {
102 1545     1545 0 1514 my ( $self, $meth_name ) = @_;
103 1545         6641 return $self->{methods}->{$meth_name};
104             }
105              
106             has 'validate_when_empty' => ( is => 'rw' );
107             has 'not_nullable' => ( is => 'rw' );
108       1094 0   sub is_repeatable {}
109       3 0   sub is_compound {}
110 128     128 0 1304 sub is_form {0}
111 289     289 0 753 sub no_fif {0}
112              
113             around BUILDARGS => sub {
114             my ( $orig, $class, %field_attr ) = @_;
115              
116             munge_field_attr(\%field_attr);
117              
118             return $class->$orig(%field_attr);
119             };
120              
121              
122             sub BUILD {
123 641     641 0 7009 my $self = shift;
124              
125 641 100       9698 if ( $self->form ) {
126             # To avoid memory cycles it needs to be weakened when
127             # it's set through a form.
128 593         27106 weaken($self->{localizer});
129 593         1888 weaken($self->{renderer});
130             }
131             else {
132             # Vivify. This would generally only happen in a standalone field, in tests.
133 48         5305 $self->localizer;
134 48         13453 $self->renderer;
135             }
136              
137 641         2526 $self->_install_methods;
138             }
139              
140             sub _install_methods {
141 641     641   680 my $self = shift;
142              
143 641 100       8913 if ( $self->form ) {
144 593         4075 my $suffix = $self->convert_full_name($self->full_name);
145 593         1916 foreach my $prefix ( 'validate', 'default' ) {
146 1186 100       21033 next if exists $self->methods->{$prefix};
147 1185         44973 my $meth_name = "${prefix}_$suffix";
148 1185 100       16917 if ( my $meth = $self->form->can($meth_name) ) {
149             my $wrap_sub = sub {
150 26     26   30 my $self = shift;
151 26         473 return $self->form->$meth($self);
152 19         175 };
153 19         128 $self->{methods}->{$prefix} = $wrap_sub;
154             }
155             }
156             }
157             }
158              
159              
160             sub fif {
161 427     427 1 6099 my $self = shift;
162 427 50       604 return unless $self->is_active;
163 427 50       914 return '' if $self->password;
164 427 100       1458 return $self->input if $self->has_input;
165 208 100       443 if ( $self->has_value ) {
166 122         306 my $value = $self->value;
167 122 100       330 $value = $self->transform_value_to_fif->($self, $value) if $self->has_transform_value_to_fif;
168 122         271 return $value;
169             }
170 86         379 return '';
171             }
172              
173              
174             sub full_name {
175 2033     2033 1 5113 my $field = shift;
176              
177 2033         4636 my $name = $field->name;
178 2033         1393 my $parent_name;
179             # field should always have a parent unless it's a standalone field test
180 2033 100       27027 if ( $field->parent ) {
181 2018         58007 $parent_name = $field->parent->full_name;
182             }
183 2033 100 100     12310 return $name unless defined $parent_name && length $parent_name;
184 550         1961 return $parent_name . '.' . $name;
185             }
186              
187             sub full_accessor {
188 0     0 1 0 my $field = shift;
189              
190 0         0 my $parent = $field->parent;
191 0 0       0 if( $field->is_contains ) {
192 0 0       0 return '' unless $parent;
193 0         0 return $parent->full_accessor;
194             }
195 0         0 my $accessor = $field->accessor;
196 0         0 my $parent_accessor;
197 0 0       0 if ( $parent ) {
198 0         0 $parent_accessor = $parent->full_accessor;
199             }
200 0 0 0     0 return $accessor unless defined $parent_accessor && length $parent_accessor;
201 0         0 return $parent_accessor . '.' . $accessor;
202             }
203              
204              
205             #====================
206             # Localization
207             #====================
208              
209             sub localize {
210 99     99 0 267 my ( $self, @message ) = @_;
211 99         1442 return $self->localizer->loc_($message[0]);
212             }
213              
214             has 'language' => ( is => 'rw', lazy => 1, builder => 'build_language' );
215 33     33 0 5863 sub build_language { 'en' }
216             has 'localizer' => (
217             is => 'rw', lazy => 1, builder => 'build_localizer',
218             );
219             sub build_localizer {
220 33     33 0 5287 my $self = shift;
221 33         357 return Data::MuForm::Localizer->new(
222             language => $self->language,
223             );
224             }
225              
226             #====================
227             # Rendering
228             #====================
229             has 'label' => ( is => 'rw', lazy => 1, builder => 'build_label' );
230             sub build_label {
231 101     101 1 8808 my $self = shift;
232 101 100       245 if ( my $meth = $self->get_method('build_label' ) ) {
233 1         3 return $meth->($self);
234             }
235 100         235 my $label = $self->name;
236 100         159 $label =~ s/_/ /g;
237 100         186 $label = ucfirst($label);
238 100         505 return $label;
239             }
240             sub loc_label {
241 99     99 0 1384 my $self = shift;
242 99         1363 return $self->localize($self->label);
243             }
244             has 'form_element' => ( is => 'rw', lazy => 1, builder => 'build_form_element' );
245 65     65 0 3981 sub build_form_element { 'input' }
246             has 'input_type' => ( is => 'rw', lazy => 1, builder => 'build_input_type' );
247 20     20 0 2431 sub build_input_type { 'text' }
248              
249             # could have everything in one big "pass to the renderer" hash?
250             has 'layout' => ( is => 'rw' );
251             has 'layout_group' => ( is => 'rw' );
252             has 'order' => ( is => 'rw', default => 0 );
253             has 'html5_input_type' => ( is => 'rw', predicate => 'has_html5_input_type' );
254              
255             sub base_render_args {
256 87     87 0 862 my $self = shift;
257 87   50     1289 my $args = {
258             name => $self->prefixed_name,
259             field_name => $self->name,
260             type => $self->type,
261             form_element => $self->form_element,
262             input_type => $self->input_type,
263             id => $self->id,
264             label => $self->loc_label,
265             required => $self->required,
266             errors => $self->errors || [],
267             fif => $self->fif,
268             layout_type => 'standard',
269             is_contains => $self->is_contains,
270             };
271 87 100       370 $args->{html5_input_type} = $self->html5_input_type if $self->has_html5_input_type;
272 87         209 return $args;
273             }
274              
275             has 'render_args' => ( is => 'rw', lazy => 1, isa => HashRef, builder => 'build_render_args' );
276 62     62 0 8435 sub build_render_args {{}}
277             # this is really just here for testing fields. If you want to test a custom
278             # renderer in a field, pass it in.
279             has 'renderer' => (
280             is => 'rw', lazy => 1,
281             builder => 'build_renderer',
282             );
283             sub build_renderer {
284 33     33 0 5628 my $self = shift;
285 33         9147 require Data::MuForm::Renderer::Base;
286 33         864 return Data::MuForm::Renderer::Base->new( localizer => $self->localizer );
287             }
288              
289             sub get_render_args {
290 87     87 0 153 my ( $self, %args ) = @_;
291 87         1605 my $render_args = merge( $self->render_args, $self->base_render_args );
292 87         270 $render_args = merge( \%args, $render_args );
293 87         249 return $render_args;
294             }
295              
296             sub render {
297 61     61 0 305 my ( $self, $rargs ) = @_;
298 61         184 munge_render_field_attr($rargs);
299 61         209 my $render_args = $self->get_render_args(%$rargs);
300 61         1083 return $self->renderer->render_field($render_args);
301             }
302              
303             sub render_element {
304 9     9 0 126 my ( $self, $rargs ) = @_;
305 9         25 my $args = { element_attr => $rargs };
306 9         17 my $do_errors = delete $rargs->{do_errors};
307 9 50       27 $args->{do_errors} = defined $do_errors ? $do_errors : 1;
308 9         52 my $render_args = $self->get_render_args(%$args);
309 9         149 return $self->renderer->render_element($render_args);
310             }
311              
312             sub render_errors {
313 1     1 0 13 my ( $self, $rargs ) = @_;
314 1         4 my $render_args = $self->get_render_args( error_attr => $rargs );
315 1         20 return $self->renderer->render_errors($render_args);
316             }
317              
318             sub render_label {
319 1     1 0 15 my ( $self, $rargs, @args ) = @_;
320 1         6 my $render_args = $self->get_render_args( label_attr => $rargs );
321 1 50       25 $self->form->render_hook($render_args) if $self->form;
322 1         18 return $self->renderer->render_label($render_args, @args);
323             }
324              
325              
326             #===================
327             # Errors
328             #===================
329              
330             # handles message with and without variables
331             sub add_error {
332 109     109 1 575 my ( $self, @message ) = @_;
333 109         99 my $out;
334 109 100       300 if ( $message[0] !~ /{/ ) {
335 72         1325 $out = $self->localizer->loc_($message[0]);
336             }
337             else {
338 37         614 $out = $self->localizer->loc_x(@message);
339             }
340 109         684 return $self->push_error($out);
341             }
342              
343             sub add_error_px {
344 0     0 0 0 my ( $self, @message ) = @_;
345 0         0 my $out = $self->localizer->loc_px(@message);
346 0         0 return $self->push_error($out);;
347             }
348              
349             sub add_error_nx {
350 1     1 0 4 my ( $self, @message ) = @_;
351 1         32 my $out = $self->localizer->loc_nx(@message);
352 1         29 return $self->push_error($out);
353             }
354              
355             sub add_error_npx {
356 0     0 0 0 my ( $self, @message ) = @_;
357 0         0 my $out = $self->localizer->loc_npx(@message);
358 0         0 return $self->push_error($out);;
359             }
360              
361              
362              
363             sub push_error {
364 110     110 1 191 my $self = shift;
365 110         99 push @{$self->{errors}}, @_;
  110         259  
366 110 100       1934 if ( $self->parent ) {
367 65         1192 $self->parent->propagate_error($self);
368             }
369             }
370              
371 7     7 0 4674 sub clear { shift->clear_data }
372              
373             #===================
374             # Transforms
375             #===================
376              
377             # these are all coderefs
378             has 'transform_param_to_input' => ( is => 'rw', predicate => 'has_transform_param_to_input' );
379             has 'transform_input_to_value' => ( is => 'rw', predicate => 'has_transform_input_to_value' );
380             has 'transform_default_to_value' => ( is => 'rw', predicate => 'has_transform_default_to_value' );
381             has 'transform_value_after_validate' => ( is => 'rw', predicate => 'has_transform_value_after_validate' );
382             has 'transform_value_to_fif' => ( is => 'rw', predicate => 'has_transform_value_to_fif' );
383              
384             #====================================================================
385             # Validation
386             #====================================================================
387              
388             has 'required' => ( is => 'rw', default => 0 );
389             has 'required_when' => ( is => 'rw', isa => HashRef, predicate => 'has_required_when' );
390             has 'unique' => ( is => 'rw', predicate => 'has_unique' );
391 1 50   1 0 12 sub validated { !$_[0]->has_errors && $_[0]->has_input }
392       198 0   sub normalize_input { } # intended for field classes, to make sure input is in correct form, mostly multiple or not
393              
394             sub input_defined {
395 585     585 0 588 my ($self) = @_;
396 585 50       1024 return unless $self->has_input;
397 585         1036 return has_some_value( $self->input );
398             }
399              
400             sub has_some_value {
401 682     682 0 640 my $x = shift;
402              
403 682 100       950 return unless defined $x;
404 678 100       3153 return $x =~ /\S/ if !ref $x;
405 94 100       183 if ( ref $x eq 'ARRAY' ) {
406 24         46 for my $elem (@$x) {
407 25 100       52 return 1 if has_some_value($elem);
408             }
409 3         14 return 0;
410             }
411 70 50       137 if ( ref $x eq 'HASH' ) {
412 70         147 for my $key ( keys %$x ) {
413 72 100       130 return 1 if has_some_value( $x->{$key} );
414             }
415 7         20 return 0;
416             }
417 0 0       0 return 1 if blessed($x); # true if blessed, otherwise false
418 0 0       0 return 1 if ref( $x );
419 0         0 return;
420             }
421              
422              
423              
424       0 0   sub base_validate { }
425 442     442 1 3218 sub validate {1}
426              
427             sub field_validate {
428 610     610 0 45317 my $self = shift;
429              
430 610 50 66     1137 return if ( $self->has_fields && $self->skip_fields_without_input && ! $self->has_input );
      33        
431              
432 610         1464 $self->normalize_input;
433              
434 610         918 my $continue_validation = 1;
435 610 100 66     4162 if ( ( $self->required ||
    100 100        
    100 100        
    100          
436             ( $self->has_required_when && $self->match_when($self->required_when) ) ) &&
437             ( ! $self->has_input || ! $self->input_defined )) {
438 24         126 $self->add_error( $self->get_message('required'), field_label => $self->label );
439 24 100       1081 if( $self->has_input ) {
440 16 50       129 $self->not_nullable ? $self->value($self->input) : $self->value(undef);
441             }
442              
443 24         40 $continue_validation = 0;
444             }
445             elsif ( $self->is_repeatable ) { }
446             elsif ( !$self->has_input ) {
447 39         49 $continue_validation = 0;
448             }
449             elsif ( !$self->input_defined ) {
450 19 100 100     209 if ( $self->not_nullable ) {
    100          
451 3         28 $self->value($self->input);
452             # handles the case where a compound field value needs to have empty subfields
453 3 50       18 $continue_validation = 0 unless $self->is_compound;
454             }
455             elsif ( $self->no_value_if_empty || $self->is_contains ) {
456 2         8 $continue_validation = 0;
457             }
458             else {
459 14         92 $self->value(undef);
460 14         21 $continue_validation = 0;
461             }
462             }
463 610 50 66     1552 return if ( !$continue_validation && !$self->validate_when_empty );
464              
465              
466 528 100       777 if ( $self->has_fields ) {
467 75         225 $self->fields_validate;
468             }
469             else {
470 453         646 my $input = $self->input;
471 453 100       1151 $input = $self->transform_input_to_value->($self, $input) if $self->has_transform_input_to_value;
472 453         1245 $self->value($input);
473             }
474              
475 528 100       2465 $self->value( $self->trim->($self->value) ) if $self->trim;
476              
477 528         1720 $self->validate($self->value); # this is field class validation. Do it before the other validations.
478              
479 528         2996 $self->apply_actions; # this could be either from the field definitions or from a custom field
480              
481             # this is validate_<field name> or methods->{validate => ...} validation
482 528 100       1393 if ( my $meth = $self->get_method('validate') ) {
483 19         40 $meth->($self);
484             }
485              
486 528 100       1543 if ( $self->has_transform_value_after_validate ) {
487 6         14 my $value = $self->value;
488 6         23 $value = $self->transform_value_after_validate->($self, $value);
489 6         37 $self->value($value);
490             }
491              
492 528         1041 return ! $self->has_errors;
493             }
494              
495             sub transform_and_set_input {
496 416     416 0 455 my ( $self, $input ) = @_;
497 416 100       1019 $input = $self->transform_param_to_input->($self, $input) if $self->has_transform_param_to_input;
498 416         894 $self->input($input);
499             }
500              
501              
502             sub apply_actions {
503 528     528 0 485 my $self = shift;
504              
505 528         398 my $error_message;
506             local $SIG{__WARN__} = sub {
507 2     2   13 my $error = shift;
508 2         3 $error_message = $error;
509 2         22 return 1;
510 528         2618 };
511              
512             my $is_type = sub {
513 229 100   229   728 my $class = blessed shift or return;
514 183   33     579 return $class eq 'MooseX::Types::TypeDecorator' || $class->isa('Type::Tiny');
515 528         1107 };
516              
517 528         465 my @actions;
518 528         459 push @actions, @{ $self->base_apply }, @{ $self->apply };
  528         1241  
  528         1079  
519 528         2221 for my $action ( @actions ) {
520 134         616 $error_message = undef;
521             # the first time through value == input
522 134         174 my $value = $self->value;
523 134         123 my $new_value = $value;
524             # Moose constraints
525 134 100 66     418 if ( !ref $action || $is_type->($action) ) {
526 88         900 $action = { type => $action };
527             }
528 134 100       297 if ( my $when = $action->{when} ) {
529 6 100       13 next unless $self->match_when($when);
530             }
531 131 100       335 if ( exists $action->{type} ) {
    100          
    100          
    100          
    50          
532 95         72 my $tobj;
533 95 50       136 if ( $is_type->($action->{type}) ) {
534 95         551 $tobj = $action->{type};
535             }
536             else {
537 0         0 my $type = $action->{type};
538 0 0       0 $tobj = Moose::Util::TypeConstraints::find_type_constraint($type) or
539             die "Cannot find type constraint $type";
540             }
541 95 100 100     204 if ( $tobj->has_coercion && $tobj->validate($value) ) {
542 14         488 eval { $new_value = $tobj->coerce($value) };
  14         35  
543 14 50       36 if ($@) {
544 0 0       0 if ( $tobj->has_message ) {
545 0         0 $error_message = $tobj->message->($value);
546             }
547             else {
548 0         0 $error_message = $@;
549             }
550             }
551             else {
552 14         32 $self->value($new_value);
553             }
554              
555             }
556 95   66     918 $error_message ||= $tobj->validate($new_value);
557             }
558             # now maybe: http://search.cpan.org/~rgarcia/perl-5.10.0/pod/perlsyn.pod#Smart_matching_in_detail
559             # actions in a hashref
560             elsif ( ref $action->{check} eq 'CODE' ) {
561 11 100       37 if ( !$action->{check}->($value, $self) ) {
562 3         38 $error_message = $self->get_message('wrong_value');
563             }
564             }
565             elsif ( ref $action->{check} eq 'Regexp' ) {
566 6 100       34 if ( $value !~ $action->{check} ) {
567 5         21 $error_message = [$self->get_message('no_match'), 'value', $value];
568             }
569             }
570             elsif ( ref $action->{check} eq 'ARRAY' ) {
571 5 100       5 if ( !grep { $value eq $_ } @{ $action->{check} } ) {
  5         9  
  5         12  
572 4         13 $error_message = [$self->get_message('not_allowed'), 'value', $value];
573             }
574             }
575             elsif ( ref $action->{transform} eq 'CODE' ) {
576 14         20 $new_value = eval {
577 93     93   559 no warnings 'all';
  93         218  
  93         91019  
578 14         45 $action->{transform}->($value, $self);
579             };
580 14 50       40 if ($@) {
581 0   0     0 $error_message = $@ || $self->get_message('error_occurred');
582             }
583             else {
584 14         34 $self->value($new_value);
585             }
586             }
587 131 100       2884 if ( defined $error_message ) {
588 50 100       137 my @message = ref $error_message eq 'ARRAY' ? @$error_message : ($error_message);
589 50 100       100 if ( defined $action->{message} ) {
590 13         16 my $act_msg = $action->{message};
591 13 100       34 if ( ref $act_msg eq 'CODE' ) {
592 3         14 $act_msg = $act_msg->($value, $self, $error_message);
593             }
594 13 100       63 if ( ref $act_msg eq 'ARRAY' ) {
    50          
595 3         4 @message = @{$act_msg};
  3         9  
596             }
597             elsif ( ref \$act_msg eq 'SCALAR' ) {
598 10         16 @message = ($act_msg);
599             }
600             }
601 50         139 $self->add_error(@message);
602             }
603             }
604             }
605              
606             sub match_when {
607 12     12 0 470 my ( $self, $when ) = @_;
608              
609 12         8 my $matched = 0;
610 12         29 foreach my $key ( keys %$when ) {
611 12         17 my $check_against = $when->{$key};
612 12         19 my $from_form = ( $key =~ /^\+/ );
613 12         19 $key =~ s/^\+//;
614 12 100       199 my $field = $from_form ? $self->form->field($key) : $self->parent->subfield( $key );
615 12 50       67 unless ( $field ) {
616 0         0 warn "field '$key' not found processing 'when' for '" . $self->full_name . "'";
617 0         0 next;
618             }
619 12 50       34 my $field_fif = defined $field->fif ? $field->fif : '';
620 12 100       50 if ( ref $check_against eq 'CODE' ) {
    100          
    100          
621 4 100       18 $matched++
622             if $check_against->($field_fif, $self);
623             }
624             elsif ( ref $check_against eq 'ARRAY' ) {
625 2         4 foreach my $value ( @$check_against ) {
626 6 100       13 $matched++ if ( $value eq $field_fif );
627             }
628             }
629             elsif ( $check_against eq $field_fif ) {
630 3         5 $matched++;
631             }
632             else {
633 3         5 $matched = 0;
634 3         4 last;
635             }
636             }
637 12         77 return $matched;
638             }
639              
640             #====================================================================
641             # Filling
642             #====================================================================
643              
644             sub fill_from_params {
645 410     410 0 854 my ( $self, $input, $exists ) = @_;
646              
647 410         781 $self->filled_from('params');
648 410 100       759 if ( $exists ) {
    100          
    100          
649 341         641 $self->transform_and_set_input($input);
650             }
651             elsif ( $self->disabled ) {
652             }
653             elsif ( $self->has_input_without_param ) {
654 20         167 $self->transform_and_set_input($self->input_without_param);
655             }
656 410         579 return;
657             }
658              
659             sub fill_from_object {
660 210     210 0 339 my ( $self, $value ) = @_;
661              
662 210         419 $self->filled_from('object');
663 210         527 $self->value($value);
664              
665 210 50       2942 if ( $self->form ) {
666 210         3167 $self->form->init_value( $self, $value );
667             }
668             else {
669 0         0 $self->init_value($value);
670             #$result->_set_value($value);
671             }
672 210 50       1131 $self->value(undef) if $self->writeonly;
673              
674 210         305 return;
675             }
676              
677             sub fill_from_fields {
678 598     598 0 1180 my ( $self ) = @_;
679              
680 598 100       1147 if ( my @values = $self->get_default_value ) {
681 36 100       131 if ( $self->has_transform_default_to_value ) {
682 2         6 @values = $self->transform_default_to_value->($self, @values);
683             }
684 36 50       82 my $value = @values > 1 ? \@values : shift @values;
685 36 50       57 if ( defined $value ) {
686 36         79 $self->init_value($value);
687 36         129 $self->value($value);
688             }
689             }
690 598         781 return;
691             }
692              
693              
694             sub clear_data {
695 294     294 0 275 my $self = shift;
696 294         3675 $self->clear_input;
697 294         14791 $self->clear_value;
698 294         13418 $self->clear_errors;
699 294         3527 $self->_clear_active;
700 294         13399 $self->clear_filled_from;
701             }
702              
703             sub get_default_value {
704 726     726 0 563 my $self = shift;
705 726 100       1309 if ( my $meth = $self->get_method('default') ) {
    100          
706 10         23 return $meth->($self);
707             }
708             elsif ( defined $self->default ) {
709 37         118 return $self->default;
710             }
711 679         1435 return;
712             }
713              
714              
715             #====================================================================
716             # Messages
717             #====================================================================
718              
719             has 'messages' => ( is => 'rw', isa => HashRef, default => sub {{}} );
720 4     4   6 sub _get_field_message { my ($self, $msg) = @_; return $self->{messages}->{$msg}; }
  4         72  
721 66     66   82 sub _has_field_message { my ($self, $msg) = @_; exists $self->{messages}->{$msg}; }
  66         221  
722 0     0 0 0 sub set_message { my ($self, $msg, $value) = @_; $self->{messages}->{$msg} = $value; }
  0         0  
723              
724              
725             our $class_messages = {
726             'field_invalid' => 'field is invalid',
727             'range_too_low' => 'Value must be greater than or equal to [_1]',
728             'range_too_high' => 'Value must be less than or equal to [_1]',
729             'range_incorrect' => 'Value must be between {start} and {end}',
730             'wrong_value' => 'Wrong value',
731             'no_match' => '[_1] does not match',
732             'not_allowed' => '[_1] not allowed',
733             'error_occurred' => 'error occurred',
734             'required' => "'{field_label}' field is required",
735             'unique' => 'Duplicate value for [_1]', # this is used in the DBIC model
736             };
737              
738             sub get_class_messages {
739 61     61 0 475 my $self = shift;
740 61         471 my $messages = { %$class_messages };
741 61         532 return $messages;
742             }
743              
744             sub get_message {
745 66     66 0 121 my ( $self, $msg ) = @_;
746              
747             # first look in messages set on individual field
748 66 100       227 return $self->_get_field_message($msg)
749             if $self->_has_field_message($msg);
750             # then look at form messages
751 62 100 100     1006 return $self->form->_get_form_message($msg)
752             if $self->has_form && $self->form->_has_form_message($msg);
753             # then look for messages up through inherited field classes
754 61         8097 return $self->get_class_messages->{$msg};
755             }
756             sub all_messages {
757 0     0 0 0 my $self = shift;
758 0 0       0 my $form_messages = $self->has_form ? $self->form->messages : {};
759 0   0     0 my $field_messages = $self->messages || {};
760 0   0     0 my $lclass_messages = $self->my_class_messages || {};
761 0         0 return {%{$lclass_messages}, %{$form_messages}, %{$field_messages}};
  0         0  
  0         0  
  0         0  
762             }
763              
764             sub clone {
765 4892     4892 0 3494 my $self = shift;
766 4892         88903 return data_clone($self);
767             }
768              
769             sub get_result {
770 2     2 0 1 my $self = shift;
771 2         7 my $result = {
772             name => $self->name,
773             full_name => $self->full_name,
774             id => $self->id,
775             label => $self->label,
776             render_args => $self->render_args,
777             fif => $self->fif,
778             };
779 2 50       7 $result->{errors} = $self->errors if $self->has_errors;
780 2         400 return $result;
781             }
782              
783             sub convert_full_name {
784 637     637 0 841 my ( $self, $full_name ) = @_;
785 637         1041 $full_name =~ s/\.\d+\./_/g;
786 637         896 $full_name =~ s/\./_/g;
787 637         959 return $full_name;
788             }
789              
790              
791             1;
792              
793             __END__
794              
795             =pod
796              
797             =encoding UTF-8
798              
799             =head1 NAME
800              
801             Data::MuForm::Field - Base field package
802              
803             =head1 VERSION
804              
805             version 0.04
806              
807             =head1 SYNOPSIS
808              
809             Instances of Field subclasses are generally built by L<Data::MuForm>
810             from 'has_field' declarations or the field_list.
811              
812             has_field 'my_field' => ( type => 'Integer' );
813             field_list => [
814             my_field => { type => 'Integer' }
815             ]
816              
817             Fields can also be added with add_field:
818              
819             $form->add_field( name => 'my_field', type => 'Integer' );
820              
821             You can create custom field classes:
822              
823             package MyApp::Field::MyText;
824             use Moo;
825             use Data::MuForm::Meta;
826             extends 'Data::MuForm::Field::Text';
827              
828             has 'my_attribute' => ( is => 'rw' );
829              
830             sub validate { <perform validation> }
831              
832             1;
833              
834             =head1 DESCRIPTION
835              
836             This is the base class for form fields. The 'type' of a field class
837             is used in the MuForm field_list or has_field to identify which field class to
838             load from the 'field_namespace' (or directly, when prefixed with '+').
839             If the type is not specified, it defaults to Text.
840              
841             See L<Data::MuForm::Manual::Fields> for a list of the fields and brief
842             descriptions of their structure.
843              
844             =head1 NAME
845              
846             Data::MuForm::Field
847              
848             =head1 ATTRIBUTES
849              
850             =head2 Names, types, accessor
851              
852             =over
853              
854             =item name
855              
856             The name of the field. Used in the HTML form. Often a db accessor.
857             The only required attribute.
858              
859             =item type
860              
861             The class or type of the field. The 'type' of L<Data::MuForm::Field::Currency>
862             is 'Currency'.
863              
864             =item id
865              
866             The id to use when rendering. This can come from a number of different places.
867              
868             1) field definition
869             2) field 'build_id' method
870             3) form 'build_field_id' method
871             4) field prefixed_name
872              
873             =item accessor
874              
875             If the name of your field is different than your database accessor, use
876             this attribute to provide the accessor.
877              
878             =item full_name
879              
880             The name of the field with all parents:
881              
882             'event.start_date.month'
883              
884             =item full_accessor
885              
886             The field accessor with all parents.
887              
888             =item prefixed_name
889              
890             The full_name plus the prefix provided in 'field_prefix'. Useful for multiple
891             forms on the same page.
892              
893             =item input_param
894              
895             By default we expect an input parameter based on the field name. This allows
896             you to look for a different input parameter.
897              
898             =back
899              
900             =head2 Field data
901              
902             =over
903              
904             =item active, inactive, is_active, is_inactive
905              
906             Determines which fields will be processed and rendered.
907              
908             Can be changed on a process call, and cleared afterward:
909              
910             $form->process( active => [ 'foo', 'bar' ], params => $params );
911              
912             You can use the is_inactive and is_active methods to check whether this particular
913             field is active. May be necessary to use in templates if you're changing the
914             active/inactive of some fields.
915              
916             if( $form->field('foo')->is_active ) { ... }
917              
918             =item input
919              
920             The input string from the parameters passed in. This is not usually set by
921             the user.
922              
923             =item value
924              
925             The value as it would come from or go into the database, after being
926             acted on by transforms and validation code. Used to construct the
927             C<< $form->values >> hash. Before validation is performed, the input is
928             copied to the 'value', and validation and constraints should act on 'value'.
929             After validation, C<< $form->value >> will get a hashref of the values.
930              
931             See also L<Data::MuForm::Manual::Transforms>.
932              
933             =item fif
934              
935             Values used to fill in the form. Read only.
936              
937             [% form.field('title').fif %]
938              
939             =item init_value
940              
941             Initial value populated by fill_from_object. You can tell if a field
942             has changed by comparing 'init_value' and 'value'. You wouldn't normally
943             change this.
944              
945             =item input_without_param
946              
947             Input for this field if there is no param. Set by default for Checkbox,
948             and Select, since an unchecked checkbox or unselected pulldown
949             does not return a parameter.
950              
951             =back
952              
953             =head2 Form, parent, etc
954              
955             =over
956              
957             =item form
958              
959             A reference to the containing form.
960              
961             =item parent
962              
963             A reference to the parent of this field. Compound fields are the
964             parents for the fields they contain.
965              
966             =item localizer
967              
968             Set from the form when fields are created.
969              
970             =item renderer
971              
972             Set from the form when fields are created.
973              
974             =back
975              
976             =head2 Errors
977              
978             =over
979              
980             =item errors
981              
982             Returns the error list (arrayref) for the field. Also provides
983             'all_errors', 'num_errors', 'has_errors', 'push_error' and 'clear_errors'.
984             Use 'add_error' to add an error to the array if you
985             want to localize the error message, or 'push_error' to skip
986             the localization.
987              
988             =item add_error
989              
990             Add an error to the list of errors. Error message will be localized
991             using 'localize' method, and the Localizer (default is
992             Data::MuForm::Localizer, which use a gettext style .po file).
993              
994             return $field->add_error( 'bad data' ) if $bad;
995              
996             =item push_error
997              
998             Adds an error to the list of errors without localization.
999              
1000             =item error_fields
1001              
1002             The form and Compound fields will have an array of errors from the subfields.
1003              
1004             =back
1005              
1006             =head2 methods
1007              
1008             A 'methods' hashref allows setting various coderefs, 'build_id', 'build_label',
1009             'build_options', 'validate', 'default'.
1010              
1011             methods => { build_id => \&my_build_id } - coderef for constructing the id
1012             methods => { build_label => \&my_build_label } - coderef for constructing the label
1013              
1014             =over
1015              
1016             =item build_id
1017              
1018             A coderef to build the field's id. If one doesn't exist, will use a form 'build_field_id'
1019             method. Fallback is to use the field's full name.
1020              
1021             =item build_label
1022              
1023             =item build_options
1024              
1025             =item validate
1026              
1027             =item default
1028              
1029             =back
1030              
1031             =head2 render_args
1032              
1033             The 'render_args' hashref contains keys which are used in rendering, with shortcuts
1034             for easier specification in a field definition.
1035              
1036             element_attr - ea
1037             label_attr - la
1038             wrapper_attr - wa
1039             error_attr - era
1040             element_wrapper_attr - ewa
1041              
1042             has_field 'foo' => ( render_args => { element_attr => { readonly => 1, my_attr => 'abc' }} );
1043             has_field 'foo' => ( 'ra.ea' => { readonly => 1, my_attr => 'abc' } );
1044             has_field 'foo' => ( 'ra'.wa.class' => ['mb10', 'wr66'] );
1045              
1046             Note the the 'name', 'id', and 'value' of fields is set by field attributes. Though
1047             it is possible to override the id in render_args, it then won't be available for
1048             other code such as 'errors_by_id'. There is some behavior associated with the 'disabled'
1049             flag too.
1050              
1051             label - Text label for this field. Defaults to ucfirst field name.
1052             id - Used in 'id="<id>"' in HTML
1053             disabled - Boolean to set field disabled
1054              
1055             The order attribute may be used to set the order in which fields are rendered.
1056              
1057             order - Used for sorting errors and fields. Built automatically,
1058             but may also be explicitly set. Auto sequence is by 5: 5, 10, 15, etc
1059              
1060             =head2 Flags
1061              
1062             =over
1063              
1064             =item password
1065              
1066             Prevents the entered value from being displayed in the form
1067              
1068             =item writeonly
1069              
1070             The initial value is not taken from the database
1071              
1072             =item no_update
1073              
1074             Do not include this field in C<< $form->values >>, and so it won't be updated in the database.
1075              
1076             =item not_nullable
1077              
1078             Fields that contain 'empty' values such as '' are changed to undef in the validation process.
1079             If this flag is set, the value is not changed to undef. If your database column requires
1080             an empty string instead of a null value (such as a NOT NULL column), set this attribute.
1081              
1082             has_field 'description' => (
1083             type => 'TextArea',
1084             not_nullable => 1,
1085             );
1086              
1087             This attribute is also used when you want an empty array to stay an empty array and not
1088             be set to undef.
1089              
1090             It's also used when you have a compound field and you want the 'value' returned
1091             to contain subfields with undef, instead of the whole field to be undef.
1092              
1093             =back
1094              
1095             =head2 Defaults
1096              
1097             See also the documentation on L<Data::MuForm::Manual::Defaults>.
1098              
1099             =over
1100              
1101             =item default method
1102              
1103             Note: do *not* set defaults by setting the 'checked' or 'selected' attributes
1104             in options. The code will be unaware that defaults have been set.
1105              
1106             has_field 'foo' => ( methods => { default => \&my_default } );
1107             sub my_default { }
1108             OR
1109             has_field 'foo';
1110             sub default_foo { }
1111              
1112             Supply a coderef (which will be a method on the field).
1113             If not specified and a form method with a name of
1114             C<< default_<field_name> >> exists, it will be used.
1115              
1116             =item default
1117              
1118             Provide an initial value in the field declaration:
1119              
1120             has_field 'bax' => ( default => 'Default bax' );
1121              
1122             =back
1123              
1124             =head1 Constraints and Validations
1125              
1126             See also L<Data::MuForm::Manual::Validation>.
1127              
1128             =head2 Constraints set in attributes
1129              
1130             =over
1131              
1132             =item required
1133              
1134             Flag indicating whether this field must have a value
1135              
1136             =item unique
1137              
1138             For DB field - check for uniqueness. Action is performed by
1139             the DB model.
1140              
1141             =item apply
1142              
1143             Use the 'apply' keyword to specify an ArrayRef of constraints and coercions to
1144             be executed on the field at field_validate time.
1145              
1146             has_field 'test' => (
1147             apply => [ TinyType,
1148             { check => sub {...}, message => { } },
1149             { transform => sub { ... lc(shift) ... } }
1150             ],
1151             );
1152              
1153             =back
1154              
1155             =head2 messages
1156              
1157             has_field 'foo' => ( messages => { required => '...', unique => '...' } );
1158             or
1159             has_field 'foo' => ( 'msg.required' => '...' );
1160              
1161             Set messages created by MuForm by setting in the 'messages'
1162             hashref or with the 'msg.<msg_name>' shortcut. Some field subclasses have additional
1163             settable messages.
1164              
1165             required: Error message text added to errors if required field is not present.
1166             The default is "Field <field label> is required".
1167              
1168             =head2 Transforms
1169              
1170             There are a number of methods to provide finely tuned transformation of the
1171             input or value.
1172              
1173             See also L<Data::MuForm::Manual::Transforms>.
1174              
1175             =over 4
1176              
1177             =item transform_input_to_value
1178              
1179             In FH was 'inflate_method'.
1180              
1181             Transforms the string that was submitted in params (and copied to 'input') when
1182             it's stored in the 'value' attribute during validation.
1183              
1184             =item transform_value_to_fif
1185              
1186             In FH was 'deflate_method'.
1187              
1188             When you get 'fif' for the field and the 'value' is used (as opposed to input)
1189             transforms the value to a string suitable for filling in a form field.
1190              
1191             =item transform_default_to_value
1192              
1193             In FH was inflate_default_method.
1194              
1195             Transform the 'default' provided by an 'model' or 'init_values' or 'default' when it's stored
1196             in the 'value'.
1197              
1198             =item transform_value_after_validate
1199              
1200             In FH was 'deflate_value_method';
1201              
1202             Transform the value after validation has been performs, in order to return
1203             a different form in C<< $form->value >>.
1204              
1205             =item transform_param_to_input
1206              
1207             Transform the param when it's stored in 'input'. Will change what the user sees
1208             in a re-presented form.
1209              
1210             =item trim
1211              
1212             A transform to trim the field. The default 'trim' sub
1213             strips beginning and trailing spaces.
1214             Set this attribute to null to skip trimming, or supply a different
1215             sub.
1216              
1217             trim => sub {
1218             my $string = shift;
1219             <do something>
1220             return $string;
1221             }
1222              
1223             Trimming is performed before any other defined actions.
1224              
1225             =back
1226              
1227             =head1 Processing and validating the field
1228              
1229             See also L<Data::MuForm::Manual::Validation>.
1230              
1231             =head2 Validate method
1232              
1233             has_field 'foo' => ( methods => { validate => \&foo_validation } );
1234             sub foo_validation { }
1235             OR
1236             has_field 'foo';
1237             sub validate_foo { }
1238              
1239             Supply a coderef (which will be a method on the field).
1240             If not specified and a form method with a name of
1241             C<< validate_<field_name> >> exists, it will be used instead.
1242              
1243             Periods in field names will be replaced by underscores, so that the field
1244             'addresses.city' will use the 'validate_addresses_city' method for validation.
1245              
1246             =head2 apply actions
1247              
1248             Use Type::Tiny types;
1249              
1250             use Types::Standard ('PosInteger');
1251             has_field 'foo' => ( apply => [ PosInteger ] );
1252              
1253             =head2 validate
1254              
1255             This field method can be used in addition to or instead of 'apply' actions
1256             in custom field classes.
1257             It should validate the field data and set error messages on
1258             errors with C<< $field->add_error >>.
1259              
1260             sub validate {
1261             my $field = shift;
1262             my $value = $field->value;
1263             return $field->add_error( ... ) if ( ... );
1264             }
1265              
1266             =head1 AUTHOR
1267              
1268             Gerda Shank
1269              
1270             =head1 COPYRIGHT AND LICENSE
1271              
1272             This software is copyright (c) 2017 by Gerda Shank.
1273              
1274             This is free software; you can redistribute it and/or modify it under
1275             the same terms as the Perl 5 programming language system itself.
1276              
1277             =cut