File Coverage

blib/lib/Catalyst/DispatchType/Path.pm
Criterion Covered Total %
statement 72 73 98.6
branch 26 28 92.8
condition 2 3 66.6
subroutine 11 11 100.0
pod 5 5 100.0
total 116 120 96.6


line stmt bran cond sub pod time code
1              
2             use Moose;
3 153     153   110538 extends 'Catalyst::DispatchType';
  153         407  
  153         1278  
4              
5             use Text::SimpleTable;
6 153     153   1073334 use Catalyst::Utils;
  153         411  
  153         4486  
7 153     153   958 use URI;
  153         362  
  153         3934  
8 153     153   12544 use Encode 2.21 'decode_utf8';
  153         900  
  153         5936  
9 153     153   1005  
  153         3959  
  153         15728  
10             has _paths => (
11             is => 'rw',
12             isa => 'HashRef',
13             required => 1,
14             default => sub { +{} },
15             );
16              
17             no Moose;
18 153     153   1179  
  153         395  
  153         1002  
19             =head1 NAME
20              
21             Catalyst::DispatchType::Path - Path DispatchType
22              
23             =head1 SYNOPSIS
24              
25             See L<Catalyst::DispatchType>.
26              
27             =head1 DESCRIPTION
28              
29             Dispatch type managing full path matching behaviour. For more information on
30             dispatch types, see:
31              
32             =over 4
33              
34             =item * L<Catalyst::Manual::Intro> for how they affect application authors
35              
36             =item * L<Catalyst::DispatchType> for implementation information.
37              
38             =back
39              
40             =head1 METHODS
41              
42             =head2 $self->list($c)
43              
44             Debug output for Path dispatch points
45              
46             =cut
47              
48             my ( $self, $c ) = @_;
49             my $avail_width = Catalyst::Utils::term_width() - 9;
50 7     7 1 27 my $col1_width = ($avail_width * .50) < 35 ? 35 : int($avail_width * .50);
51 7         29 my $col2_width = $avail_width - $col1_width;
52 7 50       62 my $paths = Text::SimpleTable->new(
53 7         23 [ $col1_width, 'Path' ], [ $col2_width, 'Private' ]
54 7         60 );
55             foreach my $path ( sort keys %{ $self->_paths } ) {
56             foreach my $action ( @{ $self->_paths->{$path} } ) {
57 7         671 my $args = $action->number_of_args;
  7         247  
58 14         48394 my $parts = defined($args) ? '/*' x $args : '/...';
  14         462  
59 14         397  
60 14 100       52 my $display_path = "/$path/$parts";
61             $display_path =~ s{/{1,}}{/}g;
62 14         45 $display_path =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; # deconvert urlencoded for pretty view
63 14         85 $display_path = decode_utf8 $display_path; # URI does encoding
64 14         41 $paths->row( $display_path, "/$action" );
  0         0  
65 14         209 }
66 14         148 }
67             $c->log->debug( "Loaded Path actions:\n" . $paths->draw . "\n" )
68             if ( keys %{ $self->_paths } );
69             }
70 7 100       30697  
  7         260  
71             =head2 $self->match( $c, $path )
72              
73             For each action registered to this exact path, offers the action a chance to
74             match the path (in the order in which they were registered). Succeeds on the
75             first action that matches, if any; if not, returns 0.
76              
77             =cut
78              
79             my ( $self, $c, $path ) = @_;
80              
81             $path = '/' if !defined $path || !length $path;
82 1372     1372 1 4073  
83             my @actions = @{ $self->_paths->{$path} || [] };
84 1372 100 66     7480  
85             foreach my $action ( @actions ) {
86 1372 100       2496 next unless $action->match($c);
  1372         42472  
87             $c->req->action($path);
88 1372         3834 $c->req->match($path);
89 627 100       3129 $c->action($action);
90 587         2943 $c->namespace( $action->namespace );
91 587         2058 return 1;
92 587         15705 }
93 587         16134  
94 587         3062 return 0;
95             }
96              
97 785         3055 =head2 $self->register( $c, $action )
98              
99             Calls register_path for every Path attribute for the given $action.
100              
101             =cut
102              
103             my ( $self, $c, $action ) = @_;
104              
105             my @register = @{ $action->attributes->{Path} || [] };
106              
107 148307     148307 1 290803 $self->register_path( $c, $_, $action ) for @register;
108              
109 148307 100       208820 return 1 if @register;
  148307         3825756  
110             return 0;
111 148307         357346 }
112              
113 148307 100       368493 =head2 $self->register_path($c, $path, $action)
114 116074         331195  
115             Registers an action at a given path.
116              
117             =cut
118              
119             my ( $self, $c, $path, $action ) = @_;
120             $path =~ s!^/!!;
121             $path = '/' unless length $path;
122             $path = URI->new($path)->canonical;
123             $path =~ s{(?<=[^/])/+\z}{};
124 32752     32752 1 73210  
125 32752         69658 $self->_paths->{$path} = [
126 32752 100       75360 sort { $a->compare($b) } ($action, @{ $self->_paths->{$path} || [] })
127 32752         109956 ];
128 32752         1939203  
129             return 1;
130             }
131 32752 100       218726  
  3496         22012  
  32752         1027074  
132             =head2 $self->uri_for_action($action, $captures)
133              
134 32752         228041 get a URI part for an action; always returns undef is $captures is set
135             since Path actions don't have captures
136              
137             =cut
138              
139             my ( $self, $action, $captures ) = @_;
140              
141             return undef if @$captures;
142              
143             if (my $paths = $action->attributes->{Path}) {
144             my $path = $paths->[0];
145 129     129 1 273 $path = '/' unless length($path);
146             $path = "/${path}" unless ($path =~ m/^\//);
147 129 100       328 $path = URI->new($path)->canonical;
148             return $path;
149 34 100       877 } else {
150 22         72 return undef;
151 22 50       71 }
152 22 100       143 }
153 22         160  
154 22         1820 =head1 AUTHORS
155              
156 12         36 Catalyst Contributors, see Catalyst.pm
157              
158             =head1 COPYRIGHT
159              
160             This library is free software. You can redistribute it and/or modify it under
161             the same terms as Perl itself.
162              
163             =cut
164              
165             __PACKAGE__->meta->make_immutable;
166              
167             1;