Args() wasn't being processed as unlimited number of args, due to
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Controller.pm
1 package Catalyst::Controller;
2
3 use Moose;
4 use Class::MOP;
5 use Class::Load ':all';
6 use String::RewritePrefix;
7 use Moose::Util qw/find_meta/;
8 use List::Util qw/first/;
9 use List::MoreUtils qw/uniq/;
10 use namespace::clean -except => 'meta';
11
12 BEGIN {
13     extends qw/Catalyst::Component/;
14     with qw/MooseX::MethodAttributes::Role::AttrContainer::Inheritable/;
15 }
16
17 use MooseX::MethodAttributes;
18 use Catalyst::Exception;
19 use Catalyst::Utils;
20
21 with 'Catalyst::Component::ApplicationAttribute';
22
23 has path_prefix => (
24     is        => 'rw',
25     isa       => 'Str',
26     init_arg  => 'path',
27     predicate => 'has_path_prefix',
28 );
29
30 has action_namespace => (
31     is        => 'rw',
32     isa       => 'Str',
33     init_arg  => 'namespace',
34     predicate => 'has_action_namespace',
35 );
36
37 has actions => (
38     accessor => '_controller_actions',
39     isa      => 'HashRef',
40     init_arg => undef,
41 );
42
43 has _action_role_args => (
44     traits     => [qw(Array)],
45     isa        => 'ArrayRef[Str]',
46     init_arg   => 'action_roles',
47     default    => sub { [] },
48     handles    => {
49         _action_role_args => 'elements',
50     },
51 );
52
53 has _action_roles => (
54     traits     => [qw(Array)],
55     isa        => 'ArrayRef[RoleName]',
56     init_arg   => undef,
57     lazy       => 1,
58     builder    => '_build__action_roles',
59     handles    => {
60         _action_roles => 'elements',
61     },
62 );
63
64 has action_args => (is => 'ro');
65
66 # ->config(actions => { '*' => ...
67 has _all_actions_attributes => (
68     is       => 'ro',
69     isa      => 'HashRef',
70     init_arg => undef,
71     lazy     => 1,
72     builder  => '_build__all_actions_attributes',
73 );
74
75 sub BUILD {
76     my ($self, $args) = @_;
77     my $action  = delete $args->{action}  || {};
78     my $actions = delete $args->{actions} || {};
79     my $attr_value = $self->merge_config_hashes($actions, $action);
80     $self->_controller_actions($attr_value);
81
82     # trigger lazy builder
83     $self->_all_actions_attributes;
84     $self->_action_roles;
85 }
86
87 sub _build__action_roles {
88     my $self = shift;
89     my @roles = $self->_expand_role_shortname($self->_action_role_args);
90     load_class($_) for @roles;
91     return \@roles;
92 }
93
94 sub _build__all_actions_attributes {
95     my ($self) = @_;
96     delete $self->_controller_actions->{'*'} || {};
97 }
98
99 =head1 NAME
100
101 Catalyst::Controller - Catalyst Controller base class
102
103 =head1 SYNOPSIS
104
105   package MyApp::Controller::Search
106   use base qw/Catalyst::Controller/;
107
108   sub foo : Local {
109     my ($self,$c,@args) = @_;
110     ...
111   } # Dispatches to /search/foo
112
113 =head1 DESCRIPTION
114
115 Controllers are where the actions in the Catalyst framework
116 reside. Each action is represented by a function with an attribute to
117 identify what kind of action it is. See the L<Catalyst::Dispatcher>
118 for more info about how Catalyst dispatches to actions.
119
120 =cut
121
122 #I think both of these could be attributes. doesn't really seem like they need
123 #to be class data. i think that attributes +default would work just fine
124 __PACKAGE__->mk_classdata($_) for qw/_dispatch_steps _action_class _action_role_prefix/;
125
126 __PACKAGE__->_dispatch_steps( [qw/_BEGIN _AUTO _ACTION/] );
127 __PACKAGE__->_action_class('Catalyst::Action');
128 __PACKAGE__->_action_role_prefix([ 'Catalyst::ActionRole::' ]);
129
130
131 sub _DISPATCH : Private {
132     my ( $self, $c ) = @_;
133
134     foreach my $disp ( @{ $self->_dispatch_steps } ) {
135         last unless $c->forward($disp);
136     }
137
138     $c->forward('_END');
139 }
140
141 sub _BEGIN : Private {
142     my ( $self, $c ) = @_;
143     my $begin = ( $c->get_actions( 'begin', $c->namespace ) )[-1];
144     return 1 unless $begin;
145     $begin->dispatch( $c );
146     return !@{ $c->error };
147 }
148
149 sub _AUTO : Private {
150     my ( $self, $c ) = @_;
151     my @auto = $c->get_actions( 'auto', $c->namespace );
152     foreach my $auto (@auto) {
153         $auto->dispatch( $c );
154         return 0 unless $c->state;
155     }
156     return 1;
157 }
158
159 sub _ACTION : Private {
160     my ( $self, $c ) = @_;
161     if (   ref $c->action
162         && $c->action->can('execute')
163         && defined $c->req->action )
164     {
165         $c->action->dispatch( $c );
166     }
167     return !@{ $c->error };
168 }
169
170 sub _END : Private {
171     my ( $self, $c ) = @_;
172     my $end = ( $c->get_actions( 'end', $c->namespace ) )[-1];
173     return 1 unless $end;
174     $end->dispatch( $c );
175     return !@{ $c->error };
176 }
177
178 sub action_for {
179     my ( $self, $name ) = @_;
180     my $app = ($self->isa('Catalyst') ? $self : $self->_application);
181     return $app->dispatcher->get_action($name, $self->action_namespace);
182 }
183
184 #my opinion is that this whole sub really should be a builder method, not
185 #something that happens on every call. Anyone else disagree?? -- groditi
186 ## -- apparently this is all just waiting for app/ctx split
187 around action_namespace => sub {
188     my $orig = shift;
189     my ( $self, $c ) = @_;
190
191     my $class = ref($self) || $self;
192     my $appclass = ref($c) || $c;
193     if( ref($self) ){
194         return $self->$orig if $self->has_action_namespace;
195     } else {
196         return $class->config->{namespace} if exists $class->config->{namespace};
197     }
198
199     my $case_s;
200     if( $c ){
201         $case_s = $appclass->config->{case_sensitive};
202     } else {
203         if ($self->isa('Catalyst')) {
204             $case_s = $class->config->{case_sensitive};
205         } else {
206             if (ref $self) {
207                 $case_s = ref($self->_application)->config->{case_sensitive};
208             } else {
209                 confess("Can't figure out case_sensitive setting");
210             }
211         }
212     }
213
214     my $namespace = Catalyst::Utils::class2prefix($self->catalyst_component_name, $case_s) || '';
215     $self->$orig($namespace) if ref($self);
216     return $namespace;
217 };
218
219 #Once again, this is probably better written as a builder method
220 around path_prefix => sub {
221     my $orig = shift;
222     my $self = shift;
223     if( ref($self) ){
224       return $self->$orig if $self->has_path_prefix;
225     } else {
226       return $self->config->{path} if exists $self->config->{path};
227     }
228     my $namespace = $self->action_namespace(@_);
229     $self->$orig($namespace) if ref($self);
230     return $namespace;
231 };
232
233 sub get_action_methods {
234     my $self = shift;
235     my $meta = find_meta($self) || confess("No metaclass setup for $self");
236     confess(
237         sprintf "Metaclass %s for %s cannot support register_actions.",
238             ref $meta, $meta->name,
239     ) unless $meta->can('get_nearest_methods_with_attributes');
240     my @methods = $meta->get_nearest_methods_with_attributes;
241
242     # actions specified via config are also action_methods
243     push(
244         @methods,
245         map {
246             $meta->find_method_by_name($_)
247                 || confess( sprintf 'Action "%s" is not available from controller %s',
248                             $_, ref $self )
249         } keys %{ $self->_controller_actions }
250     ) if ( ref $self );
251     return uniq @methods;
252 }
253
254
255 sub register_actions {
256     my ( $self, $c ) = @_;
257     $self->register_action_methods( $c, $self->get_action_methods );
258 }
259
260 sub register_action_methods {
261     my ( $self, $c, @methods ) = @_;
262     my $class = $self->catalyst_component_name;
263     #this is still not correct for some reason.
264     my $namespace = $self->action_namespace($c);
265
266     # FIXME - fugly
267     if (!blessed($self) && $self eq $c && scalar(@methods)) {
268         my @really_bad_methods = grep { ! /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/ } map { $_->name } @methods;
269         if (scalar(@really_bad_methods)) {
270             $c->log->warn("Action methods (" . join(', ', @really_bad_methods) . ") found defined in your application class, $self. This is deprecated, please move them into a Root controller.");
271         }
272     }
273
274     foreach my $method (@methods) {
275         my $name = $method->name;
276         # Horrible hack! All method metaclasses should have an attributes
277         # method, core Moose bug - see r13354.
278         my $attributes = $method->can('attributes') ? $method->attributes : [];
279         my $attrs = $self->_parse_attrs( $c, $name, @{ $attributes } );
280         if ( $attrs->{Private} && ( keys %$attrs > 1 ) ) {
281             $c->log->warn( 'Bad action definition "'
282                   . join( ' ', @{ $attributes } )
283                   . qq/" for "$class->$name"/ )
284               if $c->debug;
285             next;
286         }
287         my $reverse = $namespace ? "${namespace}/${name}" : $name;
288         my $action = $self->create_action(
289             name       => $name,
290             code       => $method->body,
291             reverse    => $reverse,
292             namespace  => $namespace,
293             class      => $class,
294             attributes => $attrs,
295         );
296
297         $c->dispatcher->register( $c, $action );
298     }
299 }
300
301 sub _apply_action_class_roles {
302     my ($self, $class, @roles) = @_;
303
304     load_class($_) for @roles;
305     my $meta = Moose::Meta::Class->initialize($class)->create_anon_class(
306         superclasses => [$class],
307         roles        => \@roles,
308         cache        => 1,
309     );
310     $meta->add_method(meta => sub { $meta });
311
312     return $meta->name;
313 }
314
315 sub action_class {
316     my $self = shift;
317     my %args = @_;
318
319     my $class = (exists $args{attributes}{ActionClass}
320         ? $args{attributes}{ActionClass}[0]
321         : $self->_action_class);
322
323     load_class($class);
324     return $class;
325 }
326
327 sub create_action {
328     my $self = shift;
329     my %args = @_;
330
331     my $class = $self->action_class(%args);
332
333     load_class($class);
334     Moose->init_meta(for_class => $class)
335         unless Class::MOP::does_metaclass_exist($class);
336
337     unless ($args{name} =~ /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/) {
338        my @roles = $self->gather_action_roles(%args);
339        push @roles, $self->gather_default_action_roles(%args);
340
341        $class = $self->_apply_action_class_roles($class, @roles) if @roles;
342     }
343
344     my $action_args = (
345         ref($self)
346             ? $self->action_args
347             : $self->config->{action_args}
348     );
349
350     my %extra_args = (
351         %{ $action_args->{'*'}           || {} },
352         %{ $action_args->{ $args{name} } || {} },
353     );
354
355     return $class->new({ %extra_args, %args });
356 }
357
358 sub gather_action_roles {
359    my ($self, %args) = @_;
360    return (
361       (blessed $self ? $self->_action_roles : ()),
362       @{ $args{attributes}->{Does} || [] },
363    );
364 }
365
366 sub gather_default_action_roles {
367   my ($self, %args) = @_;
368   my @roles = ();
369   push @roles, 'Catalyst::ActionRole::HTTPMethods'
370     if $args{attributes}->{Method};
371
372   push @roles, 'Catalyst::ActionRole::ConsumesContent'
373     if $args{attributes}->{Consumes};
374
375   push @roles, 'Catalyst::ActionRole::Scheme'
376     if $args{attributes}->{Scheme};
377
378   push @roles, 'Catalyst::ActionRole::QueryMatching'
379     if $args{attributes}->{Query};
380     return @roles;
381 }
382
383 sub _parse_attrs {
384     my ( $self, $c, $name, @attrs ) = @_;
385
386     my %raw_attributes;
387
388     foreach my $attr (@attrs) {
389
390         # Parse out :Foo(bar) into Foo => bar etc (and arrayify)
391
392         if ( my ( $key, $value ) = ( $attr =~ /^(.*?)(?:\(\s*(.*?)\s*\))?$/ ) )
393         {
394
395             if ( defined $value ) {
396                 ( $value =~ s/^'(.*)'$/$1/ ) || ( $value =~ s/^"(.*)"/$1/ );
397             }
398             push( @{ $raw_attributes{$key} }, $value );
399         }
400     }
401
402     my ($actions_config, $all_actions_config);
403     if( ref($self) ) {
404         $actions_config = $self->_controller_actions;
405         # No, you're not getting actions => { '*' => ... } with actions in MyApp.
406         $all_actions_config = $self->_all_actions_attributes;
407     } else {
408         my $cfg = $self->config;
409         $actions_config = $self->merge_config_hashes($cfg->{actions}, $cfg->{action});
410         $all_actions_config = {};
411     }
412
413     %raw_attributes = (
414         %raw_attributes,
415         # Note we deep copy array refs here to stop crapping on config
416         # when attributes are parsed. RT#65463
417         exists $actions_config->{$name} ? map { ref($_) eq 'ARRAY' ? [ @$_ ] : $_ } %{ $actions_config->{$name } } : (),
418     );
419
420     # Private actions with additional attributes will raise a warning and then
421     # be ignored. Adding '*' arguments to the default _DISPATCH / etc. methods,
422     # which are Private, will prevent those from being registered. They should
423     # probably be turned into :Actions instead, or we might want to otherwise
424     # disambiguate between those built-in internal actions and user-level
425     # Private ones.
426     %raw_attributes = (%{ $all_actions_config }, %raw_attributes)
427         unless $raw_attributes{Private};
428
429     my %final_attributes;
430
431     while (my ($key, $value) = each %raw_attributes){
432         my $new_attrs = $self->_parse_attr($c, $name, $key => $value );
433         push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
434     }
435
436     return \%final_attributes;
437 }
438
439 sub _parse_attr {
440     my ($self, $c, $name, $key, $values) = @_;
441
442     my %final_attributes;
443     foreach my $value (ref($values) eq 'ARRAY' ? @$values : $values) {
444         my $meth = "_parse_${key}_attr";
445         if ( my $code = $self->can($meth) ) {
446             my %new_attrs = $self->$code( $c, $name, $value );
447             while (my ($new_key, $value) = each %new_attrs){
448                 my $new_attrs = $key eq $new_key ?
449                     { $new_key => [$value] } :
450                     $self->_parse_attr($c, $name, $new_key => $value );
451                 push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
452             }
453         }
454         else {
455             push( @{ $final_attributes{$key} }, $value );
456         }
457     }
458
459     return \%final_attributes;
460 }
461
462 sub _parse_Global_attr {
463     my ( $self, $c, $name, $value ) = @_;
464     # _parse_attr will call _parse_Path_attr for us
465     return Path => "/$name";
466 }
467
468 sub _parse_Absolute_attr { shift->_parse_Global_attr(@_); }
469
470 sub _parse_Local_attr {
471     my ( $self, $c, $name, $value ) = @_;
472     # _parse_attr will call _parse_Path_attr for us
473     return Path => $name;
474 }
475
476 sub _parse_Relative_attr { shift->_parse_Local_attr(@_); }
477
478 sub _parse_Path_attr {
479     my ( $self, $c, $name, $value ) = @_;
480     $value = '' if !defined $value;
481     if ( $value =~ m!^/! ) {
482         return ( 'Path', $value );
483     }
484     elsif ( length $value ) {
485         return ( 'Path', join( '/', $self->path_prefix($c), $value ) );
486     }
487     else {
488         return ( 'Path', $self->path_prefix($c) );
489     }
490 }
491
492 sub _parse_Chained_attr {
493     my ($self, $c, $name, $value) = @_;
494
495     if (defined($value) && length($value)) {
496         if ($value eq '.') {
497             $value = '/'.$self->action_namespace($c);
498         } elsif (my ($rel, $rest) = $value =~ /^((?:\.{2}\/)+)(.*)$/) {
499             my @parts = split '/', $self->action_namespace($c);
500             my @levels = split '/', $rel;
501
502             $value = '/'.join('/', @parts[0 .. $#parts - @levels], $rest);
503         } elsif ($value !~ m/^\//) {
504             my $action_ns = $self->action_namespace($c);
505
506             if ($action_ns) {
507                 $value = '/'.join('/', $action_ns, $value);
508             } else {
509                 $value = '/'.$value; # special case namespace '' (root)
510             }
511         }
512     } else {
513         $value = '/'
514     }
515
516     return Chained => $value;
517 }
518
519 sub _parse_ChainedParent_attr {
520     my ($self, $c, $name, $value) = @_;
521     return $self->_parse_Chained_attr($c, $name, '../'.$name);
522 }
523
524 sub _parse_PathPrefix_attr {
525     my ( $self, $c ) = @_;
526     return PathPart => $self->path_prefix($c);
527 }
528
529 sub _parse_ActionClass_attr {
530     my ( $self, $c, $name, $value ) = @_;
531     my $appname = $self->_application;
532     $value = Catalyst::Utils::resolve_namespace($appname . '::Action', $self->_action_class, $value);
533     return ( 'ActionClass', $value );
534 }
535
536 sub _parse_MyAction_attr {
537     my ( $self, $c, $name, $value ) = @_;
538
539     my $appclass = Catalyst::Utils::class2appclass($self);
540     $value = "+${appclass}::Action::${value}";
541
542     return ( 'ActionClass', $value );
543 }
544
545 sub _parse_Does_attr {
546     my ($self, $app, $name, $value) = @_;
547     return Does => $self->_expand_role_shortname($value);
548 }
549
550 sub _parse_GET_attr     { Method => 'GET'     }
551 sub _parse_POST_attr    { Method => 'POST'    }
552 sub _parse_PUT_attr     { Method => 'PUT'     }
553 sub _parse_DELETE_attr  { Method => 'DELETE'  }
554 sub _parse_OPTIONS_attr { Method => 'OPTIONS' }
555 sub _parse_HEAD_attr    { Method => 'HEAD'    }
556 sub _parse_PATCH_attr  { Method => 'PATCH'  }
557
558 sub _expand_role_shortname {
559     my ($self, @shortnames) = @_;
560     my $app = $self->_application;
561
562     my $prefix = $self->can('_action_role_prefix') ? $self->_action_role_prefix : ['Catalyst::ActionRole::'];
563     my @prefixes = (qq{${app}::ActionRole::}, @$prefix);
564
565     return String::RewritePrefix->rewrite(
566         { ''  => sub {
567             my $loaded = load_first_existing_class(
568                 map { "$_$_[0]" } @prefixes
569             );
570             return first { $loaded =~ /^$_/ }
571               sort { length $b <=> length $a } @prefixes;
572           },
573           '~' => $prefixes[0],
574           '+' => '' },
575         @shortnames,
576     );
577 }
578
579 __PACKAGE__->meta->make_immutable;
580
581 1;
582
583 __END__
584
585 =head1 CONFIGURATION
586
587 Like any other L<Catalyst::Component>, controllers have a config hash,
588 accessible through $self->config from the controller actions.  Some
589 settings are in use by the Catalyst framework:
590
591 =head2 namespace
592
593 This specifies the internal namespace the controller should be bound
594 to. By default the controller is bound to the URI version of the
595 controller name. For instance controller 'MyApp::Controller::Foo::Bar'
596 will be bound to 'foo/bar'. The default Root controller is an example
597 of setting namespace to '' (the null string).
598
599 =head2 path
600
601 Sets 'path_prefix', as described below.
602
603 =head2 action
604
605 Allows you to set the attributes that the dispatcher creates actions out of.
606 This allows you to do 'rails style routes', or override some of the
607 attribute definitions of actions composed from Roles.
608 You can set arguments globally (for all actions of the controller) and
609 specifically (for a single action).
610
611     __PACKAGE__->config(
612         action => {
613             '*' => { Chained => 'base', Args => 0  },
614             base => { Chained => '/', PathPart => '', CaptureArgs => 0 },
615         },
616      );
617
618 In the case above every sub in the package would be made into a Chain
619 endpoint with a URI the same as the sub name for each sub, chained
620 to the sub named C<base>. Ergo dispatch to C</example> would call the
621 C<base> method, then the C<example> method.
622
623 =head2 action_args
624
625 Allows you to set constructor arguments on your actions. You can set arguments
626 globally and specifically (as above).
627 This is particularly useful when using C<ActionRole>s
628 (L<Catalyst::Controller::ActionRole>) and custom C<ActionClass>es.
629
630     __PACKAGE__->config(
631         action_args => {
632             '*' => { globalarg1 => 'hello', globalarg2 => 'goodbye' },
633             'specific_action' => { customarg => 'arg1' },
634         },
635      );
636
637 In the case above the action class associated with C<specific_action> would get
638 passed the following arguments, in addition to the normal action constructor
639 arguments, when it is instantiated:
640
641   (globalarg1 => 'hello', globalarg2 => 'goodbye', customarg => 'arg1')
642
643 =head1 METHODS
644
645 =head2 BUILDARGS ($app, @args)
646
647 From L<Catalyst::Component::ApplicationAttribute>, stashes the application
648 instance as $self->_application.
649
650 =head2 $self->action_for('name')
651
652 Returns the Catalyst::Action object (if any) for a given method name
653 in this component.
654
655 =head2 $self->action_namespace($c)
656
657 Returns the private namespace for actions in this component. Defaults
658 to a value from the controller name (for
659 e.g. MyApp::Controller::Foo::Bar becomes "foo/bar") or can be
660 overridden from the "namespace" config key.
661
662
663 =head2 $self->path_prefix($c)
664
665 Returns the default path prefix for :PathPrefix, :Local and
666 relative :Path actions in this component. Defaults to the action_namespace or
667 can be overridden from the "path" config key.
668
669 =head2 $self->register_actions($c)
670
671 Finds all applicable actions for this component, creates
672 Catalyst::Action objects (using $self->create_action) for them and
673 registers them with $c->dispatcher.
674
675 =head2 $self->get_action_methods()
676
677 Returns a list of L<Moose::Meta::Method> objects, doing the
678 L<MooseX::MethodAttributes::Role::Meta::Method> role, which are the set of
679 action methods for this package.
680
681 =head2 $self->register_action_methods($c, @methods)
682
683 Creates action objects for a set of action methods using C< create_action >,
684 and registers them with the dispatcher.
685
686 =head2 $self->action_class(%args)
687
688 Used when a controller is creating an action to determine the correct base
689 action class to use.
690
691 =head2 $self->create_action(%args)
692
693 Called with a hash of data to be use for construction of a new
694 Catalyst::Action (or appropriate sub/alternative class) object.
695
696 =head2 $self->gather_action_roles(\%action_args)
697
698 Gathers the list of roles to apply to an action with the given %action_args.
699
700 =head2 $self->gather_default_action_roles(\%action_args)
701
702 returns a list of action roles to be applied based on core, builtin rules.
703 Currently only the L<Catalyst::ActionRole::HTTPMethods> role is applied
704 this way.
705
706 =head2 $self->_application
707
708 =head2 $self->_app
709
710 Returns the application instance stored by C<new()>
711
712 =head1 ACTION SUBROUTINE ATTRIBUTES
713
714 Please see L<Catalyst::Manual::Intro> for more details
715
716 Think of action attributes as a sort of way to record metadata about an action,
717 similar to how annotations work in other languages you might have heard of.
718 Generally L<Catalyst> uses these to influence how the dispatcher sees your
719 action and when it will run it in response to an incoming request.  They can
720 also be used for other things.  Here's a summary, but you should refer to the
721 linked manual page for additional help.
722
723 =head2 Global
724
725   sub homepage :Global { ... }
726
727 A global action defined in any controller always runs relative to your root.
728 So the above is the same as:
729
730   sub myaction :Path("/homepage") { ... }
731
732 =head2 Absolute
733
734 Status: Deprecated alias to L</Global>.
735
736 =head2 Local
737
738 Alias to "Path("$action_name").  The following two actions are the same:
739
740   sub myaction :Local { ... }
741   sub myaction :Path('myaction') { ... }
742
743 =head2 Relative
744
745 Status: Deprecated alias to L</Local>
746
747 =head2 Path
748
749 Handle various types of paths:
750
751   package MyApp::Controller::Baz {
752
753     ...
754
755     sub myaction1 :Path { ... }  # -> /baz
756     sub myaction2 :Path('foo') { ... } # -> /baz/foo
757     sub myaction2 :Path('/bar') { ... } # -> /bar
758   }
759
760 This is a general toolbox for attaching your action to a given path.
761
762
763 =head2 Regex
764
765 =head2 Regexp
766
767 B<Status: Deprecated.>  Use Chained methods or other techniques.
768 If you really depend on this, install the standalone 
769 L<Catalyst::DispatchType::Regex> distribution.
770
771 A global way to match a give regular expression in the incoming request path.
772
773 =head2 LocalRegex
774
775 =head2 LocalRegexp
776
777 B<Status: Deprecated.>  Use Chained methods or other techniques.
778 If you really depend on this, install the standalone 
779 L<Catalyst::DispatchType::Regex> distribution.
780
781 Like L</Regex> but scoped under the namespace of the containing controller
782
783 =head2 Chained 
784
785 =head2 ChainedParent
786
787 =head2 PathPrefix
788
789 =head2 PathPart
790
791 =head2 CaptureArgs
792
793 Allowed values for CaptureArgs is a single integer (CaptureArgs(2), meaning two
794 allowed) or you can declare a L<Moose>, L<MooseX::Types> or L<Type::Tiny>
795 named constraint such as CaptureArgs(Int,Str) would require two args with
796 the first being a Integer and the second a string.  You may declare your own
797 custom type constraints and import them into the controller namespace:
798
799     package MyApp::Controller::Root;
800
801     use Moose;
802     use MooseX::MethodAttributes;
803     use MyApp::Types qw/Int/;
804
805     extends 'Catalyst::Controller';
806
807     sub chain_base :Chained(/) CaptureArgs(1) { }
808
809       sub any_priority_chain :Chained(chain_base) PathPart('') Args(1) { }
810
811       sub int_priority_chain :Chained(chain_base) PathPart('') Args(Int) { }
812
813 See L<Catalyst::RouteMatching> for more.
814
815 Please see L<Catalyst::DispatchType::Chained> for more.
816
817 =head2 ActionClass
818
819 Set the base class for the action, defaults to L</Catalyst::Action>.  It is now
820 preferred to use L</Does>.
821
822 =head2 MyAction
823
824 Set the ActionClass using a custom Action in your project namespace.
825
826 The following is exactly the same:
827
828     sub foo_action1 : Local ActionClass('+MyApp::Action::Bar') { ... }
829     sub foo_action2 : Local MyAction('Bar') { ... }
830
831 =head2 Does
832
833     package MyApp::Controller::Zoo;
834
835     sub foo  : Local Does('Moo')  { ... } # Catalyst::ActionRole::
836     sub bar  : Local Does('~Moo') { ... } # MyApp::ActionRole::Moo
837     sub baz  : Local Does('+MyApp::ActionRole::Moo') { ... }
838
839 =head2 GET
840
841 =head2 POST
842
843 =head2 PUT
844
845 =head2 DELETE
846
847 =head2 OPTION
848
849 =head2 HEAD
850
851 =head2 PATCH
852
853 =head2 Method('...')
854
855 Sets the give action path to match the specified HTTP method, or via one of the
856 broadly accepted methods of overriding the 'true' method (see
857 L<Catalyst::ActionRole::HTTPMethods>).
858
859 =head2 Args
860
861 When used with L</Path> indicates the number of arguments expected in
862 the path.  However if no Args value is set, assumed to 'slurp' all
863 remaining path pars under this namespace.
864
865 Allowed values for Args is a single integer (Args(2), meaning two allowed) or you
866 can declare a L<Moose>, L<MooseX::Types> or L<Type::Tiny> named constraint such
867 as Args(Int,Str) would require two args with the first being a Integer and the
868 second a string.  You may declare your own custom type constraints and import
869 them into the controller namespace:
870
871     package MyApp::Controller::Root;
872
873     use Moose;
874     use MooseX::MethodAttributes;
875     use MyApp::Types qw/Tuple Int Str StrMatch UserId/;
876
877     extends 'Catalyst::Controller';
878
879     sub user :Local Args(UserId) {
880       my ($self, $c, $int) = @_;
881     }
882
883     sub an_int :Local Args(Int) {
884       my ($self, $c, $int) = @_;
885     }
886
887     sub many_ints :Local Args(ArrayRef[Int]) {
888       my ($self, $c, @ints) = @_;
889     }
890
891     sub match :Local Args(StrMatch[qr{\d\d-\d\d-\d\d}]) {
892       my ($self, $c, $int) = @_;
893     }
894
895 If you choose not to use imported type constraints (like L<Type::Tiny>, or <MooseX::Types>
896 you may use L<Moose> 'stringy' types however just like when you use these types in your
897 declared attributes you must quote them:
898
899     sub my_moose_type :Local Args('Int') { ... }
900
901 If you use 'reference' type constraints (such as ArrayRef[Int]) that have an unknown
902 number of allowed matches, we set this the same way "Args" is.  Please keep in mind
903 that actions with an undetermined number of args match at lower precidence than those
904 with a fixed number.  You may use reference types such as Tuple from L<Types::Standard>
905 that allows you to fix the number of allowed args.  For example Args(Tuple[Int,Int])
906 would be determined to be two args (or really the same as Args(Int,Int).)  You may
907 find this useful for creating custom subtypes with complex matching rules that you 
908 wish to reuse over many actions.
909
910 See L<Catalyst::RouteMatching> for more.
911
912 =head2 Consumes('...')
913
914 Matches the current action against the content-type of the request.  Typically
915 this is used when the request is a POST or PUT and you want to restrict the
916 submitted content type.  For example, you might have an HTML for that either
917 returns classic url encoded form data, or JSON when Javascript is enabled.  In
918 this case you may wish to match either incoming type to one of two different
919 actions, for properly processing.
920
921 Examples:
922
923     sub is_json       : Chained('start') Consumes('application/json') { ... }
924     sub is_urlencoded : Chained('start') Consumes('application/x-www-form-urlencoded') { ... }
925     sub is_multipart  : Chained('start') Consumes('multipart/form-data') { ... }
926
927 To reduce boilerplate, we include the following content type shortcuts:
928
929 Examples
930
931       sub is_json       : Chained('start') Consume(JSON) { ... }
932       sub is_urlencoded : Chained('start') Consumes(UrlEncoded) { ... }
933       sub is_multipart  : Chained('start') Consumes(Multipart) { ... }
934
935 You may specify more than one match:
936
937       sub is_more_than_one
938         : Chained('start')
939         : Consumes('application/x-www-form-urlencoded')
940         : Consumes('multipart/form-data')
941
942       sub is_more_than_one
943         : Chained('start')
944         : Consumes(UrlEncoded)
945         : Consumes(Multipart)
946
947 Since it is a common case the shortcut C<HTMLForm> matches both
948 'application/x-www-form-urlencoded' and 'multipart/form-data'.  Here's the full
949 list of available shortcuts:
950
951     JSON => 'application/json',
952     JS => 'application/javascript',
953     PERL => 'application/perl',
954     HTML => 'text/html',
955     XML => 'text/XML',
956     Plain => 'text/plain',
957     UrlEncoded => 'application/x-www-form-urlencoded',
958     Multipart => 'multipart/form-data',
959     HTMLForm => ['application/x-www-form-urlencoded','multipart/form-data'],
960
961 Please keep in mind that when dispatching, L<Catalyst> will match the first most
962 relevant case, so if you use the C<Consumes> attribute, you should place your
963 most accurate matches early in the Chain, and your 'catchall' actions last.
964
965 See L<Catalyst::ActionRole::ConsumesContent> for more.
966
967 =head2 Scheme(...)
968
969 Allows you to specify a URI scheme for the action or action chain.  For example
970 you can required that a given path be C<https> or that it is a websocket endpoint
971 C<ws> or C<wss>.  For an action chain you may currently only have one defined
972 Scheme.
973
974     package MyApp::Controller::Root;
975
976     use base 'Catalyst::Controller';
977
978     sub is_http :Path(scheme) Scheme(http) Args(0) {
979       my ($self, $c) = @_;
980       $c->response->body("is_http");
981     }
982
983     sub is_https :Path(scheme) Scheme(https) Args(0)  {
984       my ($self, $c) = @_;
985       $c->response->body("is_https");
986     }
987
988 In the above example http://localhost/root/scheme would match the first
989 action (is_http) but https://localhost/root/scheme would match the second.
990
991 As an added benefit, if an action or action chain defines a Scheme, when using
992 $c->uri_for the scheme of the generated URL will use what you define in the action
993 or action chain (the current behavior is to set the scheme based on the current
994 incoming request).  This makes it easier to use uri_for on websites where some
995 paths are secure and others are not.  You may also use this to other schemes
996 like websockets.
997
998 See L<Catalyst::ActionRole::Scheme> for more.
999
1000 =head1 OPTIONAL METHODS
1001
1002 =head2 _parse_[$name]_attr
1003
1004 Allows you to customize parsing of subroutine attributes.
1005
1006     sub myaction1 :Path TwoArgs { ... }
1007
1008     sub _parse_TwoArgs_attr {
1009       my ( $self, $c, $name, $value ) = @_;
1010       # $self -> controller instance
1011       #
1012       return(Args => 2);
1013     }
1014
1015 Please note that this feature does not let you actually assign new functions
1016 to actions via subroutine attributes, but is really more for creating useful
1017 aliases to existing core and extended attributes, and transforms based on 
1018 existing information (like from configuration).  Code for actually doing
1019 something meaningful with the subroutine attributes will be located in the
1020 L<Catalyst::Action> classes (or your subclasses), L<Catalyst::Dispatcher> and
1021 in subclasses of L<Catalyst::DispatchType>.  Remember these methods only get
1022 called basically once when the application is starting, not per request!
1023
1024 =head1 AUTHORS
1025
1026 Catalyst Contributors, see Catalyst.pm
1027
1028 =head1 COPYRIGHT
1029
1030 This library is free software. You can redistribute it and/or modify
1031 it under the same terms as Perl itself.
1032
1033 =cut