version bump, changelog update
[catagits/Catalyst-Plugin-FormValidator-Simple.git] / lib / Catalyst / Plugin / FormValidator / Simple.pm
CommitLineData
04abc0cc 1package Catalyst::Plugin::FormValidator::Simple;
2use strict;
3use base qw/Catalyst::Plugin::FormValidator/;
4# doesn't use parent module at all, but this is required for Catalyst::Plugin::FillInForm
5
3176e564 6use MRO::Compat;
04abc0cc 7require FormValidator::Simple;
8
7b5056fe 9our $VERSION = '0.15';
04abc0cc 10
11sub setup {
12 my $self = shift;
3176e564 13 $self->maybe::next::method(@_);
04abc0cc 14 my $setting = $self->config->{validator};
15 my $plugins = $setting && exists $setting->{plugins}
16 ? $setting->{plugins}
17 : [];
18 FormValidator::Simple->import(@$plugins);
19 if ( $setting && exists $setting->{messages} ) {
20 FormValidator::Simple->set_messages( $setting->{messages} );
21 }
22 if ( $setting && exists $setting->{options} ) {
23 FormValidator::Simple->set_option( %{ $setting->{options} } );
24 }
25 if ( $setting && exists $setting->{message_format} ) {
26 FormValidator::Simple->set_message_format( $setting->{message_format} );
27 }
28 if ( $setting && exists $setting->{message_decode_from} ) {
29 FormValidator::Simple->set_message_decode_from( $setting->{message_decode_from} );
30 }
31}
32
33sub prepare {
34 my $c = shift;
27390aaf 35 $c = $c->maybe::next::method(@_);
04abc0cc 36 $c->{validator} = FormValidator::Simple->new;
37 return $c;
38}
39
40sub form {
41 my $c = shift;
42 if ($_[0]) {
43 my $form = $_[1] ? [@_] : $_[0];
44 $c->{validator}->check($c->req, $form);
45 }
46 return $c->{validator}->results;
47}
48
49sub set_invalid_form {
50 my $c = shift;
51 $c->{validator}->set_invalid(@_);
52 return $c->{validator}->results;
53}
54
551;
56__END__
57
58=head1 NAME
59
60Catalyst::Plugin::FormValidator::Simple - Validator for Catalyst with FormValidator::Simple
61
62=head1 SYNOPSIS
63
64 use Catalyst qw/FormValidator::Simple FillInForm/;
65
66 # set option
67 MyApp->config->{validator} = {
68 plugins => ['CreditCard', 'Japanese'],
69 options => { charset => 'euc'},
70 }
71
72in your controller
73
74 sub defaulti : Private {
75
76 my ($self, $c) = @_;
77
78 $c->form(
79 param1 => [qw/NOT_BLANK ASCII/, [qw/LENGTH 4 10/]],
80 param2 => [qw/NOT_BLANK/, [qw/JLENGTH 4 10/]],
81 mail1 => [qw/NOT_BLANK EMAIL_LOOSE/],
82 mail2 => [qw/NOT_BLANK EMAIL_LOOSE/],
83 { mail => [qw/mail1 mail2/] } => ['DUPLICATION'],
84 );
85
86 print $c->form->valid('param1');
87
88 if ( some condition... ) {
89
90 $c->form(
91 other_param => [qw/NOT_INT/],
92 );
93 }
94
95 if ( some condition... ) {
96
97 # set your original invalid type.
98 $c->set_invalid_form( param3 => 'MY_ERROR' );
99
100 }
101
102 if ( $c->form->has_error ) {
103
104 if ( $c->form->missing('param1') ) {
105 ...
106 }
107
108 if ( $c->form->invalid( param1 => 'ASCII' ) ) {
109 ...
110 }
111
112 if ( $c->form->invalid( param3 => 'MY_ERROR' ) ) {
113 ...
114 }
115
116 }
117 }
118
119=head1 DESCRIPTION
120
121This plugin allows you to validate request parameters with FormValidator::Simple.
122See L<FormValidator::Simple> for more information.
123
124This behaves like as L<Catalyst::Plugin::FormValidator>.
125
126=head1 CONFIGURATION
127
128set config with 'validator' key.
129
130 MyApp->config->{validator} = { ... };
131
132or
133
134 MyApp->config(
135 validator => { ... },
136 );
137
138=head2 PLUGINS
139
140If you want to use some plugins for FormValidator::Simple, you can set like following.
141
142 MyApp->config(
143 validator => {
144 plugins => [qw/Japanese CreditCard DBIC::Unique/],
145 },
146 );
147
148In this example, FormValidator::Simple::Plugin::Japanese, FormValidator::Simple::Plugin::CreditCard,
149and FormValidator::Simple::Plugin::DBIC::Unique are loaded.
150
151=head2 OPTIONS
152
153When you set some options needed by specific validations, do like this.
154
155 MyApp->config(
156 validator => {
157 plugins => [qw/Japanese CreditCard DBIC::Unique/],
158 options => {
159 charset => 'euc',
160 dbic_base_class => 'MyApp::Model::DBIC',
161 },
162 },
163 );
164
165'charset' is necessary for Plugin::Japanese, and 'dbic_cbase_class' is used in Plugin::DBIC::Unique.
166
167=head1 VALIDATION
168
169use 'form' method, see L<FormValidator::Simple> in detail.
170
171 sub do_add : Local {
172 my ( $self, $c ) = @_;
173
174 # execute validation.
175 $c->form(
176 name => [qw/NOT_BLANK ASCII/, [qw/LENGTH 0 20/] ],
177 email => [qw/NOT_BLANK EMAIL_LOOSE/, [qw/LENGTH 0 20/] ],
178 { unique => [qw/name email/] } => [qw/DBIC_UNIQUE User name email/],
179 );
180
181 if ( ... ) {
182
183 # execute validation one more time in specific condition.
184 $c->form(
185 ...
186 );
187
188 }
189
190 # See Catalyst::Plugin::RequestToken for '$c->validate_token'
191 if ( $c->validate_token ) {
192
193 # you can force to set invalid data.
194 $c->set_invalid_form( token => 'TOKEN' );
195
196 }
197
198 # check result.
199 # you can pick up result-object with 'form' method
200
201 my $result = $c->form;
202
203 if ( $result->has_error ) {
204
205 # this is same as
206 # if ( $result->has_missing or $result->has_invalid )
207
208 $c->detach('add');
209
210 }
211
212 }
213
214=head1 HANDLING SUCCESSFUL RESULT
215
216After it passes all validations, you may wanna put input-data into database.
217It's a elegant way to use [ L<Class::DBI> and L<Class::DBI::FromForm> ] or [ L<DBIx::Class> and L<DBIx::Class::WebForm> ].
218
219 sub do_add : Local {
220 my ( $self, $c ) = @_;
221
222 $c->form(
223 name => [qw/NOT_BLANK/],
224 email => [qw/NOT_BLANK/],
225 );
226
227 my $result = $c->form;
228 if ( $result->has_error ) {
229 $c->detach('add');
230 }
231
232 my $user = MyProj::Model::DBIC::User->create_from_form($result);
233
234 # this behaves like this...
235 # MyProj::Model::DBIC::User->create({
236 # name => $result->valid('name'),
237 # email => $result->valid('email'),
238 # });
239 #
240 # if the key exists as the table's column, set the value with 'valid'
241 }
242
243Here, I explain about 'valid' method. If the value indicated with key-name passes validations,
244You can get the data with 'valid',
245
246 my $result = $c->form(
247 name => [qw/NOT_BLANK/],
248 email => [qw/NOT_BLANK/],
249 );
250
251 print $result->valid('name');
252
253 print $result->valid('email');
254
255But, this is for only single key validation normally.
256
257 my $result = $c->form(
258 name => [qw/NOT_BLANK/], # single key validation
259 { mail_dup => [qw/email email2/] } => ['DUPLICATION'] # multiple keys one
260 );
261
262 print $result->valid('name'); # print out the value of 'name'
263
264 print $result->valid('mail_dup'); # no value.
265
266There are exceptions. These are 'DATETIME', 'DATE'.
267
268 my $result = $c->form(
269 { created_on => [qw/created_year created_month created_day/] }
270 =>
271 [qw/DATETIME/],
272 );
273
274 print $result->valid('created_on'); #print out datetime string like "2005-11-23 00:00:00".
275
276If you set some class around datetime in configuration. It returns object of the class you indicate.
277You can choose from L<Time::Piece> and L<DateTime>. For example...
278
279 MyApp->config(
280 validator => {
281 plugins => [...],
282 options => {
283 datetime_class => 'Time::Piece',
284 },
285 },
286 );
287
288or
289
290 MyApp->config(
291 validator => {
292 plugins => [...],
293 options => {
294 datetime_class => 'DateTime',
295 time_zone => 'Asia/Tokyo',
296 },
297 },
298 );
299
300then
301
302 my $result = $c->form(
303 { created_on => [qw/created_year created_month created_day/] }
304 =>
305 [qw/DATETIME/],
306 );
307
308 my $dt = $result->valid('created_on');
309
310 print $dt->ymd;
311
312 MyProj::Model::CDBI::User->create_from_form($result);
313
314This may be useful when you define 'has_a' relation for datetime columns.
315For example, in your table class inherits 'Class::DBI'
316
317 __PACKAGE__->has_a( created_on => 'DateTime',
318 inflate => ...,
319 deflate => ...,
320 );
321
322And see also L<Class::DBI::Plugin::TimePiece>, L<Class::DBI::Plugin::DateTime>.
323
324=head1 MESSAGE HANDLING
325
326in template file, you can handle it in detail.
327
328 [% IF c.form.has_error %]
329 <p>Input Error</p>
330 <ul>
331 [% IF c.form.missing('name') %]
332 <li>input name!</li>
333 [% END %]
334 [% IF c.form.invalid('name') %]
335 <li>name is wrong</li>
336 [% END %]
337 [% IF c.form.invalid('name', 'ASCII') %]
338 <li>input name with ascii code.</li>
339 [% END %]
340 [% IF c.form.invalid('name', 'LENGTH') %]
341 <li>wrong length for name.</li>
342 [% END %]
343 </ul>
344 [% END %]
345
346or, make it more easy.
347
348 [% IF c.form.has_error %]
349 <p>Input Error</p>
350 <ul>
351 [% FOREACH key IN c.form.error %]
352 [% FOREACH type IN c.form.error(key) %]
353 <li>Invalid: [% key %] - [% type %]</li>
354 [% END %]
355 [% END %]
356 </li>
357 [% END %]
358
359And you can also use messages configuration as hash reference.
360
361 MyApp->config(
362 validator => {
363 plugins => [...],
364 messages => {
365 user => {
366 name => {
367 NOT_BLANK => 'Input name!',
368 ASCII => 'Input name with ascii code!',
369 },
370 email => {
371 DEFAULT => 'email is wrong.!',
372 NOT_BLANK => 'input email.!'
373 },
374 },
375 company => {
376 name => {
377 NOT_BLANK => 'Input name!',
378 },
379 },
380 },
381 },
382 );
383
384or YAML file. set file name
385
386 MyApp->config(
387 validator => {
388 plugins => [...],
389 messages => 'conf/messages.yml',
390 },
391 );
392
393and prepare yaml file like following,
394
395 DEFAULT:
396 name:
397 DEFAULT: name is invalid
398 user:
399 name:
400 NOT_BLANK: Input name!
401 ASCII: Input name with ascii code!
402 email:
403 DEFAULT: Email is wrong!
404 NOT_BLANK: Input email!
405 company:
406 name:
407 NOT_BLANK: Input name!
408
409the format is...
410
411 Action1_Name:
412 Key1_Name:
413 Validation1_Name: Message
414 Validation2_Name: Message
415 Key2_Name:
416 Validation1_Name: Message
417 Action2_Name:
418 Key1_Name:
419 ...
420
421After messages configuration, call messages() method from result-object.
422and set action-name as argument.
423
424 [% IF c.form.has_error %]
425 <ul>
426 [% FOREACH message IN c.form.messages('user') %]
427 <li>[% message %]</li>
428 [% END %]
429 </ul>
430 [% END %]
431
432you can set each message format
433
434 MyApp->config(
435 validator => {
436 messages => 'messages.yml',
437 message_format => '<p>%s</p>'
438 },
439 );
440
441 [% IF c.form.has_error %]
442 [% c.form.messages('user').join("\n") %]
443 [% END %]
444
445=head1 SEE ALSO
446
447L<FormValidator::Simple>
448
449L<Catalyst>
450
451=head1 AUTHOR
452
453Lyo Kato E<lt>lyo.kato@gmail.comE<gt>
454
455=head1 COPYRIGHT AND LICENSE
456
457Copyright(C) 2005 by Lyo Kato
458
459This library is free software; you can redistribute it and/or
460modify it under the same terms as Perl itself.
461
462=cut
463