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