line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Data::MuForm::Fields; |
2
|
|
|
|
|
|
|
# ABSTRACT: Common attributes and methods for forms and compound fields |
3
|
82
|
|
|
82
|
|
38606
|
use Moo::Role; |
|
82
|
|
|
|
|
113
|
|
|
82
|
|
|
|
|
403
|
|
4
|
|
|
|
|
|
|
|
5
|
82
|
|
|
82
|
|
16319
|
use Types::Standard -types; |
|
82
|
|
|
|
|
109
|
|
|
82
|
|
|
|
|
701
|
|
6
|
82
|
|
|
82
|
|
244816
|
use Type::Utils; |
|
82
|
|
|
|
|
266609
|
|
|
82
|
|
|
|
|
687
|
|
7
|
82
|
|
|
82
|
|
74245
|
use Data::Clone ('data_clone'); |
|
82
|
|
|
|
|
115
|
|
|
82
|
|
|
|
|
3513
|
|
8
|
82
|
|
|
82
|
|
4040
|
use Class::Load ('load_optional_class'); |
|
82
|
|
|
|
|
88923
|
|
|
82
|
|
|
|
|
3360
|
|
9
|
82
|
|
|
82
|
|
314
|
use Scalar::Util 'blessed'; |
|
82
|
|
|
|
|
108
|
|
|
82
|
|
|
|
|
230143
|
|
10
|
|
|
|
|
|
|
with 'Data::MuForm::Common'; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
has 'value' => ( is => 'rw', predicate => 'has_value', default => sub {{}} ); |
14
|
133
|
|
|
133
|
0
|
277
|
sub clear_value { $_[0]->{value} = {} } |
15
|
7
|
|
|
7
|
0
|
1174
|
sub values { $_[0]->value } |
16
|
|
|
|
|
|
|
has 'init_value' => ( is => 'rw', clearer => 'clear_init_value' ); |
17
|
|
|
|
|
|
|
has 'input' => ( is => 'rw', clearer => 'clear_input' ); |
18
|
|
|
|
|
|
|
has 'skip_fields_without_input' => ( is => 'rw' ); # except 'input_without_param' |
19
|
|
|
|
|
|
|
has 'filled_from' => ( is => 'rw', clearer => 'clear_filled_from' ); |
20
|
|
|
|
|
|
|
has 'meta_fields' => ( is => 'rw' ); |
21
|
|
|
|
|
|
|
has 'field_list' => ( is => 'rw', isa => ArrayRef, lazy => 1, builder => 'build_field_list' ); |
22
|
223
|
|
|
223
|
0
|
55424
|
sub build_field_list {[]} |
23
|
|
|
|
|
|
|
has 'fields' => ( is => 'rw', isa => ArrayRef, default => sub {[]}); |
24
|
1050
|
|
|
1050
|
0
|
2230
|
sub push_field { my ( $self, @fields ) = @_; push @{$self->{fields}}, @fields; } |
|
1050
|
|
|
|
|
979
|
|
|
1050
|
|
|
|
|
2875
|
|
25
|
85
|
|
|
85
|
0
|
92
|
sub clear_fields { my $self = shift; $self->{fields} = undef; } |
|
85
|
|
|
|
|
172
|
|
26
|
2080
|
|
|
2080
|
0
|
2267
|
sub all_fields { my $self = shift; return @{$self->{fields}}; } |
|
2080
|
|
|
|
|
1560
|
|
|
2080
|
|
|
|
|
4937
|
|
27
|
5
|
|
|
5
|
0
|
9
|
sub set_field_at { my ( $self, $index, $field ) = @_; @{$self->{fields}}[$index] = $field; } |
|
5
|
|
|
|
|
17
|
|
|
5
|
|
|
|
|
17
|
|
28
|
60
|
|
|
60
|
0
|
4258
|
sub num_fields { my $self = shift; return scalar (@{$self->{fields}}); } |
|
60
|
|
|
|
|
71
|
|
|
60
|
|
|
|
|
329
|
|
29
|
776
|
|
|
776
|
0
|
768
|
sub has_fields { my $self = shift; return scalar (@{$self->{fields}}); } |
|
776
|
|
|
|
|
578
|
|
|
776
|
|
|
|
|
4866
|
|
30
|
|
|
|
|
|
|
has 'error_fields' => ( is => 'rw', isa => ArrayRef, default => sub {[]} ); |
31
|
308
|
|
|
308
|
0
|
484
|
sub clear_error_fields { $_[0]->{error_fields} = [] } |
32
|
375
|
|
|
375
|
0
|
331
|
sub has_error_fields { my $self = shift; return scalar @{$self->error_fields}; } |
|
375
|
|
|
|
|
278
|
|
|
375
|
|
|
|
|
787
|
|
33
|
9
|
|
|
9
|
0
|
536
|
sub num_error_fields { my $self = shift; return scalar @{$self->error_fields}; } |
|
9
|
|
|
|
|
48
|
|
|
9
|
|
|
|
|
24
|
|
34
|
81
|
|
|
81
|
0
|
88
|
sub add_error_field { my ($self, $field) = @_; push @{$self->error_fields}, $field; } |
|
81
|
|
|
|
|
80
|
|
|
81
|
|
|
|
|
318
|
|
35
|
8
|
|
|
8
|
0
|
10
|
sub all_error_fields { my $self = shift; return @{$self->error_fields}; } |
|
8
|
|
|
|
|
10
|
|
|
8
|
|
|
|
|
40
|
|
36
|
|
|
|
|
|
|
has 'field_namespace' => ( |
37
|
|
|
|
|
|
|
is => 'rw', |
38
|
|
|
|
|
|
|
isa => ArrayRef, |
39
|
|
|
|
|
|
|
builder => 'build_field_namespace', |
40
|
|
|
|
|
|
|
coerce => sub { |
41
|
|
|
|
|
|
|
my $ns = shift; |
42
|
|
|
|
|
|
|
return [] unless defined $ns; |
43
|
|
|
|
|
|
|
return $ns if ref $ns eq 'ARRAY'; |
44
|
|
|
|
|
|
|
return [$ns] if length($ns); |
45
|
|
|
|
|
|
|
return []; |
46
|
|
|
|
|
|
|
}, |
47
|
|
|
|
|
|
|
); |
48
|
129
|
|
|
129
|
0
|
3129
|
sub build_field_namespace { [] } |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
sub subfield { |
51
|
8
|
|
|
8
|
0
|
57
|
my ( $self, $name ) = @_; |
52
|
8
|
|
|
|
|
24
|
return $self->field($name, $self); |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub field { |
56
|
515
|
|
|
515
|
0
|
71945
|
my ( $self, $name, $f ) = @_; |
57
|
|
|
|
|
|
|
|
58
|
515
|
|
|
|
|
491
|
my $index; |
59
|
|
|
|
|
|
|
# if this is a full_name for a compound field |
60
|
|
|
|
|
|
|
# walk through the fields to get to it |
61
|
515
|
50
|
|
|
|
989
|
return undef unless ( defined $name ); |
62
|
515
|
100
|
66
|
|
|
2104
|
if( $self->form && $self == $self->form && |
|
|
|
66
|
|
|
|
|
63
|
|
|
|
|
|
|
exists $self->index->{$name} ) { |
64
|
436
|
|
|
|
|
36836
|
return $self->index->{$name}; |
65
|
|
|
|
|
|
|
} |
66
|
79
|
100
|
|
|
|
1922
|
if ( $name =~ /\./ ) { |
67
|
12
|
|
|
|
|
40
|
my @names = split /\./, $name; |
68
|
12
|
|
33
|
|
|
60
|
$f ||= $self->form || $self; |
|
|
|
66
|
|
|
|
|
69
|
12
|
|
|
|
|
24
|
foreach my $fname (@names) { |
70
|
30
|
|
|
|
|
83
|
$f = $f->field($fname); |
71
|
30
|
50
|
|
|
|
98
|
return unless $f; |
72
|
|
|
|
|
|
|
} |
73
|
12
|
|
|
|
|
129
|
return $f; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
else # not a compound name |
76
|
|
|
|
|
|
|
{ |
77
|
67
|
|
|
|
|
188
|
for my $field ( $self->all_fields ) { |
78
|
96
|
100
|
|
|
|
422
|
return $field if ( $field->name eq $name ); |
79
|
|
|
|
|
|
|
} |
80
|
|
|
|
|
|
|
} |
81
|
2
|
|
|
|
|
6
|
return; |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub all_sorted_fields { |
85
|
762
|
|
|
762
|
0
|
2223
|
my $self = shift; |
86
|
2059
|
|
|
|
|
4433
|
my @fields = sort { $a->order <=> $b->order } |
87
|
762
|
|
|
|
|
1584
|
grep { $_->is_active } $self->all_fields; |
|
2140
|
|
|
|
|
4218
|
|
88
|
762
|
|
|
|
|
1533
|
return @fields; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub sorted_fields { |
92
|
8
|
|
|
8
|
0
|
68
|
my $self = shift; |
93
|
8
|
|
|
|
|
23
|
my @fields = $self->all_sorted_fields; |
94
|
8
|
|
|
|
|
40
|
return \@fields; |
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
sub field_index { |
98
|
586
|
|
|
586
|
0
|
757
|
my ( $self, $name ) = @_; |
99
|
586
|
|
|
|
|
605
|
my $index = 0; |
100
|
586
|
|
|
|
|
1478
|
for my $field ( $self->all_fields ) { |
101
|
908
|
100
|
|
|
|
3942
|
return $index if $field->name eq $name; |
102
|
901
|
|
|
|
|
856
|
$index++; |
103
|
|
|
|
|
|
|
} |
104
|
579
|
|
|
|
|
821
|
return; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# Repeatable overrides this |
108
|
|
|
|
|
|
|
sub fields_validate { |
109
|
152
|
|
|
152
|
0
|
156
|
my $self = shift; |
110
|
|
|
|
|
|
|
|
111
|
152
|
50
|
|
|
|
285
|
return unless $self->has_fields; |
112
|
|
|
|
|
|
|
# validate all fields |
113
|
152
|
|
|
|
|
178
|
my %value_hash; |
114
|
152
|
|
|
|
|
305
|
foreach my $field ( $self->all_sorted_fields ) { |
115
|
438
|
100
|
66
|
|
|
1370
|
next if ( !$field->is_active || $field->disabled ); |
116
|
436
|
100
|
100
|
|
|
1252
|
next if ( $self->skip_fields_without_input && ! $field->has_input && ! $field->has_input_without_param ); |
|
|
|
66
|
|
|
|
|
117
|
|
|
|
|
|
|
# Validate each field and "inflate" input -> value. |
118
|
429
|
|
|
|
|
1186
|
$field->field_validate; # this calls all the various validation routines |
119
|
429
|
100
|
100
|
|
|
28291
|
$value_hash{ $field->accessor } = $field->value |
120
|
|
|
|
|
|
|
if ( $field->has_value && !$field->no_update ); |
121
|
|
|
|
|
|
|
} |
122
|
152
|
|
|
|
|
1139
|
$self->value( \%value_hash ); |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub fields_fif { |
126
|
111
|
|
|
111
|
0
|
146
|
my ( $self, $prefix ) = @_; |
127
|
|
|
|
|
|
|
|
128
|
111
|
|
100
|
|
|
325
|
$prefix ||= ''; |
129
|
111
|
100
|
100
|
|
|
772
|
$prefix = $self->field_prefix . "." |
130
|
|
|
|
|
|
|
if ( $self->isa('Data::MuForm') && $self->field_prefix ); |
131
|
|
|
|
|
|
|
|
132
|
111
|
|
|
|
|
106
|
my %params; |
133
|
111
|
|
|
|
|
232
|
foreach my $field ( $self->all_sorted_fields ) { |
134
|
296
|
100
|
33
|
|
|
473
|
next if ( ! $field->is_active || $field->password || $field->no_fif ); |
|
|
|
66
|
|
|
|
|
135
|
289
|
|
|
|
|
603
|
my $fif = $field->fif; |
136
|
289
|
100
|
100
|
|
|
858
|
next if ( !defined $fif || (ref $fif eq 'ARRAY' && ! scalar @{$fif} ) ); |
|
19
|
|
33
|
|
|
58
|
|
137
|
288
|
100
|
|
|
|
487
|
if ( $field->has_fields ) { |
138
|
|
|
|
|
|
|
# this builds up foo.0.bar.name |
139
|
53
|
|
|
|
|
276
|
my $next_params = $field->fields_fif( $prefix . $field->name . '.' ); |
140
|
53
|
50
|
|
|
|
120
|
next unless $next_params; |
141
|
53
|
|
|
|
|
81
|
%params = ( %params, %{$next_params} ); |
|
53
|
|
|
|
|
309
|
|
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
else { |
144
|
235
|
|
|
|
|
580
|
$params{ $prefix . $field->name } = $fif; |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
} |
147
|
111
|
50
|
|
|
|
390
|
return if !%params; |
148
|
111
|
|
|
|
|
540
|
return \%params; |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
sub fields_get_results { |
153
|
1
|
|
|
1
|
0
|
1
|
my $self = shift; |
154
|
|
|
|
|
|
|
|
155
|
1
|
|
|
|
|
5
|
my $result = $self->get_result; |
156
|
1
|
|
|
|
|
1
|
my @field_results; |
157
|
1
|
|
|
|
|
3
|
foreach my $field ( $self->all_sorted_fields ) { |
158
|
2
|
50
|
|
|
|
6
|
next if ! $field->is_active; |
159
|
2
|
|
|
|
|
8
|
my $result = $field->get_result; |
160
|
2
|
|
|
|
|
4
|
push @field_results, $result; |
161
|
|
|
|
|
|
|
} |
162
|
1
|
|
|
|
|
2
|
$result->{fields} = \@field_results; |
163
|
1
|
|
|
|
|
2
|
return $result; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
#==================================================================== |
167
|
|
|
|
|
|
|
# Build Fields |
168
|
|
|
|
|
|
|
#==================================================================== |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
sub build_fields { |
171
|
229
|
|
|
229
|
0
|
386
|
my $self = shift; |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
# process meta fields |
174
|
229
|
|
|
|
|
4112
|
my @meta_fields = $self->_meta_fields; |
175
|
229
|
|
|
|
|
3510
|
$self->meta_fields(\@meta_fields); |
176
|
229
|
|
|
|
|
4690
|
my $meta_fields = data_clone(\@meta_fields); |
177
|
229
|
|
|
|
|
1208
|
$self->process_field_array( $meta_fields ); |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
# process field_list |
180
|
228
|
|
|
|
|
1242
|
my $field_list = $self->field_list; |
181
|
228
|
100
|
100
|
|
|
7351
|
$field_list = $self->convert_field_list_to_hashes($field_list) |
182
|
|
|
|
|
|
|
if $field_list->[0] && ref($field_list->[0]) ne 'HASH'; |
183
|
228
|
|
|
|
|
1432
|
$self->process_field_array ( $field_list ); |
184
|
|
|
|
|
|
|
|
185
|
228
|
100
|
|
|
|
1140
|
return unless $self->has_fields; |
186
|
148
|
|
|
|
|
984
|
$self->order_fields; |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
sub convert_field_list_to_hashes { |
190
|
3
|
|
|
3
|
0
|
5
|
my ( $self, $field_list ) = @_; |
191
|
|
|
|
|
|
|
|
192
|
3
|
|
|
|
|
5
|
my @new_fields; |
193
|
3
|
|
|
|
|
74
|
while (@$field_list) { |
194
|
8
|
|
|
|
|
12
|
my $name = shift @$field_list; |
195
|
8
|
|
|
|
|
11
|
my $attr = shift @$field_list; |
196
|
8
|
100
|
|
|
|
22
|
unless ( ref $attr eq 'HASH' ) { |
197
|
4
|
|
|
|
|
10
|
$attr = { type => $attr }; |
198
|
|
|
|
|
|
|
} |
199
|
8
|
|
|
|
|
37
|
push @new_fields, { name => $name, %$attr }; |
200
|
|
|
|
|
|
|
} |
201
|
3
|
|
|
|
|
5
|
return \@new_fields; |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
sub process_field_array { |
205
|
457
|
|
|
457
|
0
|
600
|
my ( $self, $fields ) = @_; |
206
|
|
|
|
|
|
|
|
207
|
457
|
|
|
|
|
1647
|
$fields = $self->clean_fields($fields); |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
# TODO: there's got to be a better way of doing this |
210
|
457
|
|
|
|
|
690
|
my $num_fields = scalar @$fields; |
211
|
457
|
|
|
|
|
433
|
my $num_dots = 0; |
212
|
457
|
|
|
|
|
430
|
my $count_fields = 0; |
213
|
457
|
|
|
|
|
1076
|
while ( $count_fields < $num_fields ) { |
214
|
195
|
|
|
|
|
364
|
foreach my $field (@$fields) { |
215
|
887
|
|
|
|
|
1466
|
my $count = ( $field->{name} =~ tr/\.// ); |
216
|
887
|
100
|
|
|
|
1608
|
next unless $count == $num_dots; |
217
|
585
|
|
|
|
|
1454
|
$self->_make_field($field); |
218
|
584
|
|
|
|
|
915
|
$count_fields++; |
219
|
|
|
|
|
|
|
} |
220
|
194
|
|
|
|
|
1495
|
$num_dots++; |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
has 'include' => ( is => 'rw', builder => 'build_include', lazy => 1 ); |
225
|
226
|
|
|
226
|
0
|
30617
|
sub build_include { [] } |
226
|
|
|
|
|
|
|
sub has_include { |
227
|
457
|
|
|
457
|
0
|
523
|
my $self = shift; |
228
|
457
|
|
50
|
|
|
1483
|
my $include = $self->include || []; |
229
|
457
|
|
|
|
|
5366
|
return scalar @{$include}; |
|
457
|
|
|
|
|
1129
|
|
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
sub clean_fields { |
233
|
457
|
|
|
457
|
0
|
528
|
my ( $self, $fields ) = @_; |
234
|
457
|
100
|
|
|
|
1212
|
if( $self->has_include ) { |
235
|
6
|
|
|
|
|
9
|
my @fields; |
236
|
6
|
|
|
|
|
6
|
my %include = map { $_ => 1 } @{ $self->include }; |
|
16
|
|
|
|
|
126
|
|
|
6
|
|
|
|
|
12
|
|
237
|
6
|
|
|
|
|
13
|
foreach my $fld ( @$fields ) { |
238
|
16
|
100
|
|
|
|
46
|
push @fields, data_clone($fld) if exists $include{$fld->{name}}; |
239
|
|
|
|
|
|
|
} |
240
|
6
|
|
|
|
|
13
|
return \@fields; |
241
|
|
|
|
|
|
|
} |
242
|
451
|
|
|
|
|
4309
|
return data_clone( $fields ); |
243
|
|
|
|
|
|
|
}; |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
sub _make_field { |
246
|
587
|
|
|
587
|
|
646
|
my ( $self, $field_attr ) = @_; |
247
|
|
|
|
|
|
|
|
248
|
587
|
|
100
|
|
|
1999
|
my $type = $field_attr->{type} ||= 'Text'; |
249
|
587
|
|
|
|
|
634
|
my $name = $field_attr->{name}; |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
# check for a field prefixed with '+', that overrides |
252
|
587
|
|
|
|
|
504
|
my $do_update; |
253
|
587
|
100
|
|
|
|
1368
|
if ( $name =~ /^\+(.*)/ ) { |
254
|
4
|
|
|
|
|
10
|
$field_attr->{name} = $name = $1; |
255
|
4
|
|
|
|
|
7
|
$do_update = 1; |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
587
|
|
|
|
|
1721
|
my $class = $self->_find_field_class( $type, $name ); |
259
|
|
|
|
|
|
|
|
260
|
587
|
|
|
|
|
1878
|
my $parent = $self->_find_parent( $field_attr ); |
261
|
|
|
|
|
|
|
|
262
|
586
|
|
|
|
|
1556
|
my $field = $self->_update_or_create( $parent, $field_attr, $class, $do_update ); |
263
|
|
|
|
|
|
|
|
264
|
586
|
100
|
|
|
|
2221
|
$self->form->add_to_index( $field->full_name => $field ) if $self->form; |
265
|
|
|
|
|
|
|
|
266
|
586
|
|
|
|
|
1004
|
return $field; |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
sub _find_field_class { |
270
|
587
|
|
|
587
|
|
768
|
my ( $self, $type, $name ) = @_; |
271
|
|
|
|
|
|
|
|
272
|
587
|
|
|
|
|
2612
|
my $field_ns = $self->field_namespace; |
273
|
587
|
|
|
|
|
57612
|
my @classes; |
274
|
|
|
|
|
|
|
# '+'-prefixed fields could be full namespaces |
275
|
587
|
100
|
|
|
|
1438
|
if ( $type =~ s/^\+// ) { |
276
|
13
|
|
|
|
|
21
|
push @classes, $type; |
277
|
|
|
|
|
|
|
} |
278
|
587
|
|
|
|
|
995
|
foreach my $ns ( @$field_ns, 'Data::MuForm::Field' ) { |
279
|
598
|
|
|
|
|
1577
|
push @classes, $ns . "::" . $type; |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
# look for Field in possible namespaces |
282
|
587
|
|
|
|
|
532
|
my $class; |
283
|
587
|
|
|
|
|
720
|
foreach my $try ( @classes ) { |
284
|
595
|
100
|
|
|
|
567705
|
last if $class = load_optional_class($try) ? $try : undef; |
|
|
100
|
|
|
|
|
|
285
|
|
|
|
|
|
|
} |
286
|
587
|
50
|
|
|
|
30891
|
die "Could not load field class '$type' for field '$name'" |
287
|
|
|
|
|
|
|
unless $class; |
288
|
|
|
|
|
|
|
|
289
|
587
|
|
|
|
|
1241
|
return $class; |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub _find_parent { |
294
|
587
|
|
|
587
|
|
713
|
my ( $self, $field_attr ) = @_; |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
# parent and name correction for names with dots |
297
|
587
|
|
|
|
|
531
|
my $parent; |
298
|
587
|
100
|
100
|
|
|
3320
|
if ( $field_attr->{name} =~ /\./ ) { |
|
|
100
|
|
|
|
|
|
299
|
121
|
|
|
|
|
417
|
my @names = split /\./, $field_attr->{name}; |
300
|
121
|
|
|
|
|
181
|
my $simple_name = pop @names; |
301
|
121
|
|
|
|
|
230
|
my $parent_name = join '.', @names; |
302
|
|
|
|
|
|
|
# use special 'field' method call that starts from |
303
|
|
|
|
|
|
|
# $self, because names aren't always starting from |
304
|
|
|
|
|
|
|
# the form |
305
|
121
|
|
|
|
|
415
|
$parent = $self->field($parent_name, $self); |
306
|
121
|
100
|
|
|
|
793
|
if ($parent) { |
307
|
120
|
50
|
|
|
|
715
|
die "The parent of field " . $field_attr->{name} . " is not a Compound Field" |
308
|
|
|
|
|
|
|
unless $parent->isa('Data::MuForm::Field::Compound'); |
309
|
120
|
|
|
|
|
252
|
$field_attr->{name} = $simple_name; |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
else { |
312
|
1
|
|
|
|
|
56
|
die "did not find parent for field " . $field_attr->{name}; |
313
|
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
elsif ( !( $self->form && $self == $self->form ) ) { |
316
|
|
|
|
|
|
|
# set parent |
317
|
61
|
|
|
|
|
1097
|
$parent = $self; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# get full_name |
321
|
586
|
|
|
|
|
870
|
my $full_name = $field_attr->{name}; |
322
|
|
|
|
|
|
|
$full_name = $parent->full_name . "." . $field_attr->{name} |
323
|
586
|
100
|
|
|
|
2136
|
if $parent; |
324
|
586
|
|
|
|
|
1724
|
$field_attr->{full_name} = $full_name; |
325
|
586
|
|
|
|
|
803
|
return $parent; |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
sub _update_or_create { |
330
|
586
|
|
|
586
|
|
773
|
my ( $self, $parent, $field_attr, $class, $do_update ) = @_; |
331
|
|
|
|
|
|
|
|
332
|
586
|
|
66
|
|
|
1589
|
$parent ||= $self->form; |
333
|
586
|
|
|
|
|
814
|
$field_attr->{parent} = $parent; |
334
|
586
|
|
|
|
|
10264
|
$field_attr->{localizer} = $parent->localizer; |
335
|
586
|
|
|
|
|
19493
|
$field_attr->{renderer} = $parent->renderer; |
336
|
586
|
100
|
|
|
|
13095
|
$field_attr->{form} = $self->form if $self->form; |
337
|
|
|
|
|
|
|
$field_attr->{skip_fields_without_input} = $parent->skip_fields_without_input |
338
|
586
|
50
|
66
|
|
|
2716
|
if ! $self->is_form && $self->is_compound && ! exists $field_attr->{skip_fields_without_input}; |
|
|
|
66
|
|
|
|
|
339
|
586
|
|
|
|
|
1740
|
my $index = $parent->field_index( $field_attr->{name} ); |
340
|
586
|
|
|
|
|
517
|
my $field; |
341
|
586
|
100
|
|
|
|
950
|
if ( defined $index ) { |
342
|
7
|
100
|
|
|
|
16
|
if ($do_update) { # this field started with '+'. Update. |
343
|
2
|
|
|
|
|
12
|
$field = $parent->field( $field_attr->{name} ); |
344
|
2
|
50
|
|
|
|
14
|
die "Field to update for " . $field_attr->{name} . " not found" |
345
|
|
|
|
|
|
|
unless $field; |
346
|
2
|
|
|
|
|
6
|
munge_field_attr($field_attr); |
347
|
2
|
|
|
|
|
2
|
foreach my $key ( keys %{$field_attr} ) { |
|
2
|
|
|
|
|
7
|
|
348
|
18
|
100
|
100
|
|
|
1011
|
next if $key eq 'name' || $key eq 'form' || $key eq 'parent' || |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
349
|
|
|
|
|
|
|
$key eq 'full_name' || $key eq 'type'; |
350
|
8
|
50
|
|
|
|
72
|
$field->$key( $field_attr->{$key} ) |
351
|
|
|
|
|
|
|
if $field->can($key); |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
else { # replace existing field |
355
|
5
|
|
|
|
|
15
|
$field = $self->new_field( $class, $field_attr); |
356
|
5
|
|
|
|
|
27
|
$parent->set_field_at( $index, $field ); |
357
|
|
|
|
|
|
|
} |
358
|
|
|
|
|
|
|
} |
359
|
|
|
|
|
|
|
else { # new field |
360
|
579
|
|
|
|
|
1434
|
$field = $self->new_field( $class, $field_attr); |
361
|
579
|
|
|
|
|
2755
|
$parent->push_field($field); |
362
|
|
|
|
|
|
|
} |
363
|
586
|
100
|
100
|
|
|
8409
|
$field->form->add_repeatable_field($field) |
364
|
|
|
|
|
|
|
if ( $field->form && $field->is_repeatable); |
365
|
|
|
|
|
|
|
|
366
|
586
|
|
|
|
|
1175
|
return $field; |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
sub new_field { |
370
|
608
|
|
|
608
|
0
|
860
|
my ( $self, $class, $field_attr ) = @_; |
371
|
|
|
|
|
|
|
# not handling roles |
372
|
608
|
|
|
|
|
8519
|
my $field = $class->new(%$field_attr); |
373
|
608
|
|
|
|
|
16889
|
return $field; |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
sub order_fields { |
377
|
218
|
|
|
218
|
0
|
290
|
my $self = shift; |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
# number all unordered fields by 5 |
380
|
218
|
|
|
|
|
289
|
my $order = 5; |
381
|
218
|
|
|
|
|
419
|
foreach my $field ( $self->all_fields ) { |
382
|
625
|
100
|
|
|
|
1546
|
if ( $field->has_fields ) { |
383
|
71
|
|
|
|
|
231
|
$field->order_fields; |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
# fields will default to 0, so we |
386
|
|
|
|
|
|
|
# rewrite order if 0 |
387
|
625
|
100
|
|
|
|
1817
|
$field->order($order) unless $field->order; |
388
|
625
|
|
|
|
|
1594
|
$order += 5; |
389
|
|
|
|
|
|
|
} |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
sub _get_highest_field_order { |
393
|
1
|
|
|
1
|
|
7
|
my $self = shift; |
394
|
1
|
|
|
|
|
1
|
my $order = 0; |
395
|
1
|
|
|
|
|
2
|
foreach my $field ( $self->all_fields ) { |
396
|
3
|
100
|
|
|
|
17
|
$order = $field->order if $field->order > $order; |
397
|
|
|
|
|
|
|
} |
398
|
1
|
|
|
|
|
2
|
return $order; |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
# This is a special make field that's used in the Repeatable field to |
402
|
|
|
|
|
|
|
# create repeatable instances. It skips some of the overhead of _make_field |
403
|
|
|
|
|
|
|
# because some of the info can be hardcoded and we don't want to index it. |
404
|
|
|
|
|
|
|
sub _make_adhoc_field { |
405
|
24
|
|
|
24
|
|
164
|
my ( $self, $class, $field_attr ) = @_; |
406
|
24
|
|
|
|
|
55
|
my $field = $self->new_field( $class, $field_attr ); |
407
|
24
|
|
|
|
|
65
|
return $field; |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
#==================================================================== |
412
|
|
|
|
|
|
|
# Initialize input/value (InitResult) |
413
|
|
|
|
|
|
|
#==================================================================== |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
# $input here is from the $params passed in on ->process |
416
|
|
|
|
|
|
|
sub fill_from_params { |
417
|
160
|
|
|
160
|
0
|
215
|
my ( $self, $input, $exists ) = @_; |
418
|
|
|
|
|
|
|
|
419
|
160
|
|
|
|
|
405
|
$self->filled_from('params'); |
420
|
160
|
0
|
33
|
|
|
441
|
return unless ( defined $input || $exists || $self->has_fields ); |
|
|
|
33
|
|
|
|
|
421
|
|
|
|
|
|
|
# TODO - this will get replaced by setting the actual processed input 14 lines down. |
422
|
|
|
|
|
|
|
# Do we need this? Maybe could be used to transform input before processing? |
423
|
160
|
|
|
|
|
654
|
$self->transform_and_set_input($input); |
424
|
160
|
|
|
|
|
217
|
my $my_input = {}; |
425
|
160
|
50
|
|
|
|
449
|
if ( ref $input eq 'HASH' ) { |
426
|
160
|
|
|
|
|
398
|
foreach my $field ( $self->all_sorted_fields ) { |
427
|
454
|
50
|
|
|
|
796
|
next if ! $field->is_active; |
428
|
454
|
|
66
|
|
|
2106
|
my $fname = $field->input_param || $field->name; |
429
|
454
|
|
|
|
|
501
|
my $exists = exists $input->{$fname}; |
430
|
454
|
100
|
100
|
|
|
1313
|
next if ( $self->skip_fields_without_input && ! $exists && ! $field->has_input_without_param ); |
|
|
|
100
|
|
|
|
|
431
|
447
|
100
|
100
|
|
|
1318
|
if ( ! $exists && $field->disabled && ! $field->has_value ) { |
|
|
|
100
|
|
|
|
|
432
|
1
|
|
|
|
|
3
|
$field->fill_from_fields; |
433
|
|
|
|
|
|
|
} |
434
|
|
|
|
|
|
|
else { |
435
|
446
|
|
|
|
|
1694
|
$field->fill_from_params($input->{$fname}, $exists ); |
436
|
|
|
|
|
|
|
} |
437
|
447
|
100
|
|
|
|
1604
|
$my_input->{$fname} = $field->input if $field->has_input; |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
# save input for this form or compound field. Used to determine whether really 'submitted' |
441
|
|
|
|
|
|
|
# in form. This should not be used for errors or fif or anything like that. |
442
|
160
|
100
|
|
|
|
589
|
$self->input( scalar keys %$my_input ? $my_input : {}); |
443
|
160
|
|
|
|
|
298
|
return; |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
sub fill_from_object { |
447
|
95
|
|
|
95
|
0
|
285
|
my ( $self, $obj ) = @_; |
448
|
|
|
|
|
|
|
|
449
|
95
|
50
|
33
|
|
|
234
|
return unless ( $obj || $self->has_fields ); # empty fields for compounds |
450
|
95
|
|
|
|
|
213
|
$self->filled_from('object'); |
451
|
95
|
|
|
|
|
83
|
my $my_value; |
452
|
|
|
|
|
|
|
my $init_obj; |
453
|
95
|
100
|
66
|
|
|
728
|
if ( $self->form && |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
454
|
|
|
|
|
|
|
$self->form->fill_from_object_source && |
455
|
|
|
|
|
|
|
$self->form->fill_from_object_source eq 'model' && |
456
|
|
|
|
|
|
|
$self->form->has_init_values ) { |
457
|
6
|
|
|
|
|
31
|
$init_obj = $self->form->init_values; |
458
|
|
|
|
|
|
|
} |
459
|
95
|
|
|
|
|
1226
|
for my $field ( $self->all_sorted_fields ) { |
460
|
257
|
50
|
|
|
|
532
|
next if ! $field->is_active; |
461
|
257
|
100
|
100
|
|
|
4051
|
if ( (ref $obj eq 'HASH' && !exists $obj->{ $field->accessor } ) || |
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
462
|
|
|
|
|
|
|
( blessed($obj) && !$obj->can($field->accessor) ) ) { |
463
|
35
|
|
|
|
|
117
|
my $found = 0; |
464
|
|
|
|
|
|
|
|
465
|
35
|
100
|
|
|
|
65
|
if ($init_obj) { |
466
|
|
|
|
|
|
|
# if we're using a model, look for accessor not found in obj |
467
|
|
|
|
|
|
|
# in the init_values |
468
|
9
|
|
|
|
|
21
|
my @names = split( /\./, $field->full_name ); |
469
|
9
|
|
|
|
|
25
|
my $init_obj_value = $self->find_sub_obj( $init_obj, \@names ); |
470
|
9
|
100
|
|
|
|
15
|
if ( defined $init_obj_value ) { |
471
|
7
|
|
|
|
|
7
|
$found = 1; |
472
|
7
|
|
|
|
|
43
|
$field->fill_from_object( $init_obj_value ); |
473
|
|
|
|
|
|
|
} |
474
|
|
|
|
|
|
|
} |
475
|
|
|
|
|
|
|
|
476
|
35
|
100
|
|
|
|
111
|
$field->fill_from_fields() unless $found; |
477
|
|
|
|
|
|
|
} |
478
|
|
|
|
|
|
|
else { |
479
|
222
|
50
|
|
|
|
1334
|
my $value = $self->_get_value( $field, $obj ) unless $field->writeonly; |
480
|
222
|
|
|
|
|
698
|
$field->fill_from_object( $value ); |
481
|
|
|
|
|
|
|
} |
482
|
|
|
|
|
|
|
# TODO: the following doesn't work for 'input_without_param' fields like checkboxes |
483
|
|
|
|
|
|
|
# $my_value->{ $field->name } = $field->value if $field->has_value; |
484
|
257
|
|
|
|
|
945
|
$my_value->{ $field->name } = $field->value; |
485
|
|
|
|
|
|
|
} |
486
|
95
|
|
|
|
|
712
|
$self->value($my_value); |
487
|
95
|
|
|
|
|
281
|
return; |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
# for when there are no params and no init_values |
491
|
|
|
|
|
|
|
sub fill_from_fields { |
492
|
238
|
|
|
238
|
0
|
296
|
my ( $self ) = @_; |
493
|
|
|
|
|
|
|
|
494
|
238
|
|
|
|
|
818
|
$self->filled_from('fields'); |
495
|
|
|
|
|
|
|
# defaults for compounds, etc. |
496
|
238
|
100
|
|
|
|
879
|
if ( my @values = $self->get_default_value ) { |
497
|
6
|
50
|
|
|
|
816
|
my $value = @values > 1 ? \@values : shift @values; |
498
|
6
|
50
|
66
|
|
|
27
|
if( ref $value eq 'HASH' || blessed $value ) { |
499
|
6
|
|
|
|
|
121
|
return $self->fill_from_object( $value ); |
500
|
|
|
|
|
|
|
} |
501
|
0
|
0
|
|
|
|
0
|
if ( defined $value ) { |
502
|
0
|
|
|
|
|
0
|
$self->init_value($value); |
503
|
0
|
|
|
|
|
0
|
$self->value($value); |
504
|
|
|
|
|
|
|
} |
505
|
|
|
|
|
|
|
} |
506
|
232
|
|
|
|
|
251
|
my $my_value; |
507
|
232
|
|
|
|
|
808
|
for my $field ( $self->all_sorted_fields ) { |
508
|
642
|
50
|
|
|
|
3065
|
next if (!$field->is_active); |
509
|
642
|
|
|
|
|
1590
|
$field->fill_from_fields(); |
510
|
642
|
100
|
|
|
|
1782
|
$my_value->{ $field->name } = $field->value if $field->has_value; |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
# setting value here to handle disabled compound fields, where we want to |
513
|
|
|
|
|
|
|
# preserve the 'value' because the fields aren't submitted...except for the |
514
|
|
|
|
|
|
|
# form. Not sure it's the best idea to skip for form, but it maintains previous behavior |
515
|
232
|
100
|
|
|
|
759
|
$self->value($my_value) if ( keys %$my_value ); |
516
|
232
|
|
|
|
|
2580
|
return; |
517
|
|
|
|
|
|
|
} |
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
sub find_sub_obj { |
520
|
10
|
|
|
10
|
0
|
44
|
my ( $self, $obj, $field_name_array ) = @_; |
521
|
10
|
|
|
|
|
13
|
my $this_fname = shift @$field_name_array;; |
522
|
10
|
|
|
|
|
24
|
my $field = $self->field($this_fname); |
523
|
10
|
|
|
|
|
50
|
my $new_obj = $self->_get_value( $field, $obj ); |
524
|
10
|
50
|
|
|
|
23
|
if ( scalar @$field_name_array ) { |
525
|
0
|
|
|
|
|
0
|
$new_obj = $field->find_sub_obj( $new_obj, $field_name_array ); |
526
|
|
|
|
|
|
|
} |
527
|
10
|
|
|
|
|
15
|
return $new_obj; |
528
|
|
|
|
|
|
|
} |
529
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
sub _get_value { |
533
|
232
|
|
|
232
|
|
244
|
my ( $self, $field, $obj ) = @_; |
534
|
|
|
|
|
|
|
|
535
|
232
|
|
|
|
|
3041
|
my $accessor = $field->accessor; |
536
|
232
|
|
|
|
|
924
|
my @values; |
537
|
232
|
100
|
66
|
|
|
812
|
if ( blessed($obj) && $obj->can($accessor) ) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
538
|
|
|
|
|
|
|
# this must be an array, so that DBIx::Class relations are arrays not resultsets |
539
|
11
|
|
|
|
|
31
|
@values = $obj->$accessor; |
540
|
|
|
|
|
|
|
# for non-DBIC blessed object where access returns arrayref |
541
|
11
|
100
|
66
|
|
|
57
|
if ( scalar @values == 1 && ref $values[0] eq 'ARRAY' && $field->multiple ) { |
|
|
|
66
|
|
|
|
|
542
|
1
|
|
|
|
|
1
|
@values = @{$values[0]}; |
|
1
|
|
|
|
|
8
|
|
543
|
|
|
|
|
|
|
} |
544
|
|
|
|
|
|
|
} |
545
|
|
|
|
|
|
|
elsif ( exists $obj->{$accessor} ) { |
546
|
216
|
|
|
|
|
244
|
my $v = $obj->{$accessor}; |
547
|
216
|
100
|
100
|
|
|
528
|
if($field->multiple && ref($v) eq 'ARRAY'){ |
548
|
2
|
|
|
|
|
5
|
@values = @$v; |
549
|
|
|
|
|
|
|
} else { |
550
|
214
|
|
|
|
|
314
|
@values = $v; |
551
|
|
|
|
|
|
|
} |
552
|
|
|
|
|
|
|
} |
553
|
|
|
|
|
|
|
elsif ( @values = $field->get_default_value ) { |
554
|
|
|
|
|
|
|
} |
555
|
|
|
|
|
|
|
else { |
556
|
2
|
|
|
|
|
3
|
return; |
557
|
|
|
|
|
|
|
} |
558
|
230
|
100
|
|
|
|
555
|
if( $field->has_transform_default_to_value ) { |
559
|
8
|
|
|
|
|
33
|
@values = $field->transform_default_to_value->($field, @values); |
560
|
|
|
|
|
|
|
} |
561
|
230
|
|
|
|
|
212
|
my $value; |
562
|
230
|
100
|
|
|
|
352
|
if( $field->multiple ) { |
563
|
5
|
100
|
100
|
|
|
44
|
if ( scalar @values == 1 && ! defined $values[0] ) { |
|
|
100
|
100
|
|
|
|
|
564
|
1
|
|
|
|
|
2
|
$value = []; |
565
|
|
|
|
|
|
|
} |
566
|
|
|
|
|
|
|
elsif ( scalar @values == 1 && ref $values[0] eq 'ARRAY' ) { |
567
|
1
|
|
|
|
|
2
|
$value = shift @values; |
568
|
|
|
|
|
|
|
} |
569
|
|
|
|
|
|
|
else { |
570
|
3
|
|
|
|
|
4
|
$value = \@values; |
571
|
|
|
|
|
|
|
} |
572
|
|
|
|
|
|
|
} |
573
|
|
|
|
|
|
|
else { |
574
|
225
|
50
|
|
|
|
414
|
$value = @values > 1 ? \@values : shift @values; |
575
|
|
|
|
|
|
|
} |
576
|
230
|
|
|
|
|
324
|
return $value; |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
sub fields_set_value { |
581
|
103
|
|
|
103
|
0
|
133
|
my $self = shift; |
582
|
103
|
|
|
|
|
120
|
my %value_hash; |
583
|
103
|
|
|
|
|
277
|
foreach my $field ( $self->all_fields ) { |
584
|
305
|
100
|
|
|
|
1404
|
next if ! $field->is_active; |
585
|
302
|
100
|
100
|
|
|
4906
|
$value_hash{ $field->accessor } = $field->value |
586
|
|
|
|
|
|
|
if ( $field->has_value && !$field->no_update ); |
587
|
|
|
|
|
|
|
} |
588
|
103
|
|
|
|
|
854
|
$self->value( \%value_hash ); |
589
|
|
|
|
|
|
|
} |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
sub clear_data { |
593
|
133
|
|
|
133
|
0
|
405
|
my $self = shift; |
594
|
133
|
|
|
|
|
447
|
$self->clear_input; |
595
|
133
|
|
|
|
|
11363
|
$self->clear_value; |
596
|
|
|
|
|
|
|
# TODO - better way? |
597
|
133
|
100
|
|
|
|
513
|
$self->_clear_active unless $self->is_form;; |
598
|
133
|
|
|
|
|
1373
|
$self->clear_error_fields; |
599
|
133
|
|
|
|
|
347
|
$self->clear_filled_from; |
600
|
133
|
|
|
|
|
2324
|
foreach my $field ( $self->all_fields ) { |
601
|
349
|
|
|
|
|
12842
|
$field->clear_data; |
602
|
|
|
|
|
|
|
} |
603
|
|
|
|
|
|
|
} |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
# References to fields with errors are propagated up the tree. |
606
|
|
|
|
|
|
|
# All fields with errors should end up being in the form's |
607
|
|
|
|
|
|
|
# error_results. Once. |
608
|
|
|
|
|
|
|
sub propagate_error { |
609
|
81
|
|
|
81
|
0
|
587
|
my ( $self, $field ) = @_; |
610
|
|
|
|
|
|
|
|
611
|
81
|
|
|
|
|
269
|
$self->add_error_field($field); |
612
|
81
|
100
|
|
|
|
9175
|
if ( $self->parent ) { |
613
|
16
|
|
|
|
|
384
|
$self->parent->propagate_error( $field ); |
614
|
|
|
|
|
|
|
} |
615
|
|
|
|
|
|
|
} |
616
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
1; |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
__END__ |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
=pod |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
=encoding UTF-8 |
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
=head1 NAME |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
Data::MuForm::Fields - Common attributes and methods for forms and compound fields |
628
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
=head1 VERSION |
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
version 0.04 |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
=head2 NAME |
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
Data::MuForm::Fields |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
=head2 DESCRIPTION |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
This role holds things that are common to Data::MuForm and compound fields. |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
Includes code that was split up into multiple roles in FormHandler: Fields, |
642
|
|
|
|
|
|
|
BuildFields, InitResult. |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
=head1 AUTHOR |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
Gerda Shank |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
649
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
This software is copyright (c) 2017 by Gerda Shank. |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
653
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
=cut |