File Coverage

blib/lib/CGI/Application/Plugin/Routes.pm
Criterion Covered Total %
statement 27 70 38.5
branch 1 16 6.2
condition n/a
subroutine 5 10 50.0
pod 5 5 100.0
total 38 101 37.6


line stmt bran cond sub pod time code
1             package CGI::Application::Plugin::Routes;
2 1     1   18936 use strict;
  1         2  
  1         30  
3 1     1   5 use Carp;
  1         2  
  1         64  
4              
5 1     1   4 use vars qw($VERSION @ISA @EXPORT);
  1         4  
  1         93  
6              
7             our $VERSION = '1.02';
8              
9             sub import {
10 1     1   8 my $pkg = shift;
11 1         2 my $callpkg = caller;
12              
13             # Do our own exporting.
14             {
15 1     1   4 no strict qw(refs);
  1         1  
  1         693  
  1         2  
16 1         1 *{ $callpkg . '::routes' } = \&CGI::Application::Plugin::Routes::routes;
  1         5  
17 1         2 *{ $callpkg . '::routes_parse' } = \&CGI::Application::Plugin::Routes::routes_parse;
  1         3  
18 1         1 *{ $callpkg . '::routes_dbg' } = \&CGI::Application::Plugin::Routes::routes_dbg;
  1         4  
19 1         2 *{ $callpkg . '::routes_root' } = \&CGI::Application::Plugin::Routes::routes_root;
  1         3  
20 1         2 *{ $callpkg . '::routes_params' } = \&CGI::Application::Plugin::Routes::routes_params;
  1         3  
21            
22             }
23              
24 1 50       9 if ( ! UNIVERSAL::isa($callpkg, 'CGI::Application') ) {
    0          
25 1         43 warn "Calling package is not a CGI::Application module so not setting up the prerun hook. If you are using \@ISA instead of 'use base', make sure it is in a BEGIN { } block, and make sure these statements appear before the plugin is loaded";
26             }
27             elsif ( ! UNIVERSAL::can($callpkg, 'add_callback')) {
28 0           warn "You are using an older version of CGI::Application that does not support callbacks, so the prerun method can not be registered automatically (Lookup the prerun_callback method in the docs for more info)";
29             }
30             else {
31             #Add the required callback to the CGI::Application app so it executes the routes_parse sub on the prerun stage
32 0           $callpkg->add_callback( prerun => 'routes_parse' );
33             }
34             }
35              
36             sub routes {
37 0     0 1   my ($self, $table) = @_;
38 0           $self->{'Application::Plugin::Routes::__dispatch_table'} = $table;
39             #register every runmode declared.
40 0           for(my $i = 1 ; $i < scalar(@$table) ; $i += 2) {
41 0           my $rm_name = $table->[$i];
42 0           $self->run_modes([$rm_name]);
43             }
44             }
45              
46             sub routes_dbg {
47 0     0 1   my $self = shift;
48 0           require Data::Dumper;
49 0           return Dumper($self->{'Application::Plugin::Routes::__r_params'});
50             }
51              
52             sub routes_root{
53 0     0 1   my ($self, $root) = @_;
54             #make sure no trailing slash is present on the root.
55 0           $root =~ s/\/$//;
56 0           $self->{'Application::Plugin::Routes::__routes_root'} = $root;
57             }
58              
59             sub routes_params{
60 0     0 1   my ($self) = shift;
61 0 0         if ( @_ ){
62 0           $self->{'Application::Plugin::Routes::__routes_params'} = [ @_ ];
63             }
64 0           return $self->{'Application::Plugin::Routes::__routes_params'};
65             }
66              
67             sub routes_parse {
68             #all this routine, except a few own modifications was borrowed from the wonderful
69             # Michael Peter's CGI::Application::Dispatch module that can be found here:
70             # http://search.cpan.org/~wonko/CGI-Application-Dispatch/
71 0     0 1   my ($self) = @_;
72 0           my $path = $self->query->path_info;
73             # get the module name from the table
74 0           my $table = $self->{'Application::Plugin::Routes::__dispatch_table'};
75 0 0         unless(ref($table) eq 'ARRAY') {
76 0           carp "[__parse_path] Invalid or no dispatch table!\n";
77 0           return;
78             }
79             # look at each rule and stop when we get a match
80 0           for(my $i = 0 ; $i < scalar(@$table) ; $i += 2) {
81 0           my $rule = $self->{'Application::Plugin::Routes::__routes_root'} . $table->[$i];
82 0           my @names = ();
83             # translate the rule into a regular expression, but remember where the named args are
84             # '/:foo' will become '/([^\/]*)'
85             # and
86             # '/:bar?' will become '/?([^\/]*)?'
87             # and then remember which position it matches
88 0           $rule =~ s{
89             (^|/) # beginning or a /
90             (:([^/\?]+)(\?)?) # stuff in between
91             }{
92 0           push(@names, $3);
93 0 0         $1 . ($4 ? '?([^/]*)?' : '([^/]*)')
94             }gxe;
95             # '/*/' will become '/(.*)/$' the end / is added to the end of
96             # both $rule and $path elsewhere
97 0 0         if($rule =~ m{/\*/$}) {
98 0           $rule =~ s{/\*/$}{/(.*)/\$};
99 0           push(@names, 'dispatch_url_remainder');
100             }
101             # if we found a match, then run with it
102 0 0         if(my @values = ($path =~ m#^$rule$#)) {
103 0           $self->{'Application::Plugin::Routes::__match'} = $path;
104 0           $self->routes_params( @names );
105 0           my %named_args;
106 0           $self->param('rm',$table->[++$i]);
107              
108 0           my $rm_name = $table->[$i];
109 0           $self->prerun_mode($rm_name);
110              
111 0 0         @named_args{@names} = @values if @names;
112             #force params into $self->query. NOTE that it will overwrite any existing param with the same name
113 0           foreach my $k (keys %named_args){
114 0           $self->query->param("$k", $named_args{$k});
115             }
116 0           $self->{'Application::Plugin::Routes::__r_params'} = {"parsed_params: " => \%named_args, "path_received: " => $path, "rule_matched: " => $rule, "runmode: " => $rm_name};
117             }
118             }
119             }
120              
121             1;
122             __END__