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 152     152   94377 extends 'Catalyst::DispatchType';
  152         412  
  152         1115  
4              
5             use Text::SimpleTable;
6 152     152   919216 use Catalyst::Utils;
  152         433  
  152         4065  
7 152     152   856 use URI;
  152         309  
  152         3131  
8 152     152   788 use Encode 2.21 'decode_utf8';
  152         321  
  152         4473  
9 152     152   10800  
  152         3741  
  152         13624  
10             has _paths => (
11             is => 'rw',
12             isa => 'HashRef',
13             required => 1,
14             default => sub { +{} },
15             );
16              
17             no Moose;
18 152     152   1326  
  152         347  
  152         945  
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 24 my $col1_width = ($avail_width * .50) < 35 ? 35 : int($avail_width * .50);
51 7         25 my $col2_width = $avail_width - $col1_width;
52 7 50       60 my $paths = Text::SimpleTable->new(
53 7         17 [ $col1_width, 'Path' ], [ $col2_width, 'Private' ]
54 7         55 );
55             foreach my $path ( sort keys %{ $self->_paths } ) {
56             foreach my $action ( @{ $self->_paths->{$path} } ) {
57 7         521 my $args = $action->number_of_args;
  7         248  
58 14         41150 my $parts = defined($args) ? '/*' x $args : '/...';
  14         373  
59 14         369  
60 14 100       56 my $display_path = "/$path/$parts";
61             $display_path =~ s{/{1,}}{/}g;
62 14         40 $display_path =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; # deconvert urlencoded for pretty view
63 14         70 $display_path = decode_utf8 $display_path; # URI does encoding
64 14         29 $paths->row( $display_path, "/$action" );
  0         0  
65 14         206 }
66 14         169 }
67             $c->log->debug( "Loaded Path actions:\n" . $paths->draw . "\n" )
68             if ( keys %{ $self->_paths } );
69             }
70 7 100       27824  
  7         203  
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 1370     1370 1 2986  
83             my @actions = @{ $self->_paths->{$path} || [] };
84 1370 100 66     5503  
85             foreach my $action ( @actions ) {
86 1370 100       1972 next unless $action->match($c);
  1370         34092  
87             $c->req->action($path);
88 1370         3068 $c->req->match($path);
89 625 100       2373 $c->action($action);
90 585         2210 $c->namespace( $action->namespace );
91 585         1637 return 1;
92 585         12485 }
93 585         13612  
94 585         2398 return 0;
95             }
96              
97 785         2506 =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 148295     148295 1 237342 $self->register_path( $c, $_, $action ) for @register;
108              
109 148295 100       174301 return 1 if @register;
  148295         3174945  
110             return 0;
111 148295         293653 }
112              
113 148295 100       308972 =head2 $self->register_path($c, $path, $action)
114 116064         279394  
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 32750     32750 1 59355  
125 32750         56320 $self->_paths->{$path} = [
126 32750 100       59368 sort { $a->compare($b) } ($action, @{ $self->_paths->{$path} || [] })
127 32750         87968 ];
128 32750         1586058  
129             return 1;
130             }
131 32750 100       178115  
  3496         20004  
  32750         848042  
132             =head2 $self->uri_for_action($action, $captures)
133              
134 32750         197312 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 226 $path = '/' unless length($path);
146             $path = "/${path}" unless ($path =~ m/^\//);
147 129 100       275 $path = URI->new($path)->canonical;
148             return $path;
149 34 100       742 } else {
150 22         57 return undef;
151 22 50       72 }
152 22 100       109 }
153 22         154  
154 22         1567 =head1 AUTHORS
155              
156 12         29 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;