X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Runtime.git;a=blobdiff_plain;f=lib%2FCatalyst%2FDispatchType%2FChained.pm;h=18e7c5928e81fc81f37d037fd4a1722eb1beaf2e;hp=399a3788c6083e9b4dacaa4b765f52170f66d450;hb=634780e00f88651be2fe6f261d56604e313b369a;hpb=d21a2b27d12dd019f96f1ff1a5139728373ae779 diff --git a/lib/Catalyst/DispatchType/Chained.pm b/lib/Catalyst/DispatchType/Chained.pm index 399a378..18e7c59 100644 --- a/lib/Catalyst/DispatchType/Chained.pm +++ b/lib/Catalyst/DispatchType/Chained.pm @@ -5,6 +5,7 @@ extends 'Catalyst::DispatchType'; use Text::SimpleTable; use Catalyst::ActionChain; +use Catalyst::Utils; use URI; has _endpoints => ( @@ -38,6 +39,8 @@ Catalyst::DispatchType::Chained - Path Part DispatchType =head1 SYNOPSIS +Path part matching, allowing several actions to sequentially take care of processing a request: + # root action - captures one argument after it sub foo_setup : Chained('/') PathPart('foo') CaptureArgs(1) { my ( $self, $c, $foo_arg ) = @_; @@ -52,7 +55,16 @@ Catalyst::DispatchType::Chained - Path Part DispatchType =head1 DESCRIPTION -See L. +Dispatch type managing default behaviour. For more information on +dispatch types, see: + +=over 4 + +=item * L for how they affect application authors + +=item * L for implementation information. + +=back =head1 METHODS @@ -67,9 +79,15 @@ sub list { return unless $self->_endpoints; + my $column_width = Catalyst::Utils::term_width() - 35 - 9; my $paths = Text::SimpleTable->new( - [ 35, 'Path Spec' ], [ 36, 'Private' ] - ); + [ 35, 'Path Spec' ], [ $column_width, 'Private' ], + ); + + my $has_unattached_actions; + my $unattached_actions = Text::SimpleTable->new( + [ 35, 'Private' ], [ $column_width, 'Missing parent' ], + ); ENDPOINT: foreach my $endpoint ( sort { $a->reverse cmp $b->reverse } @@ -92,7 +110,11 @@ sub list { $curr = $self->_actions->{$parent}; unshift(@parents, $curr) if $curr; } - next ENDPOINT unless $parent eq '/'; # skip dangling action + if ($parent ne '/') { + $has_unattached_actions = 1; + $unattached_actions->row('/' . ($parents[0] || $endpoint)->reverse, $parent); + next ENDPOINT; + } my @rows; foreach my $p (@parents) { my $name = "/${p}"; @@ -105,11 +127,13 @@ sub list { push(@rows, [ '', $name ]); } push(@rows, [ '', (@rows ? "=> " : '')."/${endpoint}" ]); - $rows[0][0] = join('/', '', @parts); + $rows[0][0] = join('/', '', @parts) || '/'; $paths->row(@$_) for @rows; } $c->log->debug( "Loaded Chained actions:\n" . $paths->draw . "\n" ); + $c->log->debug( "Unattached Chained actions:\n", $unattached_actions->draw . "\n" ) + if $has_unattached_actions; } =head2 $self->match( $c, $path ) @@ -127,7 +151,13 @@ sub match { my @parts = split('/', $path); my ($chain, $captures, $parts) = $self->recurse_match($c, '/', \@parts); - push @{$request->args}, @$parts if $parts && @$parts; + + if ($parts && @$parts) { + for my $arg (@$parts) { + $arg =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; + push @{$request->args}, $arg; + } + } return 0 unless $chain; @@ -245,8 +275,13 @@ sub register { "Multiple Chained attributes not supported registering ${action}" ); } + my $chained_to = $chained_attr[0]; + + Catalyst::Exception->throw( + "Actions cannot chain to themselves registering /${action}" + ) if ($chained_to eq '/' . $action); - my $children = ($self->_children_of->{ $chained_attr[0] } ||= {}); + my $children = ($self->_children_of->{ $chained_to } ||= {}); my @path_part = @{ $action->attributes->{PathPart} || [] }; @@ -300,7 +335,9 @@ sub uri_for_action { if (my $cap = $curr->attributes->{CaptureArgs}) { return undef unless @captures >= $cap->[0]; # not enough captures if ($cap->[0]) { - unshift(@parts, splice(@captures, -$cap->[0])); + unshift(@parts, + map { s/([^A-Za-z0-9\-_.!~*'()])/$URI::Escape::escapes{$1}/go; $_; } + splice(@captures, -$cap->[0])); } } if (my $pp = $curr->attributes->{PartPath}) { @@ -316,7 +353,32 @@ sub uri_for_action { return undef if @captures; # fail for too many captures return join('/', '', @parts); - + +} + +=head2 $c->expand_action($action) + +Return a list of actions that represents a chained action. See +L for more info. You probably want to +use the expand_action it provides rather than this directly. + +=cut + +sub expand_action { + my ($self, $action) = @_; + + return unless $action->attributes && $action->attributes->{Chained}; + + my @chain; + my $curr = $action; + + while ($curr) { + push @chain, $curr; + my $parent = $curr->attributes->{Chained}->[0]; + $curr = $self->_actions->{$parent}; + } + + return Catalyst::ActionChain->from_chain([reverse @chain]); } __PACKAGE__->meta->make_immutable;