diff --git a/Changes b/Changes index a4a9db8d..ea5b92c2 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,24 @@ {{$NEXT}} + - Constraint when() with not(1) now applies the constraint when the + named field is missing from the submission, such as an unchecked + Checkbox. Previously a missing field caused the constraint to be + skipped regardless of not(), so default_empty_value was needed on + the Checkbox. RT#45409 + + - Behaviour change: Constraint when() with fields() now requires + every named field to be present and match. Previously a missing + field was silently ignored. + + - Fields without a name no longer emit "Use of uninitialized value" + warnings when a form is processed or rendered: an unnamed Submit or + Button with a value triggered one via force_default, and the Select, + Textarea, Checkboxgroup, Radiogroup, ContentButton and Date string + renderers emitted name="" with a warning. The name attribute is now + omitted, matching the other Input elements. RT#106557 + + - New github org: uperl + - Migrate from List::MoreUtils to List::SomeUtils - Fix CVE-2026-19873: bound the Repeatable element's counter_name diff --git a/README.pod b/README.pod index 5d828cf2..383800de 100644 --- a/README.pod +++ b/README.pod @@ -2,6 +2,14 @@ =encoding UTF-8 +=head1 NAME + +HTML::FormFu - HTML Form Creation, Rendering and Validation Framework + +=head1 VERSION + +version 2.08 + =head1 SYNOPSIS Note: These examples make use of L. As of @@ -268,6 +276,19 @@ used as the return value for L. If L is not set, L will return true if a value for any known fieldname was submitted. +=head2 repeatable_max_counter + +Arguments: $number + +Default Value: C<100> + +The default L +for all L elements in this +form. Individual Repeatable elements can override this by setting their own +L. + +Set to C<0> to disable clamping form-wide. + =head2 auto_fieldset Arguments: 1 @@ -1999,7 +2020,7 @@ Carl Franks =head1 COPYRIGHT AND LICENSE -This software is copyright (c) 2018 by Carl Franks. +This software is copyright (c) 2026, 2018, 2016, 2015, 2012, 2011 by Carl Franks. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. diff --git a/dist.ini b/dist.ini index dc89b2ee..90443583 100644 --- a/dist.ini +++ b/dist.ini @@ -2,7 +2,7 @@ name = HTML-FormFu author = Carl Franks license = Perl_5 copyright_holder = Carl Franks -copyright_year = 2021 +copyright_year = 2026 main_module = lib/HTML/FormFu.pm [Prereqs] diff --git a/lib/HTML/FormFu/Constraint.pm b/lib/HTML/FormFu/Constraint.pm index 1924b754..60518851 100644 --- a/lib/HTML/FormFu/Constraint.pm +++ b/lib/HTML/FormFu/Constraint.pm @@ -259,30 +259,22 @@ sub _process_when { croak "'fields' is set to an empty list" if !@$when_fields; for my $name (@$when_fields) { - my $value = $self->get_nested_hash_value( $params, $name ); - - push @when_fields_value, $value - if defined $value; + push @when_fields_value, + $self->get_nested_hash_value( $params, $name ); } } else { - - # nothing to constrain if field doesn't exist - my $value = $self->get_nested_hash_value( $params, $when_field ); - - push @when_fields_value, $value - if defined $value; + push @when_fields_value, + $self->get_nested_hash_value( $params, $when_field ); } + # a field missing from the submission (e.g. an unchecked Checkbox) has + # an undefined value, which is treated as not matching - so with 'not' + # set, the condition is fulfilled and the constraint is applied. RT#45409 + DEBUG_CONSTRAINTS_WHEN && debug( 'WHEN_FIELDS_VALUES' => \@when_fields_value ); - if ( !@when_fields_value ) { - DEBUG_CONSTRAINTS_WHEN - && debug("No 'when' fields values exist - returning false"); - return 0; - } - my @values; if ( defined( my $value = $when->{value} ) ) { @@ -297,12 +289,13 @@ sub _process_when { if (@values) { for my $value (@when_fields_value) { - push @ok, any { $value eq $_ } @values; + push @ok, + ( defined $value && any { $value eq $_ } @values ) ? 1 : 0; } } else { for my $value (@when_fields_value) { - push @ok, $value ? 1 : 0; + push @ok, ( defined $value && $value ) ? 1 : 0; } } @@ -492,10 +485,14 @@ Nested-name of form field that shall be checked against - if C<< when->{value} > is set, the C condition passes if the named field's value matches that, otherwise the C condition passes if the named field's value is true. +If the named field is missing from the submission altogether (as an unchecked +Checkbox is), its value is treated as not matching. + =item fields Array-ref of nested-names that shall be checked. The C condition passes if all named-fields' values pass, using the same rules as C above. +A field missing from the submission does not pass. =item any_field @@ -512,7 +509,9 @@ Array of multiple values, one must match to fulfill the condition =item not -Inverts the when condition - value(s) must not match +Inverts the when condition - value(s) must not match. A field missing from the +submission counts as not matching, so a constraint with C set is applied +when, for example, the named Checkbox is unchecked. =item callback diff --git a/lib/HTML/FormFu/Element.pm b/lib/HTML/FormFu/Element.pm index 660b1458..39c6930f 100644 --- a/lib/HTML/FormFu/Element.pm +++ b/lib/HTML/FormFu/Element.pm @@ -65,7 +65,7 @@ sub name { if ( @_ > 1 ) { - if ( $name =~ /[\.\[\]]/ ) { + if ( defined $name && $name =~ /[\.\[\]]/ ) { croak <<'ERROR_MESSAGE'; element names may not contain periods or square brackets see documentation on nested_names() for details diff --git a/lib/HTML/FormFu/Element/Checkboxgroup.pm b/lib/HTML/FormFu/Element/Checkboxgroup.pm index 5a547cd1..0c7e5825 100644 --- a/lib/HTML/FormFu/Element/Checkboxgroup.pm +++ b/lib/HTML/FormFu/Element/Checkboxgroup.pm @@ -150,6 +150,11 @@ sub _string_field { # radiogroup_tag template + my $name_attr + = defined $render->{nested_name} + ? sprintf( qq{ name="%s"}, $render->{nested_name} ) + : q{}; + my $html .= sprintf "\n", process_attrs( $render->{attributes} ); for my $option ( @{ $render->{options} } ) { @@ -174,8 +179,8 @@ sub _string_field { ; my $input = sprintf - qq{\n}, - $render->{nested_name}, + qq{\n}, + $name_attr, $render->{input_type}, $item->{value}, process_attrs( $item->{attributes} ), @@ -205,8 +210,8 @@ sub _string_field { ; my $input = sprintf - qq{\n}, - $render->{nested_name}, + qq{\n}, + $name_attr, $render->{input_type}, $option->{value}, process_attrs( $option->{attributes} ), diff --git a/lib/HTML/FormFu/Element/ContentButton.pm b/lib/HTML/FormFu/Element/ContentButton.pm index 5f5c032f..64ef1b4d 100644 --- a/lib/HTML/FormFu/Element/ContentButton.pm +++ b/lib/HTML/FormFu/Element/ContentButton.pm @@ -46,10 +46,13 @@ sub _string_field { # content_button template - my $html .= sprintf qq{