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