[html-formfu] HTML::FormFu::Constraint::Dynamic for review

Mario Minati mario.minati at googlemail.com
Sun Sep 9 17:20:25 GMT 2007


Hi @all,

just another module for review.

I have to constraint a textfield depending on the value of an associated 
select field. In my case either a telephone or fax number or an email address 
or maybe later on an icq or skype address.

This brought me to the idea to create a dynamic constraint which loads the 
needed constraints later on.

At the moment if got the feeling it's more like a hack of FormFu. Maybe some 
has an idea to run it smoother with the FormFu structure.

Parameters:
- dynamic_field: the name of the form field that's values are taken inti 
account
- dynamic: the structure defining the values and it's specific constraints and 
the message that will be shown
- force: dynamic gives an error itself if the value of dynamic_field is not 
contained in the parameter dynamic'
- message: shown when the value is not found in the parameter dynamic'

What I have in my configfile:
      - type: Text
        name: data
        label: Value
        size: 50
        constraints:
          - Required
          - Printable
          - Dynamic
            dynamic_field: type_id
            dynamic:
              1:
                constraints:
                  - type: Regex
                    regex: '\d'
                message: not a valid telefax number
              2:
                constraints:
                  - type: Email
                message: not a valid email address
              3:
                constraints:
                  - type: Regex
                    common:
                     - URI
                     - tel
                     - nofuture
                message: not a valid telehone number
              4:
                constraints:
                  - type: Regex
                    common:
                     - URI
                     - tel
                     - nofuture
                message: not a valid mobile phone number
            force: 1
            message: type of input could not be determined

Below the code.

Greets,
Mario

###################################
package HTML::FormFu::Constraint::Dynamic;

use strict;
use base 'HTML::FormFu::Constraint';
use HTML::FormFu::ObjectUtil
    qw/
        _require_constraint
    /;

__PACKAGE__->mk_accessors(
    qw/
        dynamic_field
        dynamic
        force
    /
);

sub process {
    my ( $self, $params ) = @_;

    # we need the dynamic field parameter
    my $dynamic_field = $self->dynamic_field;
    return if !defined $dynamic_field;

    # the dynamic_field param must exist
    return if !exists $params->{$dynamic_field};
    my $dynamic_value = $params->{$dynamic_field};

    # do we force a known value
    my $force = $self->force;

    # we need dynamic data
    my $dynamic_definition = $self->dynamic;
    if (!defined $dynamic_definition) {
        # error if we force a known value
        if ($force) {
            return $self->mk_errors( {
                    pass => 0,
                    message  => $self->message,
                } );
        }
        # nothing to do
        return;
    }

    # Reorganize data by value
    my $constrain_values = $dynamic_definition;
#    map {
#        $constrain_values->{ delete $_->{value} } = {
#            constraint => delete $_->{constraints},
#            message    => delete $_->{message}
#        } } @$dynamic_definition;

    # if the value is unknown
# TODO: $dynamic_value is tainted - rewrite for 'eq'-compare
    if (!defined $constrain_values->{ $dynamic_value }) {
        # error if we force a known value
        if ($force) {
            return $self->mk_errors( {
                    pass => 0,
                    message  => $self->message,
                } );
        }
        # nothing to do
        return;
    }

    # create constraints
    my @constraints;
    foreach my $constraint_data
        ( @{ $constrain_values->{ $dynamic_value }->{constraints} } ) {
# CAVEAT: the css class is dynmaic_error, not xxx_error

        # create constraint and correct parent
        my $constraint = $self->_require_constraint(
            delete $constraint_data->{type}, $constraint_data );
        $constraint->{parent} = $self->{parent};
        push @constraints, $constraint;
    }

    # run constraints
    my @errors;
    foreach my $constraint ( @constraints ) {
        my @constraint_errors = eval { $constraint->process( $params ); };
        push @errors, @constraint_errors;
    }

    # replace my message string with specific one
    $self->message( $constrain_values->{ $dynamic_value }->{message} );
# CAVEAT: Doesn't use any messages from the sub constraints

    return @errors;
}

1;

__END__



More information about the HTML-FormFu mailing list