Skip to content

Commit 2dc3cfd

Browse files
committed
Constraint 'when' condition now supports new 'fields' and 'any_field' options
1 parent 21ff53d commit 2dc3cfd

6 files changed

+415
-17
lines changed

Changes

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
no other fields, was causing the block's nested_name to be added to
77
$form->valid(). RT #54967
88

9+
- Constraint 'when' condition now supports new 'fields' and 'any_field'
10+
options.
11+
912
- Bumped required version of DateTime to 0.54 - needed to pass tests under
1013
Test::More 0.96.
1114

lib/HTML/FormFu/Constraint.pm

+73-17
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use HTML::FormFu::Util qw(
1212
);
1313
use Carp qw( croak );
1414
use Clone ();
15-
use List::MoreUtils qw( any );
15+
use List::MoreUtils qw( any all );
1616
use List::Util qw( first );
1717
use Scalar::Util qw( reftype blessed );
1818

@@ -173,7 +173,7 @@ sub _process_when {
173173

174174
# returns 1 if when condition is fullfilled or not defined
175175
# returns 0 if when condition is defined and not fullfilled
176-
# If it's a callback, return callback's return value (so when
176+
# If it's a callback, return callback's return value (so 'when'
177177
# condition is met if callback returns a true value)
178178

179179
# get when condition
@@ -184,20 +184,55 @@ sub _process_when {
184184
croak "Parameter 'when' is not a hash ref" if ref $when ne 'HASH';
185185

186186
# field or callback must be defined
187-
my $when_field = $when->{field};
188-
my $when_callback = $when->{callback};
189-
croak "Parameter 'field' or 'callback' is not defined"
190-
if !defined $when_field && !defined $when_callback;
187+
my $when_field = $when->{field};
188+
my $when_fields = $when->{fields};
189+
my $when_any_field = $when->{any_field};
190+
my $when_callback = $when->{callback};
191+
192+
croak "'field', 'fields', 'any_field' or 'callback' key must be defined in 'when'"
193+
if all {!defined} $when_field, $when_fields, $when_any_field, $when_callback;
191194

192195
# Callback will be the preferred thing
193196
if ($when_callback) {
194197
no strict 'refs';
195198
return $when_callback->($params);
196199
}
200+
201+
my $any;
202+
my @when_fields_value;
203+
204+
if ($when_any_field) {
205+
croak "'any_field' is set to an empty list" if !@$when_any_field;
206+
207+
$any = 1;
208+
209+
@$when_fields = @$when_any_field;
210+
}
211+
212+
if ($when_fields) {
213+
croak "'fields' is set to an empty list" if !@$when_fields;
214+
215+
for my $name (@$when_fields) {
216+
my $value = $self->get_nested_hash_value( $params, $name );
217+
218+
push @when_fields_value, $value
219+
if defined $value;
220+
}
221+
}
222+
else {
223+
# nothing to constrain if field doesn't exist
224+
my $value = $self->get_nested_hash_value( $params, $when_field );
225+
226+
push @when_fields_value, $value
227+
if defined $value;
228+
}
197229

198-
# nothing to constrain if field doesn't exist
199-
my $when_field_value = $self->get_nested_hash_value( $params, $when_field );
200-
return 0 if !defined $when_field_value;
230+
DEBUG_CONSTRAINTS && debug('WHEN_FIELDS_VALUES' => \@when_fields_value);
231+
232+
if (!@when_fields_value) {
233+
DEBUG_CONSTRAINTS && debug("No 'when' fields values exist - returning false");
234+
return 0;
235+
}
201236

202237
my @values;
203238

@@ -209,19 +244,28 @@ sub _process_when {
209244
}
210245

211246
# determine if condition is fulfilled
212-
my $ok;
247+
my @ok;
213248

214249
if (@values) {
215-
$ok = any { $when_field_value eq $_ } @values;
250+
for my $value (@when_fields_value) {
251+
push @ok, any { $value eq $_ } @values;
252+
}
216253
}
217254
else {
218-
$ok = $when_field_value ? 1 : 0;
255+
for my $value (@when_fields_value) {
256+
push @ok, $value ? 1 : 0;
257+
}
219258
}
259+
260+
DEBUG_CONSTRAINTS && debug("'when' value matches" => \@ok);
220261

221-
# invert when condition if asked for
222-
$ok = $when->{not} ? !$ok : $ok;
223-
224-
return $ok;
262+
my $return = $any ? any { $when->{not} ? !$_ : $_ } @ok
263+
: all { $when->{not} ? !$_ : $_ } @ok
264+
;
265+
266+
DEBUG_CONSTRAINTS && debug("'when' return value" => $return);
267+
268+
return $return;
225269
}
226270

227271
sub clone {
@@ -384,7 +428,19 @@ The following keys are supported:
384428
385429
=item field
386430
387-
nested-name of form field that shall be checked against
431+
Nested-name of form field that shall be checked against - if C<when->{value}>
432+
is set, the C<when> condition passes if the named field's value matches that,
433+
otherwise the C<when> condition passes if the named field's value is true.
434+
435+
=item fields
436+
437+
Array-ref of nested-names that shall be checked. The C<when> condition passes
438+
if all named-fields' values pass, using the same rules as C<field> above.
439+
440+
=item any_field
441+
442+
Array-ref of nested-names that shall be checked. The C<when> condition passes
443+
if any named-fields' values pass, using the same rules as C<field> above.
388444
389445
=item value
390446
+182
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
use strict;
2+
use warnings;
3+
4+
use Test::More 'no_plan';
5+
6+
use HTML::FormFu;
7+
8+
my $form = HTML::FormFu->new;
9+
10+
$form->load_config_file('t/constraints/constraint_when_any_field.yml');
11+
12+
#$ENV{HTML_FORMFU_DEBUG_PROCESS} = 1;
13+
14+
# Valid
15+
{
16+
$form->process( {
17+
a => '',
18+
b => '',
19+
c => '',
20+
d => '',
21+
} );
22+
23+
ok( $form->submitted_and_valid );
24+
25+
ok( $form->valid('a'), 'a valid' );
26+
ok( $form->valid('b'), 'b valid' );
27+
ok( $form->valid('c'), 'c valid' );
28+
ok( $form->valid('d'), 'd valid' );
29+
}
30+
31+
# Valid
32+
{
33+
$form->process( {
34+
a => '1',
35+
b => '',
36+
c => '',
37+
d => '',
38+
} );
39+
40+
ok( $form->submitted_and_valid );
41+
42+
ok( $form->valid('a'), 'a valid' );
43+
ok( $form->valid('b'), 'b valid' );
44+
ok( $form->valid('c'), 'c valid' );
45+
ok( $form->valid('d'), 'd valid' );
46+
}
47+
48+
# Valid
49+
{
50+
$form->process( {
51+
a => '',
52+
b => '1',
53+
c => '',
54+
d => '',
55+
} );
56+
57+
ok( $form->submitted_and_valid );
58+
59+
ok( $form->valid('a'), 'a valid' );
60+
ok( $form->valid('b'), 'b valid' );
61+
ok( $form->valid('c'), 'c valid' );
62+
ok( $form->valid('d'), 'd valid' );
63+
}
64+
65+
# Valid
66+
{
67+
$form->process( {
68+
a => '',
69+
b => '',
70+
c => '1',
71+
d => '',
72+
} );
73+
74+
ok( $form->submitted_and_valid );
75+
76+
ok( $form->valid('a'), 'a valid' );
77+
ok( $form->valid('b'), 'b valid' );
78+
ok( $form->valid('c'), 'c valid' );
79+
ok( $form->valid('d'), 'd valid' );
80+
}
81+
82+
# Valid
83+
{
84+
$form->process( {
85+
a => '',
86+
b => '',
87+
c => '',
88+
d => '1',
89+
} );
90+
91+
ok( $form->submitted_and_valid );
92+
93+
ok( $form->valid('a'), 'a valid' );
94+
ok( $form->valid('b'), 'b valid' );
95+
ok( $form->valid('c'), 'c valid' );
96+
ok( $form->valid('d'), 'd valid' );
97+
}
98+
99+
# Valid
100+
{
101+
$form->process( {
102+
a => '1',
103+
b => '1',
104+
c => '',
105+
d => '',
106+
} );
107+
108+
ok( $form->submitted_and_valid );
109+
110+
ok( $form->valid('a'), 'a valid' );
111+
ok( $form->valid('b'), 'b valid' );
112+
ok( $form->valid('c'), 'c valid' );
113+
ok( $form->valid('d'), 'd valid' );
114+
}
115+
116+
# Valid
117+
{
118+
$form->process( {
119+
a => '',
120+
b => '1',
121+
c => '1',
122+
d => '',
123+
} );
124+
125+
ok( $form->submitted_and_valid );
126+
127+
ok( $form->valid('a'), 'a valid' );
128+
ok( $form->valid('b'), 'b valid' );
129+
ok( $form->valid('c'), 'c valid' );
130+
ok( $form->valid('d'), 'd valid' );
131+
}
132+
133+
# Invalid
134+
{
135+
$form->process( {
136+
a => '1',
137+
b => '1',
138+
c => '1',
139+
d => '',
140+
} );
141+
142+
ok( !$form->submitted_and_valid );
143+
144+
ok( !$form->valid('a'), 'a not valid' );
145+
ok( $form->valid('b'), 'b valid' );
146+
ok( $form->valid('c'), 'c valid' );
147+
ok( $form->valid('d'), 'd valid' );
148+
}
149+
150+
# Invalid
151+
{
152+
$form->process( {
153+
a => '',
154+
b => '1',
155+
c => '1',
156+
d => '1',
157+
} );
158+
159+
ok( !$form->submitted_and_valid );
160+
161+
ok( !$form->valid('a'), 'a not valid' );
162+
ok( $form->valid('b'), 'b valid' );
163+
ok( $form->valid('c'), 'c valid' );
164+
ok( $form->valid('d'), 'd valid' );
165+
}
166+
167+
# Invalid
168+
{
169+
$form->process( {
170+
a => '1',
171+
b => '1',
172+
c => '1',
173+
d => '1',
174+
} );
175+
176+
ok( !$form->submitted_and_valid );
177+
178+
ok( !$form->valid('a'), 'a not valid' );
179+
ok( $form->valid('b'), 'b valid' );
180+
ok( $form->valid('c'), 'c valid' );
181+
ok( $form->valid('d'), 'd valid' );
182+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
elements:
3+
- name: a
4+
constraints:
5+
- type: MinMaxFields
6+
min: 1
7+
max: 2
8+
others:
9+
- 'b'
10+
- 'c'
11+
- 'd'
12+
when:
13+
any_field:
14+
- 'a'
15+
- 'b'
16+
- 'c'
17+
- 'd'
18+
19+
- name: b
20+
21+
- name: c
22+
23+
- name: d

0 commit comments

Comments
 (0)