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