sort { $a->reverse cmp $b->reverse }
@{ $self->_endpoints }
) {
- my $args = $endpoint->attributes->{Args}->[0];
+ my $args = $endpoint->list_extra_info->{Args};
my @parts = (defined($args) ? (("*") x $args) : '...');
my @parents = ();
my $parent = "DUMMY";
+ my $extra = $self->_list_extra_http_methods($endpoint);
my $curr = $endpoint;
while ($curr) {
- if (my $cap = $curr->attributes->{CaptureArgs}) {
- unshift(@parts, (("*") x $cap->[0]));
+ if (my $cap = $curr->list_extra_info->{CaptureArgs}) {
+ unshift(@parts, (("*") x $cap));
}
if (my $pp = $curr->attributes->{PathPart}) {
unshift(@parts, $pp->[0])
my @rows;
foreach my $p (@parents) {
my $name = "/${p}";
- if (my $cap = $p->attributes->{CaptureArgs}) {
- $name .= ' ('.$cap->[0].')';
+
+ if (defined(my $extra = $self->_list_extra_http_methods($p))) {
+ $name = "${extra} ${name}";
+ }
+ if (defined(my $cap = $p->list_extra_info->{CaptureArgs})) {
+ $name .= ' ('.$cap.')';
}
unless ($p eq $parents[0]) {
$name = "-> ${name}";
}
push(@rows, [ '', $name ]);
}
- push(@rows, [ '', (@rows ? "=> " : '')."/${endpoint}" ]);
+ push(@rows, [ '', (@rows ? "=> " : '').($extra ? "$extra " : '')."/${endpoint}" ]);
$rows[0][0] = join('/', '', @parts) || '/';
$paths->row(@$_) for @rows;
}
if $has_unattached_actions;
}
+sub _list_extra_http_methods {
+ my ( $self, $action ) = @_;
+ return unless defined $action->list_extra_info->{HTTP_METHODS};
+ return join(', ', @{$action->list_extra_info->{HTTP_METHODS}});
+}
+
=head2 $self->match( $c, $path )
Calls C<recurse_match> to see if a chain matches the C<$path>.
my @try_actions = @{$children->{$try_part}};
TRY_ACTION: foreach my $action (@try_actions) {
if (my $capture_attr = $action->attributes->{CaptureArgs}) {
+ $capture_attr ||= 0;
# Short-circuit if not enough remaining parts
- next TRY_ACTION unless @parts >= ($capture_attr->[0]||0);
+ next TRY_ACTION unless @parts >= $capture_attr->[0];
my @captures;
my @parts = @parts; # localise
# strip CaptureArgs into list
push(@captures, splice(@parts, 0, $capture_attr->[0]));
+ # check if the action may fit, depending on a given test by the app
+ if ($action->can('match_captures')) { next TRY_ACTION unless $action->match_captures($c, \@captures) }
+
# try the remaining parts against children of this action
my ($actions, $captures, $action_parts, $n_pathparts) = $self->recurse_match(
$c, '/'.$action->reverse, \@parts
if (!$best_action ||
@parts < @{$best_action->{parts}} ||
- (!@parts && $args_attr eq 0)){
+ (!@parts && defined($args_attr) && $args_attr eq "0")){
$best_action = {
actions => [ $action ],
captures=> [],
my $curr = $action;
while ($curr) {
if (my $cap = $curr->attributes->{CaptureArgs}) {
- return undef unless @captures >= $cap->[0]; # not enough captures
+ return undef unless @captures >= ($cap->[0]||0); # not enough captures
if ($cap->[0]) {
unshift(@parts, splice(@captures, -$cap->[0]));
}
}
__PACKAGE__->meta->make_immutable;
+1;
=head1 USAGE
you C<detach> out of a chain, the rest of the chain will not get called
after the C<detach>.
+=head2 match_captures
+
+A method which can optionally be implemented by actions to
+stop chain matching.
+
+See L<Catalyst::Action> for further details.
+
=head1 AUTHORS
Catalyst Contributors, see Catalyst.pm