use Catalyst::ActionChain;
use Catalyst::Utils;
use URI;
+use Scalar::Util ();
has _endpoints => (
is => 'rw',
=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 ) = @_;
=head1 DESCRIPTION
-See L</USAGE>.
+Dispatch type managing default behaviour. For more information on
+dispatch types, see:
+
+=over 4
+
+=item * L<Catalyst::Manual::Intro> for how they affect application authors
+
+=item * L<Catalyst::DispatchType> for implementation information.
+
+=back
=head1 METHODS
my $has_unattached_actions;
my $unattached_actions = Text::SimpleTable->new(
- [ 35, 'Private' ], [ 36, 'Missing parent' ],
+ [ 35, 'Private' ], [ $column_width, 'Missing parent' ],
);
ENDPOINT: foreach my $endpoint (
}
if ($parent ne '/') {
$has_unattached_actions = 1;
- $unattached_actions->row('/'.$parents[0]->reverse, $parent);
+ $unattached_actions->row('/' . ($parents[0] || $endpoint)->reverse, $parent);
next ENDPOINT;
}
my @rows;
push(@rows, [ '', $name ]);
}
push(@rows, [ '', (@rows ? "=> " : '')."/${endpoint}" ]);
- $rows[0][0] = join('/', '', @parts);
+ $rows[0][0] = join('/', '', @parts) || '/';
$paths->row(@$_) for @rows;
}
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;
$self->_actions->{'/'.$action->reverse} = $action;
+ if (exists $action->attributes->{Args}) {
+ my $args = $action->attributes->{Args}->[0];
+ if (defined($args) and not (
+ Scalar::Util::looks_like_number($args) and
+ int($args) == $args
+ )) {
+ require Data::Dumper;
+ local $Data::Dumper::Terse = 1;
+ local $Data::Dumper::Indent = 0;
+ $args = Data::Dumper::Dumper($args);
+ Catalyst::Exception->throw(
+ "Invalid Args($args) for action " . $action->reverse() .
+ " (use 'Args' or 'Args(<number>)'"
+ );
+ }
+ }
+
unless ($action->attributes->{CaptureArgs}) {
unshift(@{ $self->_endpoints }, $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}) {
return undef if @captures; # fail for too many captures
return join('/', '', @parts);
-
+
}
=head2 $c->expand_action($action)
=head1 COPYRIGHT
-This program is free software, you can redistribute it and/or modify it under
+This library is free software. You can redistribute it and/or modify it under
the same terms as Perl itself.
=cut