1NAME
2    Brannigan - Comprehensive, flexible system for validating and parsing
3    input, mainly targeted at web applications.
4
5SYNOPSIS
6            use Brannigan;
7
8            my %scheme1 = ( name => 'scheme1', params => ... );
9            my %scheme2 = ( name => 'scheme2', params => ... );
10            my %scheme3 = ( name => 'scheme3', params => ... );
11
12            # use the OO interface
13            my $b = Brannigan->new(\%scheme1, \%scheme2);
14            $b->add_scheme(\%scheme3);
15
16            my $parsed = $b->process('scheme1', \%params);
17            if ($parsed->{_rejects}) {
18                    die $parsed->{_rejects};
19            } else {
20                    return $parsed;
21            }
22
23            # Or use the functional interface
24            my $parsed = Brannigan::process(\%scheme1, \%params);
25            if ($parsed->{_rejects}) {
26                    die $parsed->{_rejects};
27            } else {
28                    return $parsed;
29            }
30
31    For a more comprehensive example, see "MANUAL" in this document or the
32    Brannigan::Examples document.
33
34DESCRIPTION
35    Brannigan is an attempt to ease the pain of collecting, validating and
36    parsing input parameters in web applications. It's designed to answer
37    both of the main problems that web applications face:
38
39    * Simple user input
40
41      Brannigan can validate and parse simple, "flat", user input, possibly
42      coming from web forms.
43
44    * Complex data structures
45
46      Brannigan can validate and parse complex data structures, possibly
47      deserialized from JSON or XML data sent to web services and APIs.
48
49    Brannigan's approach to data validation is as follows: define a
50    structure of parameters and their needed validations, and let the module
51    automatically examine input parameters against this structure. Brannigan
52    provides you with common validation methods that are used everywhere,
53    and also allows you to create custom validations easily. This structure
54    also defines how, if at all, the input should be parsed. This is akin to
55    schema-based validations such as XSD, but much more functional, and most
56    of all flexible.
57
58    Check the next section for an example of such a structure. I call this
59    structure a validation/parsing scheme. Schemes can inherit all the
60    properties of other schemes, which allows you to be much more flexible
61    in certain situations. Imagine you have a blogging application. A base
62    scheme might define all validations and parsing needed to create a new
63    blog post from a user's input. When editing a post, however, some
64    parameters that were required when creating the post might not be
65    required now (so you can just use older values), and maybe new
66    parameters are introduced. Inheritance helps you avoid repeating
67    yourself. You can another scheme which gets all the properties of the
68    base scheme, only changing whatever it is needs changing (and possibly
69    adding specific properties that don't exist in the base scheme).
70
71MANUAL
72    In the following manual, we will look at the following example. It is
73    based on Catalyst, but should be fairly understandable for non-Catalyst
74    users. Do not be alarmed by the size of this, this is only because it
75    displays basically every aspect of Brannigan.
76
77    This example uses Catalyst, but should be pretty self explanatory. It's
78    fairly complex, since it details pretty much all of the available
79    Brannigan functionality, so don't be alarmed by the size of this thing.
80
81            package MyApp::Controller::Post;
82
83            use strict;
84            use warnings;
85            use Brannigan;
86
87            # create a new Brannigan object with two validation/parsing schemes:
88            my $b = Brannigan->new({
89                    name => 'post',
90                    ignore_missing => 1,
91                    params => {
92                            subject => {
93                                    required => 1,
94                                    length_between => [3, 40],
95                            },
96                            text => {
97                                    required => 1,
98                                    min_length => 10,
99                                    validate => sub {
100                                            my $value = shift;
101
102                                            return undef unless $value;
103
104                                            return $value =~ m/^lorem ipsum/ ? 1 : undef;
105                                    }
106                            },
107                            day => {
108                                    required => 0,
109                                    integer => 1,
110                                    value_between => [1, 31],
111                            },
112                            mon => {
113                                    required => 0,
114                                    integer => 1,
115                                    value_between => [1, 12],
116                            },
117                            year => {
118                                    required => 0,
119                                    integer => 1,
120                                    value_between => [1900, 2900],
121                            },
122                            section => {
123                                    required => 1,
124                                    integer => 1,
125                                    value_between => [1, 3],
126                                    parse => sub {
127                                            my $val = shift;
128
129                                            my $ret = $val == 1 ? 'reviews' :
130                                                      $val == 2 ? 'receips' :
131                                                      'general';
132
133                                            return { section => $ret };
134                                    },
135                            },
136                            id => {
137                                    required => 1,
138                                    exact_length => 10,
139                                    value_between => [1000000000, 2000000000],
140                            },
141                            '/^picture_(\d+)$/' => {
142                                    length_between => [3, 100],
143                                    validate => sub {
144                                            my ($value, $num) = @_;
145
146                                            ...
147                                    },
148                            },
149                            picture_1 => {
150                                    default => 'http://www.example.com/avatar.png',
151                            },
152                            array_of_ints => {
153                                    array => 1,
154                                    min_length => 3,
155                                    values => {
156                                            integer => 1,
157                                    },
158                            },
159                            hash_of_langs => {
160                                    hash => 1,
161                                    keys => {
162                                            _all => {
163                                                    exact_length => 10,
164                                            },
165                                            en => {
166                                                    required => 1,
167                                            },
168                                    },
169                            },
170                    },
171                    groups => {
172                            date => {
173                                    params => [qw/year mon day/],
174                                    parse => sub {
175                                            my ($year, $mon, $day) = @_;
176                                            return undef unless $year && $mon && $day;
177                                            return { date => $year.'-'.$mon.'-'.$day };
178                                    },
179                            },
180                            tags => {
181                                    regex => '/^tags_(en|he|fr)$/',
182                                    forbid_words => ['bad_word', 'very_bad_word'],
183                                    parse => sub {
184                                            return { tags => \@_ };
185                                    },
186                            },
187                    },
188            }, {
189                    name => 'edit_post',
190                    inherits_from => 'post',
191                    params => {
192                            subject => {
193                                    required => 0, # subject is no longer required
194                            },
195                            id => {
196                                    forbidden => 1,
197                            },
198                    },
199            });
200
201            # create the custom 'forbid_words' validation method
202            $b->custom_validation('forbid_words', sub {
203                    my $value = shift;
204
205                    foreach (@_) {
206                            return 0 if $value =~ m/$_/;
207                    }
208
209                    return 1;
210            });
211
212            # post a new blog post
213            sub new_post : Local {
214                    my ($self, $c) = @_;
215
216                    # get input parameters hash-ref
217                    my $params = $c->request->params;
218
219                    # process the parameters
220                    my $parsed_params = $b->process('post', $params);
221
222                    if ($parsed_params->{_rejects}) {
223                            die $c->list_errors($parsed_params);
224                    } else {
225                            $c->model('DB::BlogPost')->create($parsed_params);
226                    }
227            }
228
229            # edit a blog post
230            sub edit_post : Local {
231                    my ($self, $c, $id) = @_;
232
233                    my $params = $b->process('edit_posts', $c->req->params);
234
235                    if ($params->{_rejects}) {
236                            die $c->list_errors($params);
237                    } else {
238                            $c->model('DB::BlogPosts')->find($id)->update($params);
239                    }
240            }
241
242  HOW BRANNIGAN WORKS
243    In essence, Brannigan works in three stages (which all boil down to one
244    single command):
245
246    *   Input stage and preparation
247
248        Brannigan receives a hash-ref of input parameters, or a hash-ref
249        based data structure, and the name of a scheme to validate against.
250        Brannigan then loads the scheme and prepares it (by merging it with
251        inherited schemes) for later processing.
252
253    *   Data validation
254
255        Brannigan invokes all validation methods defined in the scheme on
256        the input data, and generates a hash-ref of rejected parameters. For
257        every parameter in this hash-ref, a list of failed validations is
258        created in an array-ref.
259
260    *   Data parsing
261
262        Regardless of the previous stage, every parsing method defined in
263        the scheme is applied on the relevant data. The data resulting from
264        these parsing methods, along with the values of all input parameters
265        for which no parsing methods were defined, is returned to the user
266        in a hash-ref. This hash-ref also includes a _rejects key whose
267        value is the rejects hash created in the previous stage.
268
269        The reason I say this stage isn't dependant on the previous stage is
270        simple. First of all, it's possible no parameters failed validation,
271        but the truth is this stage doesn't care if a parameter failed
272        validation. It will still parse it and return it to the user, and no
273        errors are ever raised by Brannigan. It is the developer's (i.e.
274        you) job to decide what to do in case rejects are present.
275
276  HOW SCHEMES LOOK
277    The validation/parsing scheme defines the structure of the data you're
278    expecting to receive, along with information about the way it should be
279    validated and parsed. Schemes are created by passing them to the
280    Brannigan constructor. You can pass as many schemes as you like, and
281    these schemes can inherit from one another. You can create the Brannigan
282    object that gets these schemes wherever you want. Maybe in a controller
283    of your web app that will directly use this object to validate and parse
284    input it gets, or maybe in a special validation class that will hold all
285    schemes. It doesn't matter where, as long as you make the object
286    available for your application.
287
288    A scheme is a hash-ref based data structure that has the following keys:
289
290    *   name
291
292        Defines the name of the scheme. Required.
293
294    *   ignore_missing
295
296        Boolean value indicating whether input parameters that are not
297        referenced in the scheme should be added to the parsed output or
298        not. Optional, defaults to false (i.e. parameters missing from the
299        scheme will be added to the output as-is). You might find it is
300        probably a good idea to turn this on, so any input parameters you're
301        not expecting to receive from users are ignored.
302
303    *   inherits_from
304
305        Either a scalar naming a different scheme or an array-ref of scheme
306        names. The new scheme will inherit all the properties of the
307        scheme(s) defined by this key. If an array-ref is provided, the
308        scheme will inherit their properties in the order they are defined.
309        See the "CAVEATS" section for some "heads-up" about inheritance.
310
311    *   params
312
313        The params key is the most important part of the scheme, as it
314        defines the expected input. This key takes a hash-ref containing the
315        names of input parameters. Every such name (i.e. key) in itself is
316        also a hash-ref. This hash-ref defines the necessary validation
317        methods to assert for this parameter, and optionally a 'parse' and
318        'default' method. The idea is this: use the name of the validation
319        method as the key, and the appropriate values for this method as the
320        value of this key. For example, if a certain parameter, let's say
321        'subject', must be between 3 to 10 characters long, then your scheme
322        will contain:
323
324                subject => {
325                        length_between => [3, 10]
326                }
327
328        The 'subject' parameter's value (from the user input), along with
329        both of the values defined above (3 and 10) will be passed to the
330        "length_between()" validation method. Now, suppose a certain subject
331        sent to your app failed the "length_between()" validation; then the
332        rejects hash-ref described earlier will have something like this:
333
334                subject => ['length_between(3, 10)']
335
336        Notice the values of the "length_between()" validation method were
337        added to the string, so you can easily know why the parameter failed
338        the validation.
339
340        Custom validation methods: Aside for the built-in validation methods
341        that come with Brannigan, a custom validation method can be defined
342        for each parameter. This is done by adding a 'validate' key to the
343        parameter, and an anonymous subroutine as the value. As with
344        built-in methods, the parameter's value will be automatically sent
345        to this method. So, for example, if the subject parameter from above
346        must start with the words 'lorem ipsum', then we can define the
347        subject parameter like so:
348
349                subject => {
350                        length_between => [3, 10],
351                        validate => sub {
352                                my $value = shift;
353
354                                return $value =~ m/^lorem ipsum/ ? 1 : 0;
355                        }
356                }
357
358        Custom validation methods, just like built-in ones, are expected to
359        return a true value if the parameter passed the validation, or a
360        false value otherwise. If a parameter failed a custom validation
361        method, then 'validate' will be added to the list of failed
362        validations for this parameter. So, in our 'subject' example, the
363        rejects hash-ref will have something like this:
364
365                subject => ['length_between(3, 10)', 'validate']
366
367        Default values: For your convenience, Brannigan allows you to set
368        default values for parameters that are not required (so, if you set
369        a default value for a parameter, don't add the "required()"
370        validation method to it). There are two ways to add a default value:
371        either directly, or through an anonymous subroutine (just like the
372        custom validation method). For example, maybe we'd like the
373        'subject' parameter to have a default value of 'lorem ipsum dolor
374        sit amet'. Then we can have the following definition:
375
376                subject => {
377                        length_between => [3, 10],
378                        validate => sub {
379                                my $value = shift;
380
381                                return $value =~ m/^lorem ipsum/ ? 1 : 0;
382                        },
383                        default => 'lorem ipsum dolor sit amet'
384                }
385
386        Alternatively, you can give a parameter a generated default value by
387        using an anonymous subroutine, like so:
388
389                subject => {
390                        length_between => [3, 10],
391                        validate => sub {
392                                my $value = shift;
393
394                                return $value =~ m/^lorem ipsum/ ? 1 : 0;
395                        },
396                        default => sub {
397                                return int(rand(100000000));
398                        }
399                }
400
401        Notice that default values are added to missing parameters only at
402        the parsing stage (i.e. stage 3 - after the validation stage), so
403        validation methods do not apply to default values.
404
405        Parse methods: It is more than possible that the way input
406        parameters are passed to your application will not be exactly the
407        way you'll eventually use them. That's where parsing methods can
408        come in handy. Brannigan doesn't have any built-in parsing methods
409        (obviously), so you must create these by yourself, just like custom
410        validation methods. All you need to do is add a 'parse' key to the
411        parameter's definition, with an anonymous subroutine. This
412        subroutine also receives the value of the parameter automatically,
413        and is expected to return a hash-ref of key-value pairs. You will
414        probably find it that most of the time this hash-ref will only
415        contain one key-value pair, and that the key will probably just be
416        the name of the parameter. But note that when a parse method exists,
417        Brannigan makes absolutely no assumptions of what else to do with
418        that parameter, so you must tell it exactly how to return it. After
419        all parameters were parsed by Brannigan, all these little hash-refs
420        are merged into one hash-ref that is returned to the caller. If a
421        parse method doesn't exist for a paramter, Brannigan will simply add
422        it "as-is" to the resulting hash-ref. Returning to our subject
423        example (which we defined must start with 'lorem ipsum'), let's say
424        we want to substitute 'lorem ipsum' with 'effing awesome' before
425        using this parameter. Then the subject definition will now look like
426        this:
427
428                subject => {
429                        length_between => [3, 10],
430                        validate => sub {
431                                my $value = shift;
432
433                                return $value =~ m/^lorem ipsum/ ? 1 : 0;
434                        },
435                        default => 'lorem ipsum dolor sit amet',
436                        parse => sub {
437                                my $value = shift;
438
439                                $value =~ s/^lorem ipsum/effing awesome/;
440
441                                return { subject => $value };
442                        }
443                }
444
445        If you're still not sure what happens when no parse method exists,
446        then you can imagine Brannigan uses the following default parse
447        method:
448
449                param => {
450                        parse => sub {
451                                my $value = shift;
452
453                                return { param => $value };
454                        }
455                }
456
457        Regular expressions: As of version 0.3, parameter names can also be
458        regular expressions in the form '/regex/'. Sometimes you cannot know
459        the names of all parameters passed to your app. For example, you
460        might have a dynamic web form which starts with a single field
461        called 'url_1', but your app allows your visitors to dynamically add
462        more fields, such as 'url_2', 'url_3', etc. Regular expressions are
463        handy in such situations. Your parameter key can be '/^url_(\d+)$/',
464        and all such fields will be matched. Regex params have a special
465        feature: if your regex uses capturing, then captured values will be
466        passed to the custom "validate" and "parse" methods (in their order)
467        after the parameter's value. For example:
468
469                '/^url_(\d+)$/' => {
470                        validate => sub {
471                                my ($value, $num) = @_;
472
473                                # $num has the value captured by (\d+) in the regex
474
475                                return $value =~ m!^http://! ? 1 : undef;
476                        },
477                        parse => sub {
478                                my ($value, $num) = @_;
479
480                                return { urls => { $num => $value } };
481                        },
482                }
483
484        Please note that a regex must be defined with a starting and
485        trailing slash, in single quotes, otherwise it won't work. It is
486        also important to note what happens when a parameter matches a regex
487        rule (or perhaps rules), and also has a direct reference in the
488        scheme. For example, let's say we have the following rules in our
489        scheme:
490
491                '/^sub(ject|headline)$/' => {
492                        required => 1,
493                        length_between => [3, 10],
494                },
495                subject => {
496                        required => 0,
497                }
498
499        When validating and parsing the 'subject' parameter, Brannigan will
500        automatically merge both of these references to the subject
501        parameter, giving preference to the direct reference, so the actual
502        structure on which the parameter will be validated is as follows:
503
504                subject => {
505                        required => 0,
506                        length_between => [3, 10],
507                }
508
509        If your parameter matches more than one regex rule, they will all be
510        merged, but there's no way (yet) to ensure in which order these
511        regex rules will be merged.
512
513        Complex data structures: As previously stated, Brannigan can also
514        validate and parse a little more complex data structures. So, your
515        parameter no longer has to be just a string or a number, but maybe a
516        hash-ref or an array-ref. In the first case, you tell Brannigan the
517        paramter is a hash-ref by adding a 'hash' key with a true value, and
518        a 'keys' key with a hash-ref which is just like the 'params'
519        hash-ref. For example, suppose you're receiving a 'name' parameter
520        from the user as a hash-ref containing first and last names. That's
521        how the 'name' parameter might be defined:
522
523                name => {
524                        hash => 1,
525                        required => 1,
526                        keys => {
527                                first_name => {
528                                        length_between => [3, 10],
529                                },
530                                last_name => {
531                                        required => 1,
532                                        min_length => 3,
533                                },
534                        }
535                }
536
537        What are we seeing here? We see that the 'name' parameter must be a
538        hash-ref, that it's required, and that it has two keys: first_name,
539        whose length must be between 3 to 10 if it's present, and last_name,
540        which must be 3 characters or more, and must be present.
541
542        An array parameter, on the other hand, is a little different.
543        Similar to hashes, you define the parameter as an array-ref with the
544        'array' key with a true value, and a 'values' key. This key has a
545        hash-ref of validation and parse methods that will be applied to
546        EVERY value inside this array. For example, suppose you're receiving
547        a 'pictures' parameter from the user as an array-ref containing URLs
548        to pictures on the web. That's how the 'pictures' parameter might be
549        defined:
550
551                pictures => {
552                        array => 1,
553                        length_between => [1, 5],
554                        values => {
555                                min_length => 3,
556                                validate => sub {
557                                        my $value = shift;
558
559                                        return $value =~ m!^http://! ? 1 : 0;
560                                },
561                        },
562                }
563
564        What are we seeing this time? We see that the 'pictures' parameter
565        must be an array, with no less than one item (i.e. value) and no
566        more than five items (notice that we're using the same
567        "length_between()" method from before, but in the context of an
568        array, it doesn't validate against character count but item count).
569        We also see that every value in the 'pictures' array must have a
570        minimum length of three (this time it is characterwise), and must
571        match 'http://' in its beginning.
572
573        Since complex data structures are supported, you can define default
574        values for parameters that aren't just strings or numbers (or
575        methods), for example:
576
577                complex_param => {
578                        hash => 1,
579                        keys => {
580                                ...
581                        },
582                        default => { key1 => 'def1', key2 => 'def2' }
583                }
584
585        What Brannigan returns for such structures when they fail
586        validations is a little different than before. Instead of an
587        array-ref of failed validations, Brannigan will return a hash-ref.
588        This hash-ref might contain a '_self' key with an array-ref of
589        validations that failed specifically on the 'pictures' parameter
590        (such as the 'required' validation for the 'name' parameter or the
591        'length_between' validation for the 'pictures' parameter), and/or
592        keys for each value in these structures that failed validation. If
593        it's a hash, then the key will simply be the name of that key. If
594        it's an array, it will be its index. For example, let's say the
595        'first_name' key under the 'name' parameter failed the
596        "length_between(3, 10)" validation method, and that the 'last_name'
597        key was not present (and hence failed the "required()" validation).
598        Also, let's say the 'pictures' parameter failed the
599        "length_between(1, 5)" validation (for the sake of the argument,
600        let's say it had 6 items instead of the maximum allowed 5), and that
601        the 2nd item failed the min_length(3) validation, and the 6th item
602        failed the custom validate method. Then our rejects hash-ref will
603        have something like this:
604
605                name => {
606                        first_name => ['length_between(3, 10)'],
607                        last_name => ['required(1)'],
608                },
609                pictures => {
610                        _self => ['length_between(1, 5)'],
611                        1 => ['min_length(3)'],
612                        5 => ['validate'],
613                }
614
615        Notice the '_self' key under 'pictures' and that the numbering of
616        the items of the 'pictures' array starts at zero (obviously).
617
618        The beauty of Brannigan's data structure support is that it's
619        recursive. So, it's not that a parameter can be a hash-ref and
620        that's it. Every key in that hash-ref might be in itself a hash-ref,
621        and every key in that hash-ref might be an array-ref, and every
622        value in that array-ref might be a hash-ref... well, you get the
623        idea. How might that look like? Well, just take a look at this:
624
625                pictures => {
626                        array => 1,
627                        values => {
628                                hash => 1,
629                                keys => {
630                                        filename => {
631                                                min_length => 5,
632                                        },
633                                        source => {
634                                                hash => 1,
635                                                keys => {
636                                                        website => {
637                                                                validate => sub { ... },
638                                                        },
639                                                        license => {
640                                                                one_of => [qw/GPL FDL CC/],
641                                                        },
642                                                },
643                                        },
644                                },
645                        },
646                }
647
648        So, we have a pictures array that every value in it is a hash-ref
649        with a filename key and a source key whose value is a hash-ref with
650        a website key and a license key.
651
652        Local validations: The _all "parameter" can be used in a scheme to
653        define rules that apply to all of the parameters in a certain level.
654        This can either be used directly in the 'params' key of the scheme,
655        or in the 'keys' key of a hash parameter.
656
657                _all => {
658                        required => 1
659                },
660                subject => {
661                        length_between => [3, 255]
662                },
663                text => {
664                        min_length => 10
665                }
666
667        In the above example, both 'subject' and 'text' receive the
668        "required()" validation methods.
669
670    *   groups
671
672        Groups are very useful to parse parameters that are somehow related
673        together. This key takes a hash-ref containing the names of the
674        groups (names are irrelevant, they're more for you). Every group
675        will also take a hash-ref, with a rule defining which parameters are
676        members of this group, and a parse method to use with these
677        parameters (just like our custom parse method from the 'params'
678        key). This parse method will automatically receive the values of all
679        the parameters in the group, in the order they were defined.
680
681        For example, suppose our app gets a user's birth date by using three
682        web form fields: day, month and year. And suppose our app saves this
683        date in a database in the format 'YYYY-MM-DD'. Then we can define a
684        group, say 'date', that automatically does this. For example:
685
686                date => {
687                        params => [qw/year month day/],
688                        parse => sub {
689                                my ($year, $month, $day) = @_;
690
691                                $month = '0'.$month if $month < 10;
692                                $day = '0'.$day if $day < 10;
693
694                                return { date => $year.'-'.$month.'-'.$day };
695                        },
696                }
697
698        Alternative to the 'params' key, you can define a 'regex' key that
699        takes a regex. All parameters whose name matches this regex will be
700        parsed as a group. As oppose to using regexes in the 'params' key of
701        the scheme, captured values in the regexes will not be passed to the
702        parse method, only the values of the parameters will. Also, please
703        note that there's no way to know in which order the values will be
704        provided when using regexes for groups.
705
706        For example, let's say our app receives one or more URLs (to
707        whatever type of resource) in the input, in parameters named
708        'url_1', 'url_2', 'url_3' and so on, and that there's no limit on
709        the number of such parameters we can receive. Now, suppose we want
710        to create an array of all of these URLs, possibly to push it to a
711        database. Then we can create a 'urls' group such as this:
712
713                urls => {
714                        regex => '/^url_(\d+)$/',
715                        parse => sub {
716                                my @urls = @_;
717
718                                return { urls => \@urls };
719                        }
720                }
721
722  BUILT-IN VALIDATION METHODS
723    As mentioned earlier, Brannigan comes with a set of built-in validation
724    methods which are most common and useful everywhere. For a list of all
725    validation methods provided by Brannigan, check Brannigan::Validations.
726
727  CROSS-SCHEME CUSTOM VALIDATION METHODS
728    Custom "validate" methods are nice, but when you want to use the same
729    custom validation method in different places inside your scheme, or more
730    likely in different schemes altogether, repeating the definition of each
731    custom method in every place you want to use it is not very comfortable.
732    Brannigan provides a simple mechanism to create custom, named validation
733    methods that can be used across schemes as if they were internal
734    methods.
735
736    The process is simple: when creating your schemes, give the names of the
737    custom validation methods and their relevant supplement values as with
738    every built-in validation method. For example, suppose we want to create
739    a custom validation method named 'forbid_words', that makes sure a
740    certain text does not contain any words we don't like it to contain.
741    Suppose this will be true for a parameter named 'text'. Then we define
742    'text' like so:
743
744            text => {
745                    required => 1,
746                    forbid_words => ['curse_word', 'bad_word', 'ugly_word'],
747            }
748
749    As you can see, we have provided the name of our custom method, and the
750    words we want to forbid. Now we need to actually create this
751    "forbid_words()" method. We do this after we've created our Brannigan
752    object, by using the "custom_validation()" method, as in this example:
753
754            $b->custom_validation('forbid_words', sub {
755                    my ($value, @forbidden) = @_;
756
757                    foreach (@forbidden) {
758                            return 0 if $value =~ m/$_/;
759                    }
760
761                    return 1;
762            });
763
764    We give the "custom_validation()" method the name of our new method, and
765    an anonymous subroutine, just like in "local" custom validation methods.
766
767    And that's it. Now we can use the "forbid_words()" validation method
768    across our schemes. If a paremeter failed our custom method, it will be
769    added to the rejects like built-in methods. So, if 'text' failed our new
770    method, our rejects hash-ref will contain:
771
772            text => [ 'forbid_words(curse_word, bad_word, ugly_word)' ]
773
774    As an added bonus, you can use this mechanism to override Brannigan's
775    built-in validations. Just give the name of the validation method you
776    wish to override, along with the new code for this method. Brannigan
777    gives precedence to cross-scheme custom validations, so your method will
778    be used instead of the internal one.
779
780  NOTES ABOUT PARSE METHODS
781    As stated earlier, your "parse()" methods are expected to return a
782    hash-ref of key-value pairs. Brannigan collects all of these key-value
783    pairs and merges them into one big hash-ref (along with all the
784    non-parsed parameters).
785
786    Brannigan actually allows you to have your "parse()" methods be
787    two-leveled. This means that a value in a key-value pair in itself can
788    be a hash-ref or an array-ref. This allows you to use the same key in
789    different places, and Brannigan will automatically aggregate all of
790    these occurrences, just like in the first level. So, for example,
791    suppose your scheme has a regex rule that matches parameters like
792    'tag_en' and 'tag_he'. Your parse method might return something like "{
793    tags => { en => 'an english tag' } }" when it matches the 'tag_en'
794    parameter, and something like "{ tags => { he => 'a hebrew tag' } }"
795    when it matches the 'tag_he' parameter. The resulting hash-ref from the
796    process method will thus include "{ tags => { en => 'an english tag', he
797    => 'a hebrew tag' } }".
798
799    Similarly, let's say your scheme has a regex rule that matches
800    parameters like 'url_1', 'url_2', etc. Your parse method might return
801    something like "{ urls => [$url_1] }" for 'url_1' and "{ urls =>
802    [$url_2] }" for 'url_2'. The resulting hash-ref in this case will be "{
803    urls => [$url_1, $url_2] }".
804
805    Take note however that only two-levels are supported, so don't go crazy
806    with this.
807
808  SO HOW DO I PROCESS INPUT?
809    OK, so we have created our scheme(s), we know how schemes look and work,
810    but what now?
811
812    Well, that's the easy part. All you need to do is call the "process()"
813    method on the Brannigan object, passing it the name of the scheme to
814    enforce and a hash-ref of the input parameters/data structure. This
815    method will return a hash-ref back, with all the parameters after
816    parsing. If any validations failed, this hash-ref will have a '_rejects'
817    key, with the rejects hash-ref described earlier. Remember: Brannigan
818    doesn't raise any errors. It's your job to decide what to do, and that's
819    a good thing.
820
821    Example schemes, input and output can be seen in Brannigan::Examples.
822
823CONSTRUCTOR
824  new( \%scheme | @schemes )
825    Creates a new instance of Brannigan, with the provided scheme(s) (see
826    "HOW SCHEMES LOOK" for more info on schemes).
827
828OBJECT METHODS
829  add_scheme( \%scheme | @schemes )
830    Adds one or more schemes to the object. Every scheme hash-ref should
831    have a "name" key with the name of the scheme. Existing schemes will be
832    overridden. Returns the object itself for chainability.
833
834  process( $scheme, \%params )
835    Receives the name of a scheme and a hash-ref of input parameters (or a
836    data structure), and validates and parses these paremeters according to
837    the scheme (see "HOW SCHEMES LOOK" for detailed information about this
838    process).
839
840    Returns a hash-ref of parsed parameters according to the parsing scheme,
841    possibly containing a list of failed validations for each parameter.
842
843    Actual processing is done by Brannigan::Tree.
844
845  process( \%scheme, \%params )
846    Same as above, but takes a scheme hash-ref instead of a name hash-ref.
847    That basically gives you a functional interface for Brannigan, so you
848    don't have to go through the regular object oriented interface. The only
849    downsides to this are that you cannot define custom validations using
850    the "custom_validation()" method (defined below) and that your scheme
851    must be standalone (it cannot inherit from other schemes). Note that
852    when directly passing a scheme, you don't need to give the scheme a
853    name.
854
855  custom_validation( $name, $code )
856    Receives the name of a custom validation method ($name), and a reference
857    to an anonymous subroutine ($code), and creates a new validation method
858    with that name and code, to be used across schemes in the Brannigan
859    object as if they were internal methods. You can even use this to
860    override internal validation methods, just give the name of the method
861    you want to override and the new code.
862
863CAVEATS
864    Brannigan is still in an early stage. Currently, no checks are made to
865    validate the schemes built, so if you incorrectly define your schemes,
866    Brannigan will not croak and processing will probably fail. Also, there
867    is no support yet for recursive inheritance or any crazy inheritance
868    situation. While deep inheritance is supported, it hasn't been tested
869    extensively. Also bugs are popping up as I go along, so keep in mind
870    that you might encounter bugs (and please report any if that happens).
871
872IDEAS FOR THE FUTURE
873    The following list of ideas may or may not be implemented in future
874    versions of Brannigan:
875
876    *   Cross-scheme custom parsing methods
877
878        Add an option to define custom parse methods in the Brannigan object
879        that can be used in the schemes as if they were built-in methods
880        (cross-scheme custom validations are already supported, next up is
881        parse methods).
882
883    *   Support for third-party validation methods
884
885        Add support for loading validation methods defined in third-party
886        modules (written like Brannigan::Validations) and using them in
887        schemes as if they were built-in methods.
888
889    *   Validate schemes by yourself
890
891        Have Brannigan use itself to validate the schemes it receives from
892        the developers (i.e. users of this module).
893
894    *   Support loading schemes from JSON/XML
895
896        Allow loading schemes from JSON/XML files or any other source. Does
897        that make any sense?
898
899    *   Something to aid rejects traversal
900
901        Find something that would make traversal of the rejects list easier
902        or whatever. Plus, printing the name of the validation method and
903        its supplement values in the rejects list isn't always a good idea.
904        For example, if we use the "one_of()" validation method with a big
905        list of say 100 options, our rejects list will contain all these 100
906        options, and that's not nice. So, think about something there.
907
908SEE ALSO
909    Brannigan::Validations, Brannigan::Tree, Brannigan::Examples.
910
911AUTHOR
912    Ido Perlmuter, "<ido at ido50 dot net>"
913
914BUGS
915    Please report any bugs or feature requests to "bug-brannigan at
916    rt.cpan.org", or through the web interface at
917    <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Brannigan>. I will be
918    notified, and then you'll automatically be notified of progress on your
919    bug as I make changes.
920
921SUPPORT
922    You can find documentation for this module with the perldoc command.
923
924            perldoc Brannigan
925
926    You can also look for information at:
927
928    *   RT: CPAN's request tracker
929
930        <http://rt.cpan.org/NoAuth/Bugs.html?Dist=Brannigan>
931
932    *   AnnoCPAN: Annotated CPAN documentation
933
934        <http://annocpan.org/dist/Brannigan>
935
936    *   CPAN Ratings
937
938        <http://cpanratings.perl.org/d/Brannigan>
939
940    *   Search CPAN
941
942        <http://search.cpan.org/dist/Brannigan/>
943
944ACKNOWLEDGEMENTS
945    Brannigan was inspired by Oogly (Al Newkirk) and the "Ketchup" jQuery
946    validation plugin (<http://demos.usejquery.com/ketchup-plugin/>).
947
948LICENSE AND COPYRIGHT
949    Copyright 2017 Ido Perlmuter
950
951    Licensed under the Apache License, Version 2.0 (the "License"); you may
952    not use this file except in compliance with the License. You may obtain
953    a copy of the License at
954
955        http://www.apache.org/licenses/LICENSE-2.0
956
957    Unless required by applicable law or agreed to in writing, software
958    distributed under the License is distributed on an "AS IS" BASIS,
959    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
960    See the License for the specific language governing permissions and
961    limitations under the License.
962
963