package Catalyst::Plugin::FormValidator::Simple; use strict; use base qw/Catalyst::Plugin::FormValidator/; # doesn't use parent module at all, but this is required for Catalyst::Plugin::FillInForm use MRO::Compat; require FormValidator::Simple; our $VERSION = '0.15'; sub setup { my $self = shift; $self->maybe::next::method(@_); my $setting = $self->config->{validator}; my $plugins = $setting && exists $setting->{plugins} ? $setting->{plugins} : []; FormValidator::Simple->import(@$plugins); if ( $setting && exists $setting->{messages} ) { FormValidator::Simple->set_messages( $setting->{messages} ); } if ( $setting && exists $setting->{options} ) { FormValidator::Simple->set_option( %{ $setting->{options} } ); } if ( $setting && exists $setting->{message_format} ) { FormValidator::Simple->set_message_format( $setting->{message_format} ); } if ( $setting && exists $setting->{message_decode_from} ) { FormValidator::Simple->set_message_decode_from( $setting->{message_decode_from} ); } } sub prepare { my $c = shift; $c = $c->maybe::next::method(@_); $c->{validator} = FormValidator::Simple->new; return $c; } sub form { my $c = shift; if ($_[0]) { my $form = $_[1] ? [@_] : $_[0]; $c->{validator}->check($c->req, $form); } return $c->{validator}->results; } sub set_invalid_form { my $c = shift; $c->{validator}->set_invalid(@_); return $c->{validator}->results; } 1; __END__ =head1 NAME Catalyst::Plugin::FormValidator::Simple - Validator for Catalyst with FormValidator::Simple =head1 SYNOPSIS use Catalyst qw/FormValidator::Simple FillInForm/; # set option MyApp->config->{validator} = { plugins => ['CreditCard', 'Japanese'], options => { charset => 'euc'}, } in your controller sub defaulti : Private { my ($self, $c) = @_; $c->form( param1 => [qw/NOT_BLANK ASCII/, [qw/LENGTH 4 10/]], param2 => [qw/NOT_BLANK/, [qw/JLENGTH 4 10/]], mail1 => [qw/NOT_BLANK EMAIL_LOOSE/], mail2 => [qw/NOT_BLANK EMAIL_LOOSE/], { mail => [qw/mail1 mail2/] } => ['DUPLICATION'], ); print $c->form->valid('param1'); if ( some condition... ) { $c->form( other_param => [qw/NOT_INT/], ); } if ( some condition... ) { # set your original invalid type. $c->set_invalid_form( param3 => 'MY_ERROR' ); } if ( $c->form->has_error ) { if ( $c->form->missing('param1') ) { ... } if ( $c->form->invalid( param1 => 'ASCII' ) ) { ... } if ( $c->form->invalid( param3 => 'MY_ERROR' ) ) { ... } } } =head1 DESCRIPTION This plugin allows you to validate request parameters with FormValidator::Simple. See L for more information. This behaves like as L. =head1 CONFIGURATION set config with 'validator' key. MyApp->config->{validator} = { ... }; or MyApp->config( validator => { ... }, ); =head2 PLUGINS If you want to use some plugins for FormValidator::Simple, you can set like following. MyApp->config( validator => { plugins => [qw/Japanese CreditCard DBIC::Unique/], }, ); In this example, FormValidator::Simple::Plugin::Japanese, FormValidator::Simple::Plugin::CreditCard, and FormValidator::Simple::Plugin::DBIC::Unique are loaded. =head2 OPTIONS When you set some options needed by specific validations, do like this. MyApp->config( validator => { plugins => [qw/Japanese CreditCard DBIC::Unique/], options => { charset => 'euc', dbic_base_class => 'MyApp::Model::DBIC', }, }, ); 'charset' is necessary for Plugin::Japanese, and 'dbic_cbase_class' is used in Plugin::DBIC::Unique. =head1 VALIDATION use 'form' method, see L in detail. sub do_add : Local { my ( $self, $c ) = @_; # execute validation. $c->form( name => [qw/NOT_BLANK ASCII/, [qw/LENGTH 0 20/] ], email => [qw/NOT_BLANK EMAIL_LOOSE/, [qw/LENGTH 0 20/] ], { unique => [qw/name email/] } => [qw/DBIC_UNIQUE User name email/], ); if ( ... ) { # execute validation one more time in specific condition. $c->form( ... ); } # See Catalyst::Plugin::RequestToken for '$c->validate_token' if ( $c->validate_token ) { # you can force to set invalid data. $c->set_invalid_form( token => 'TOKEN' ); } # check result. # you can pick up result-object with 'form' method my $result = $c->form; if ( $result->has_error ) { # this is same as # if ( $result->has_missing or $result->has_invalid ) $c->detach('add'); } } =head1 HANDLING SUCCESSFUL RESULT After it passes all validations, you may wanna put input-data into database. It's a elegant way to use [ L and L ] or [ L and L ]. sub do_add : Local { my ( $self, $c ) = @_; $c->form( name => [qw/NOT_BLANK/], email => [qw/NOT_BLANK/], ); my $result = $c->form; if ( $result->has_error ) { $c->detach('add'); } my $user = MyProj::Model::DBIC::User->create_from_form($result); # this behaves like this... # MyProj::Model::DBIC::User->create({ # name => $result->valid('name'), # email => $result->valid('email'), # }); # # if the key exists as the table's column, set the value with 'valid' } Here, I explain about 'valid' method. If the value indicated with key-name passes validations, You can get the data with 'valid', my $result = $c->form( name => [qw/NOT_BLANK/], email => [qw/NOT_BLANK/], ); print $result->valid('name'); print $result->valid('email'); But, this is for only single key validation normally. my $result = $c->form( name => [qw/NOT_BLANK/], # single key validation { mail_dup => [qw/email email2/] } => ['DUPLICATION'] # multiple keys one ); print $result->valid('name'); # print out the value of 'name' print $result->valid('mail_dup'); # no value. There are exceptions. These are 'DATETIME', 'DATE'. my $result = $c->form( { created_on => [qw/created_year created_month created_day/] } => [qw/DATETIME/], ); print $result->valid('created_on'); #print out datetime string like "2005-11-23 00:00:00". If you set some class around datetime in configuration. It returns object of the class you indicate. You can choose from L and L. For example... MyApp->config( validator => { plugins => [...], options => { datetime_class => 'Time::Piece', }, }, ); or MyApp->config( validator => { plugins => [...], options => { datetime_class => 'DateTime', time_zone => 'Asia/Tokyo', }, }, ); then my $result = $c->form( { created_on => [qw/created_year created_month created_day/] } => [qw/DATETIME/], ); my $dt = $result->valid('created_on'); print $dt->ymd; MyProj::Model::CDBI::User->create_from_form($result); This may be useful when you define 'has_a' relation for datetime columns. For example, in your table class inherits 'Class::DBI' __PACKAGE__->has_a( created_on => 'DateTime', inflate => ..., deflate => ..., ); And see also L, L. =head1 MESSAGE HANDLING in template file, you can handle it in detail. [% IF c.form.has_error %]

Input Error

    [% IF c.form.missing('name') %]
  • input name!
  • [% END %] [% IF c.form.invalid('name') %]
  • name is wrong
  • [% END %] [% IF c.form.invalid('name', 'ASCII') %]
  • input name with ascii code.
  • [% END %] [% IF c.form.invalid('name', 'LENGTH') %]
  • wrong length for name.
  • [% END %]
[% END %] or, make it more easy. [% IF c.form.has_error %]

Input Error

    [% FOREACH key IN c.form.error %] [% FOREACH type IN c.form.error(key) %]
  • Invalid: [% key %] - [% type %]
  • [% END %] [% END %] [% END %] And you can also use messages configuration as hash reference. MyApp->config( validator => { plugins => [...], messages => { user => { name => { NOT_BLANK => 'Input name!', ASCII => 'Input name with ascii code!', }, email => { DEFAULT => 'email is wrong.!', NOT_BLANK => 'input email.!' }, }, company => { name => { NOT_BLANK => 'Input name!', }, }, }, }, ); or YAML file. set file name MyApp->config( validator => { plugins => [...], messages => 'conf/messages.yml', }, ); and prepare yaml file like following, DEFAULT: name: DEFAULT: name is invalid user: name: NOT_BLANK: Input name! ASCII: Input name with ascii code! email: DEFAULT: Email is wrong! NOT_BLANK: Input email! company: name: NOT_BLANK: Input name! the format is... Action1_Name: Key1_Name: Validation1_Name: Message Validation2_Name: Message Key2_Name: Validation1_Name: Message Action2_Name: Key1_Name: ... After messages configuration, call messages() method from result-object. and set action-name as argument. [% IF c.form.has_error %]
      [% FOREACH message IN c.form.messages('user') %]
    • [% message %]
    • [% END %]
    [% END %] you can set each message format MyApp->config( validator => { messages => 'messages.yml', message_format => '

    %s

    ' }, ); [% IF c.form.has_error %] [% c.form.messages('user').join("\n") %] [% END %] =head1 SEE ALSO L L =head1 AUTHOR Lyo Kato Elyo.kato@gmail.comE =head1 COPYRIGHT AND LICENSE Copyright(C) 2005 by Lyo Kato This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut