The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

App::ZofCMS::Plugin::FormChecker - plugin to check HTML form data.

SYNOPSIS

In ZofCMS template or main config file:

    plugins => [ qw/FormChecker/ ],
    plug_form_checker => {
        trigger     => 'some_param',
        ok_key      => 't',
        ok_code     => sub { die "All ok!" },
        fill_prefix => 'form_checker_',
        rules       => {
            param1 => 'num',
            param2 => qr/foo|bar/,
            param3 => [ qw/optional num/ ],
            param4 => {
                optional        => 1,
                select          => 1,
                must_match      => qr/foo|bar/,
                must_not_match  => qr/foos/,
                must_match_error => 'Param4 must contain either foo or bar but not foos',
                param           => 'param2',
            },
            param5 => {
                valid_values        => [ qw/foo bar baz/ ],
                valid_values_error  => 'Param5 must be foo, bar or baz',
            },
            param6 => sub { time() % 2 }, # return true or false values
        },
    },

In your HTML::Template template:

    <tmpl_if name="plug_form_checker_error">
        <p class="error"><tmpl_var name="plug_form_checker_error"></p>
    </tmpl_if>

    <form ......

DESCRIPTION

The module is a plugin for App::ZofCMS that provides nifteh form checking.

This documentation assumes you've read App::ZofCMS, App::ZofCMS::Config and App::ZofCMS::Template

ZofCMS TEMPLATE/MAIN CONFIG FILE FIRST LEVEL KEYS

The keys can be set either in ZofCMS template or in Main Config file, if same keys are set in both, then the one in ZofCMS template takes precedence.

plugins

    plugins => [ qw/FormChecker/ ],

You obviously would want to include the plugin in the list of plugins to execute.

plug_form_checker

    # keys are listed for demostrative purposes,
    # some of these don't make sense when used together
    plug_form_checker => {
        trigger     => 'plug_form_checker',
        ok_key      => 'd',
        ok_redirect => '/some-page',
        fail_code   => sub { die "Not ok!" },
        ok_code     => sub { die "All ok!" },
        no_fill     => 1,
        fill_prefix => 'plug_form_q_',
        rules       => {
            param1 => 'num',
            param2 => qr/foo|bar/,
            param3 => [ qw/optional num/ ],
            param4 => {
                optional        => 1,
                select          => 1,
                must_match      => qr/foo|bar/,
                must_not_match  => qr/foos/,
                must_match_error => 'Param4 must contain either foo or bar but not foos',
            },
            param5 => {
                valid_values        => [ qw/foo bar baz/ ],
                valid_values_error  => 'Param5 must be foo, bar or baz',
            },
            param6 => sub { time() % 2 }, # return true or false values
        },
    },

The plug_form_checker first-level key takes a hashref as a value. Only the rules key is mandatory, the rest are optional. The possible keys/values of that hashref are as follows.

trigger

    trigger => 'plug_form_checker',

Optional. Takes a string as a value that must contain the name of the query parameter that would trigger checking of the form. Generally, it would be some parameter of the form you are checking (that would always contain true value, in perl's sense of true) or you could always use <input type="hidden" name="plug_form_checker" value="1">. Defaults to: plug_form_checker

ok_key

    ok_key => 'd',

Optional. If the form passed all the checks plugin will set a second level key plug_form_checker_ok to a true value. The ok_key parameter specifies the first level key in ZofCMS template where to put the plug_form_checker key. For example, you can set ok_key to 't' and then in your HTML::Template template use <tmpl_if name="plug_form_checker_ok">FORM OK!</tmpl_if>... but, beware of using the 't' key when you are also using App::ZofCMS::QueryToTemplate plugin, as someone could avoid proper form checking by passing fake query parameter. Defaults to: d ("data" ZofCMS template special key).

ok_redirect

    ok_redirect => '/some-page',

Optional. If specified, the plugin will automatically redirect the user to the URL specified as a value to ok_redirect key. Note that the plugin will exit() right after printing the redirect header. By default not specified.

ok_code

    ok_code => sub {
        my ( $template, $query, $config ) = @_;
        $template->{t}{foo} = "Kewl!";
    }

Optional. Takes a subref as a value. When specfied that subref will be executed if the form passes all the checks. The @_ will contain the following (in that order): hashref of ZofCMS Template, hashref of query parameters and App::ZofCMS::Config object. By default is not specified. Note: if you specify ok_code and ok_redirect the code will be executed and only then user will be redirected.

fail_code

    fail_code => sub {
        my ( $template, $query, $config, $error ) = @_;
        $template->{t}{foo} = "We got an error: $error";
    }

Optional. Takes a subref as a value. When specfied that subref will be executed if the form fails any of the checks. The @_ will contain the following (in that order): hashref of ZofCMS Template, hashref of query parameters, App::ZofCMS::Config object and (if the all_errors is set to a false value) the scalar contain the error that would also go into {t}{plug_form_checker_error} in ZofCMS template; if all_errors is set to a true value, than $error will be an arrayref of hashrefs that have only one key - error, value of which is the error message. By default is not specified.

all_errors

    all_errors => 1,

Optional. Takes either true or false values. When set to a false value plugin will stop processing as soon as it finds the first error and will report it to the user. When set to a true value will find all errors and report all of them; see HTML::Template VARIABLES section below for samples. Defaults to: 0

no_fill

    no_fill => 1,

Optional. When set to a true value plugin will not fill query values. Defaults to: 0. When no_fill is set to a false value the plugin will fill in ZofCMS template's {t} special key with query parameter values (only the ones that you are checking, though, see rules key below). This allows you to fill your form with values that user already specified in case the form check failed. The names of the keys inside the {t} key will be formed as follows: $prefix . $query_param_name where $prefix is the value of fill_prefix key (see below) and $query_param_name is the name of the query parameter. Of course, this alone wouldn't cut it for radio buttons or <select> elements. For that, you need to set select => 1 in the ruleset for that particular query parameter (see rules key below); when select rule is set to a true value then the names of the keys inside the {t} key will be formed as follows: $prefix . $query_param_name . '_' . $value. Where the $prefix is the value of fill_prefix key, $query_param_name is the name of the query parameter; following is the underscore (_) and then $value that is the value of the query parameter. Consider the following snippet in ZofCMS template and corresponding HTML::Template HTML code as an example:

    plug_form_checker => {
        trigger => 'foo',
        fill_prefix => 'plug_form_q_',
        rules => { foo => { select => 1 } },
    }

    <form action="" method="POST">
        <input type="text" name="bar" value="<tmpl_var name="plug_form_q_">">
        <input type="radio" name="foo" value="1"
            <tmpl_if name="plug_form_q_foo_1"> checked </tmpl_if>
        >
        <input type="radio" name="foo" value="2"
            <tmpl_if name="plug_form_q_foo_2"> checked </tmpl_if>
        >
    </form>

fill_prefix

    fill_prefix => 'plug_form_q_',

Optional. Specifies the prefix to use for keys in {t} ZofCMS template special key when no_fill is set to a false value. The "filling" is described above in no_fill description. Defaults to: plug_form_q_ (note the underscore at the very end)

rules

        rules       => {
            param1 => 'num',
            param2 => qr/foo|bar/,
            param3 => [ qw/optional num/ ],
            param4 => {
                optional        => 1,
                select          => 1,
                must_match      => qr/foo|bar/,
                must_not_match  => qr/foos/,
                must_match_error => 'Param4 must contain either foo or bar but not foos',
            },
            param5 => {
                valid_values        => [ qw/foo bar baz/ ],
                valid_values_error  => 'Param5 must be foo, bar or baz',
            },
            param6 => sub { time() % 2 }, # return true or false values
        },

This is the "heart" of the plugin, the place where you specify the rules for checking. The rules key takes a hashref or a subref as a value. If the value is a subref, its @_ will contain (in that order) ZofCMS Template hashref, query parameters hashref and App::ZofCMS::Config object. The return value of the subref will be assigned to rules parameter and therefore must be a hashref; alternatively the sub may return an undef, in which case the plugin will stop executing.

The keys of rules hashref are the names of the query parameters that you wish to check. The values of those keys are the "rulesets". The values can be either a string, regex (qr//), arrayref, subref, scalarref or a hashref; If the value is NOT a hashref it will be changed into hashref as follows (the actual meaning of resulting hashrefs is described below):

a string

    param => 'num',
    # same as
    param => { num => 1 },

a regex

    param => qr/foo/,
    # same as
    param => { must_match => qr/foo/ },

an arrayref

    param => [ qw/optional num/ ],
    # same as
    param => {
        optional => 1,
        num      => 1,
    },

a subref

    param => sub { time() % 2 },
    # same as
    param => { code => sub { time() % 2 } },

a scalarref

    param => \'param2',
    # same as
    param => { param => 'param2' },

rules RULESETS

The rulesets (values of rules hashref) have keys that define the type of the rule and value defines diffent things or just indicates that the rule should be considered. Here is the list of all valid ruleset keys:

    rules => {
        param => {
            name            => 'Parameter', # the name of this param to use in error messages
            num             => 1, # value must be numbers-only
            optional        => 1, # parameter is optional
            either_or       => [ qw/foo bar baz/ ], # param or foo or bar or baz must be set
            must_match      => qr/foo/, # value must match given regex
            must_not_match  => qr/bar/, # value must NOT match the given regex
            max             => 20, # value must not exceed 20 characters in length
            min             => 3,  # value must be more than 3 characters in length
            valid_values    => [ qw/foo bar baz/ ], # value must be one from the given list
            code            => sub { time() %2 }, # return from the sub determines pass/fail
            select          => 1, # flag for "filling", see no_fill key above
            param           => 'param1',
            num_error       => 'Numbers only!', # custom error if num rule failed
            mandatory_error => '', # same for if parameter is missing and not optional.
            must_match_error => '', # same for must_match rule
            must_not_match_error => '', # same for must_not_match_rule
            max_error            => '', # same for max rule
            min_error            => '', # same for min rule
            code_error           => '', # same for code rule
            either_or_error      => '', # same for either_or rule
            valid_values_error   => '', # same for valid_values rule
            param_error          => '', # same fore param rule
        },
    }

You can mix and match the rules for perfect tuning.

name

    name => 'Decent name',

This is not actually a rule but the text to use for the name of the parameter in error messages. If not specified the actual parameter name - on which ucfirst() will be run - will be used.

num

    num => 1,

When set to a true value the query parameter's value must contain digits only.

optional

    optional => 1,

When set to a true value indicates that the parameter is optional. Note that you can specify other rules along with this one, e.g.:

    optional => 1,
    num      => 1,

Means, query parameter is optional, but if it is given it must contain only digits.

either_or

    optional    => 1, # must use this
    either_or   => 'foo',

    optional    => 1, # must use this
    either_or   => [ qw/foo bar baz/ ],

The optional rul must be set to a true value in order for either_or rule to work. The rule takes either a string or an arrayref as a value. Specifying a string as a value is the same as specifying a hashref with just that string in it. Each string in an arrayref represents the name of a query parameter. In order for the rule to succeed either one of the parameters must be set. It's a bit messy, but you must use the optional rule as well as list the either_or rule for every parameter that is tested for "either or" rule.

must_match

    must_match => qr/foo/,

Takes a regex (qr//) as a value. The query parameter's value must match this regex.

must_not_match

    must_not_match => qr/bar/,

Takes a regex (qr//) as a value. The query parameter's value must NOT match this regex.

max

    max => 20,

Takes a positive integer as a value. Query parameter's value must not exceed max characters in length.

min

    min => 3,

Takes a positive integer as a value. Query parameter's value must be at least min characters in length.

valid_values

    valid_values => [ qw/foo bar baz/ ],

Takes an arrayref as a value. Query parameter's value must be one of the items in the arrayref.

code

    code => sub { time() %2 },

Here you can let your soul dance to your desire. Takes a subref as a value. The @_ will contain the following (in that order): - the value of the parameter that is being tested, the hashref of ZofCMS Template, hashref of query parameters and the App::ZofCMS::Config object. If the sub returns a true value - the check will be considered successfull. If the sub returns a false value, then test fails and form check stops and errors.

param

    param => 'param2',

Takes a string as an argument; that string will be interpreted as a name of a query parameter. Values of the parameter that is currently being inspected and the one given as a value must match in order for the rule to succeed. The example above indicates that query parameter param eq query parameter param2.

select

    select => 1,

This one is not actually a "rule". This is a flag for {t} "filling" that is described in great detail (way) above under the description of no_fill key.

CUSTOM ERROR MESSAGES IN RULESETS

All *_error keys take strings as values; they can be used to set custom error messages for each test in the ruleset. In the defaults listed below under each *_error, the $name represents either the name of the parameter or the value of name key that you set in the ruleset.

num_error

    num_error => 'Numbers only!',

This will be the error to be displayed if num test fails. Defaults to Parameter $name must contain digits only.

mandatory_error

    mandatory_error => 'Must gimme!',

This is the error when optional is set to a false value, which is the default, and user did not specify the query parameter. I.e., "error to display for missing mandatory parameters". Defaults to: You must specify parameter $name

must_match_error

    must_match_error => 'Must match me!',

This is the error for must_match rule. Defaults to: Parameter $name contains incorrect data

must_not_match_error

    must_not_match_error => 'Cannot has me!',

This is the error for must_not_match rule. Defaults to: Parameter $name contains incorrect data

max_error

    max_error => 'Too long!',

This is the error for max rule. Defaults to: Parameter $name cannot be longer than $max characters where $max is the max rule's value.

min_error

    min_error => 'Too short :(',

This is the error for min rule. Defaults to: Parameter $name must be at least $rule-{min} characters long>

code_error

    code_error => 'No likey 0_o',

This is the error for code rule. Defaults to: Parameter $name contains incorrect data

either_or_error

    either_or_error => "You must specify either Foo or Bar",

This is the error for either_or rule. Defaults to: Parameter $name must contain data if other parameters are not set

valid_values_error

    valid_values_error => 'Pick the correct one!!!',

This is the error for valid_values rule. Defaults to: Parameter $name must be $list_of_values where $list_of_values is the list of the values you specified in the arrayref given to valid_values rule joined by commas and the last element joined by word "or".

param_error

    param_error => "Two passwords do not match",

This is the error for param rule. You pretty much always would want to set a custom error message here as it defaults to: Parameter $name does not match parameter $rule->{param} where $rule->{param} is the value you set to param rule.

HTML::Template VARIABLES

    <tmpl_if name="plug_form_checker_error">
        <p class="error"><tmpl_var name="plug_form_checker_error"></p>
    </tmpl_if>

    # or, if 'all_errors' is turned on:
    <tmpl_if name="plug_form_checker_error">
        <tmpl_loop name="plug_form_checker_error">
            <p class="error"><tmpl_var name="error"></p>
        </tmpl_loop>
    </tmpl_if>

If the form values failed any of your checks, the plugin will set plug_form_checker_error key in {t} special key explaining the error. If all_errors option is turned on, then the plugin will set plug_form_checker_error to a data structure that you can feed into <tmpl_loop name=""> where the <tmpl_var name="error"> will be replaced with the error message. The sample usage of this is presented above.

AUTHOR

'Zoffix, <'zoffix at cpan.org'> (http://zoffix.com/, http://haslayout.net/, http://zofdesign.com/)

Patches by Simon aka jonsmith1982

BUGS

Please report any bugs or feature requests to bug-app-zofcms-plugin-formchecker at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=App-ZofCMS-Plugin-FormChecker. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc App::ZofCMS::Plugin::FormChecker

You can also look for information at:

COPYRIGHT & LICENSE

Copyright 2008 'Zoffix, all rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.