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