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