NAME Brannigan - Easy, flexible system for validating and parsing input, mainly targeted at web applications. SYNOPSIS This example uses Catalyst, but should be pretty self explanatory. package MyApp::Controller::Post; use strict; use warnings; use Brannigan; # create a new Brannigan object with two validation/parsing schemes: my $b = Brannigan->new( { name => 'post', ignore_missing => 1, params => { subject => { required => 1, length_between => [3, 40], }, text => { required => 1, min_length => 10, validate => sub { my $value = shift; return undef unless $value; return $value =~ m/^lorem ipsum/ ? 1 : undef; } }, day => { required => 0, integer => 1, value_between => [1, 31], }, mon => { required => 0, integer => 1, value_between => [1, 12], }, year => { required => 0, integer => 1, value_between => [1900, 2900], }, section => { required => 1, integer => 1, value_between => [1, 3], parse => sub { my $val = shift; my $ret = $val == 1 ? 'reviews' : $val == 2 ? 'receips' : 'general'; return { section => $ret }; }, }, id => { required => 1, exact_length => 10, value_between => [1000000000, 2000000000], }, }, groups => { date => { params => [qw/year mon day/], parse => sub { my ($year, $mon, $day) = @_; return undef unless $year && $mon && $day; return { date => $year.'-'.$mon.'-'.$day }; }, }, }, }, { name => 'edit_post', inherits_from => 'post', params => { subject => { required => 0, }, id => { forbidden => 1, }, }, }); # post a new blog post sub new_post : Local { my ($self, $c) = @_; # get input parameters hash-ref my $params = $c->request->params; # process the parameters my $parsed_params = $b->process('post', $params); if ($parsed_params->{_rejects}) { die $c->list_errors($parsed_params); } else { $c->model('DB::BlogPost')->create($parsed_params); } } # edit a blog post sub edit_post : Local { my ($self, $c, $id) = @_; my $params = $b->process('edit_posts', $c->req->params); if ($params->{_rejects}) { die $c->list_errors($params); } else { $c->model('DB::BlogPosts')->find($id)->update($params); } } DESCRIPTION Brannigan is an attempt to ease the pain of collecting input parameters in web applications, validating them and finally (if necessary), parsing them before actually using them. On the "validational" aspect of this module, it is quite like Oogly. The idea is to define a structure of parameters ("fields" in Oogly) and their needed validations, and let the module automatically examine input parameters against this structure. Unlike Oogly, however, Brannigan does provide validation routines (along with custom validations), and also allows the ability to parse input (which probably means turning input parameters into something usable by the app). Check the synopsis section for an example of such a structure. I call this structure a validation/parsing scheme. Schemes can inherit all the properties of other schemes, which allows you to be much more flexible in certain situations. As per the synopsis example, imagine you have a blogging application. The base scheme defines all validations and parsing needed to create a new blog post. When editing a post, however, some parameters that were required when creating the post might not be required now (so you can just use older values). Inheritance allows you to do so easily by creating another scheme which gets all the properties of the base scheme, only changing whatever it is needs changing (and possibly adding specific properties that don't exist in the base scheme). Brannigan works by receiving a hash-ref of input parameters, asserting all validation methods required for each parameter, and parsing every parameter (or group of parameters, see below). Brannigan then returns a hash-ref with all parsed input parameters (read about parsing below). HOW SCHEMES WORK A scheme is just a hash-ref with the following keys: * name Defines the name of the scheme. Required. * ignore_missing Boolean value indicating whether input parameters that are not referenced in the scheme should be added to the parsed output or not. Optional, defaults to false (i.e. parameters missing from the scheme will be added to the output as-is). * params A hash-ref containing the names of input parameters. Every such name (i.e. key) in itself is also a hash-ref. This hash-ref defines the necessary validation methods, and optionally a parse method. This is done by naming the validation method as the key, and passing parameters to that method with the value. A custom validation method is defined with the 'validate' key, which expects to receive an anonymous subroutine. The value of the input parameter is automatically prepended to all validation routines. The routine is expected to return a true value if the parameter passed the check, or a false value otherwise. A parsing method is defined with the 'parse' method, which is also an anonymous subroutine which automatically receives the value of the parameter. This method is expected to return a hash-ref of key-value pairs. These will be automatically apended to the output hash-ref. If no "parse()" method is provided, the parameter is appended to the output hash-ref as-is (i.e. "param => value"). For a list of all validation methods provided by Brannigan, check Brannigan::Validations. * groups A hash-ref containing the names of groups of input parameters. These are useful for parsing input parameters that are somehow related together. As per the synopsis example, suppose your web application receives a date by using three input fields (day, month and year). A parse method on these three parameters allows you, for example, to return a string called 'date' which concatenates these three parameters to the YYYY-MM-DD format. A group is defined with a 'params' key, which expects an array-ref of parameters that belong to the group, and a 'parse' key which expects an anonymous subroutine, just like for individual parameters. After validating, if any validation requirements were not met by any of the input parameters, the resulting hash-ref will also include a '_rejects' key, whose value is a hash-ref of "misbehaving" parameters and all the validation methods they failed (in an array-ref). Errors are not raised and error messages are not created, this will be your job, and I think it's better this way, 'cause there is no flexibility in automatic error messages. Suppose a parameter failed the 'min_length' test, which was defined with a minimum length of 3 characters and a maximum length of 10 characters; then this test will be appended to the array-ref as 'min_length(3, 10)', in order to allow you to know exactly why a test failed (this, of course, does not apply to custom validation methods, which will simply be added as 'validate'). Note that if a parameter failed validation, it will still be added to the parsed output. Suppose the following input parameters were processed with the 'post' scheme from our synopsis example: { subject => 'su', text => undef, day => 13, mon => 12, year => 2010, section => 2, thing => 3, id => 300000000, } The resulting hash-ref would be: { '_rejects' => { 'text' => [ 'required(1)', 'min_length(10)', 'validate' ], 'subject' => [ 'length_between(3, 40)' ], 'id' => [ 'exact_length(10)', 'value_between(1000000000, 2000000000)' ] }, 'date' => '2010-12-13', 'subject' => 'su', 'section' => 'receips', 'text' => undef, 'day' => 13, 'mon' => 12, 'id' => 300000000, 'year' => 2010 } Notice the 'thing' key from the input parameters is missing from the resulting hash-ref, since it is not referenced by the scheme and "ignore_missing" is on. Also, notice the 'date' key which was generated by the 'date' group. The 'day', 'mon' and 'year' parameters are still returned even though they are part of the 'date' group. METHODS new( \%scheme | @schemes ) Creates a new instance of Brannigan, with the provided scheme(s) (see HOW SCHEMES WORK for more info on schemes). process( \%scheme, \%params ) Receives the name of a scheme and a hash-ref of inupt parameters, and validates and parses these paremeters according to the scheme (see HOW SCHEMES WORK for detailed information about this process). Returns a hash-ref of parsed parameters according to the parsing scheme. INTERNAL METHODS _build_tree( \%scheme ) Builds the final "tree" of validations and parsing methods to be performed on the parameters hash during processing. _merge_trees( @trees ) Merges two or more hash-ref of validation/parsing trees and returns the resulting tree. The merge is performed in order, so trees later in the array (i.e. on the right) "tramp" the trees on the left. CAVEATS This is the initial, "quick" version of Brannigan, so pretty much no checks are made on created schemes, so if you incorrectly define your schemes, Brannigan will not croak and processing will fail. Also, there is no support yet for recursive inheritance or any crazy inheritance situation. While deep inheritance is supported, it hasn't been tested yet. In the next release, the ability to define custom validation methods to be available across schemes (even schemes that do not have any inheritance connections) will be added. Some code for this feature has already been written, but isn't functional yet. SEE ALSO Brannigan::Validations, Brannigan::Tree, Oogly. AUTHOR Ido Perlmuter, "" BUGS Please report any bugs or feature requests to "bug-brannigan at rt.cpan.org", or through the web interface at . 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 Brannigan You can also look for information at: * RT: CPAN's request tracker * AnnoCPAN: Annotated CPAN documentation * CPAN Ratings * Search CPAN ACKNOWLEDGEMENTS Brannigan is inspired by Oogly (Al Newkirk) and the "Ketchup" jQuery validation plugin (). LICENSE AND COPYRIGHT Copyright 2010 Ido Perlmuter. This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See http://dev.perl.org/licenses/ for more information.