1 package Catalyst::Controller;
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';
13 extends qw/Catalyst::Component/;
14 with qw/MooseX::MethodAttributes::Role::AttrContainer::Inheritable/;
17 use MooseX::MethodAttributes;
18 use Catalyst::Exception;
21 with 'Catalyst::Component::ApplicationAttribute';
27 predicate => 'has_path_prefix',
30 has action_namespace => (
33 init_arg => 'namespace',
34 predicate => 'has_action_namespace',
38 accessor => '_controller_actions',
43 has _action_role_args => (
44 traits => [qw(Array)],
45 isa => 'ArrayRef[Str]',
46 init_arg => 'action_roles',
47 default => sub { [] },
49 _action_role_args => 'elements',
53 has _action_roles => (
54 traits => [qw(Array)],
55 isa => 'ArrayRef[RoleName]',
58 builder => '_build__action_roles',
60 _action_roles => 'elements',
64 has action_args => (is => 'ro');
66 # ->config(actions => { '*' => ...
67 has _all_actions_attributes => (
72 builder => '_build__all_actions_attributes',
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);
82 # trigger lazy builder
83 $self->_all_actions_attributes;
87 sub _build__action_roles {
89 my @roles = $self->_expand_role_shortname($self->_action_role_args);
90 load_class($_) for @roles;
94 sub _build__all_actions_attributes {
96 delete $self->_controller_actions->{'*'} || {};
101 Catalyst::Controller - Catalyst Controller base class
105 package MyApp::Controller::Search
106 use base qw/Catalyst::Controller/;
109 my ($self,$c,@args) = @_;
111 } # Dispatches to /search/foo
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.
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/;
126 __PACKAGE__->_dispatch_steps( [qw/_BEGIN _AUTO _ACTION/] );
127 __PACKAGE__->_action_class('Catalyst::Action');
128 __PACKAGE__->_action_role_prefix([ 'Catalyst::ActionRole::' ]);
131 sub _DISPATCH : Private {
132 my ( $self, $c ) = @_;
134 foreach my $disp ( @{ $self->_dispatch_steps } ) {
135 last unless $c->forward($disp);
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 };
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;
159 sub _ACTION : Private {
160 my ( $self, $c ) = @_;
162 && $c->action->can('execute')
163 && defined $c->req->action )
165 $c->action->dispatch( $c );
167 return !@{ $c->error };
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 };
179 my ( $self, $name ) = @_;
180 my $app = ($self->isa('Catalyst') ? $self : $self->_application);
181 return $app->dispatcher->get_action($name, $self->action_namespace);
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 {
189 my ( $self, $c ) = @_;
191 my $class = ref($self) || $self;
192 my $appclass = ref($c) || $c;
194 return $self->$orig if $self->has_action_namespace;
196 return $class->config->{namespace} if exists $class->config->{namespace};
201 $case_s = $appclass->config->{case_sensitive};
203 if ($self->isa('Catalyst')) {
204 $case_s = $class->config->{case_sensitive};
207 $case_s = ref($self->_application)->config->{case_sensitive};
209 confess("Can't figure out case_sensitive setting");
214 my $namespace = Catalyst::Utils::class2prefix($self->catalyst_component_name, $case_s) || '';
215 $self->$orig($namespace) if ref($self);
219 #Once again, this is probably better written as a builder method
220 around path_prefix => sub {
224 return $self->$orig if $self->has_path_prefix;
226 return $self->config->{path} if exists $self->config->{path};
228 my $namespace = $self->action_namespace(@_);
229 $self->$orig($namespace) if ref($self);
233 sub get_action_methods {
235 my $meta = find_meta($self) || confess("No metaclass setup for $self");
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;
242 # actions specified via config are also action_methods
246 $meta->find_method_by_name($_)
247 || confess( sprintf 'Action "%s" is not available from controller %s',
249 } keys %{ $self->_controller_actions }
251 return uniq @methods;
255 sub register_actions {
256 my ( $self, $c ) = @_;
257 $self->register_action_methods( $c, $self->get_action_methods );
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);
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.");
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->trace(1, 'Bad action definition "'
282 . join( ' ', @{ $attributes } )
283 . qq/" for "$class->$name"/ );
286 my $reverse = $namespace ? "${namespace}/${name}" : $name;
287 my $action = $self->create_action(
289 code => $method->body,
291 namespace => $namespace,
293 attributes => $attrs,
296 $c->dispatcher->register( $c, $action );
300 sub _apply_action_class_roles {
301 my ($self, $class, @roles) = @_;
303 load_class($_) for @roles;
304 my $meta = Moose::Meta::Class->initialize($class)->create_anon_class(
305 superclasses => [$class],
309 $meta->add_method(meta => sub { $meta });
318 my $class = (exists $args{attributes}{ActionClass}
319 ? $args{attributes}{ActionClass}[0]
320 : $self->_action_class);
330 my $class = $self->action_class(%args);
333 Moose->init_meta(for_class => $class)
334 unless Class::MOP::does_metaclass_exist($class);
336 unless ($args{name} =~ /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/) {
337 my @roles = $self->gather_action_roles(%args);
338 push @roles, $self->gather_default_action_roles(%args);
340 $class = $self->_apply_action_class_roles($class, @roles) if @roles;
346 : $self->config->{action_args}
350 %{ $action_args->{'*'} || {} },
351 %{ $action_args->{ $args{name} } || {} },
354 return $class->new({ %extra_args, %args });
357 sub gather_action_roles {
358 my ($self, %args) = @_;
360 (blessed $self ? $self->_action_roles : ()),
361 @{ $args{attributes}->{Does} || [] },
365 sub gather_default_action_roles {
366 my ($self, %args) = @_;
368 push @roles, 'Catalyst::ActionRole::HTTPMethods'
369 if $args{attributes}->{Method};
371 push @roles, 'Catalyst::ActionRole::ConsumesContent'
372 if $args{attributes}->{Consumes};
378 my ( $self, $c, $name, @attrs ) = @_;
382 foreach my $attr (@attrs) {
384 # Parse out :Foo(bar) into Foo => bar etc (and arrayify)
386 if ( my ( $key, $value ) = ( $attr =~ /^(.*?)(?:\(\s*(.+?)\s*\))?$/ ) )
389 if ( defined $value ) {
390 ( $value =~ s/^'(.*)'$/$1/ ) || ( $value =~ s/^"(.*)"/$1/ );
392 push( @{ $raw_attributes{$key} }, $value );
396 my ($actions_config, $all_actions_config);
398 $actions_config = $self->_controller_actions;
399 # No, you're not getting actions => { '*' => ... } with actions in MyApp.
400 $all_actions_config = $self->_all_actions_attributes;
402 my $cfg = $self->config;
403 $actions_config = $self->merge_config_hashes($cfg->{actions}, $cfg->{action});
404 $all_actions_config = {};
409 # Note we deep copy array refs here to stop crapping on config
410 # when attributes are parsed. RT#65463
411 exists $actions_config->{$name} ? map { ref($_) eq 'ARRAY' ? [ @$_ ] : $_ } %{ $actions_config->{$name } } : (),
414 # Private actions with additional attributes will raise a warning and then
415 # be ignored. Adding '*' arguments to the default _DISPATCH / etc. methods,
416 # which are Private, will prevent those from being registered. They should
417 # probably be turned into :Actions instead, or we might want to otherwise
418 # disambiguate between those built-in internal actions and user-level
420 %raw_attributes = (%{ $all_actions_config }, %raw_attributes)
421 unless $raw_attributes{Private};
423 my %final_attributes;
425 while (my ($key, $value) = each %raw_attributes){
426 my $new_attrs = $self->_parse_attr($c, $name, $key => $value );
427 push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
430 return \%final_attributes;
434 my ($self, $c, $name, $key, $values) = @_;
436 my %final_attributes;
437 foreach my $value (ref($values) eq 'ARRAY' ? @$values : $values) {
438 my $meth = "_parse_${key}_attr";
439 if ( my $code = $self->can($meth) ) {
440 my %new_attrs = $self->$code( $c, $name, $value );
441 while (my ($new_key, $value) = each %new_attrs){
442 my $new_attrs = $key eq $new_key ?
443 { $new_key => [$value] } :
444 $self->_parse_attr($c, $name, $new_key => $value );
445 push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
449 push( @{ $final_attributes{$key} }, $value );
453 return \%final_attributes;
456 sub _parse_Global_attr {
457 my ( $self, $c, $name, $value ) = @_;
458 # _parse_attr will call _parse_Path_attr for us
459 return Path => "/$name";
462 sub _parse_Absolute_attr { shift->_parse_Global_attr(@_); }
464 sub _parse_Local_attr {
465 my ( $self, $c, $name, $value ) = @_;
466 # _parse_attr will call _parse_Path_attr for us
467 return Path => $name;
470 sub _parse_Relative_attr { shift->_parse_Local_attr(@_); }
472 sub _parse_Path_attr {
473 my ( $self, $c, $name, $value ) = @_;
474 $value = '' if !defined $value;
475 if ( $value =~ m!^/! ) {
476 return ( 'Path', $value );
478 elsif ( length $value ) {
479 return ( 'Path', join( '/', $self->path_prefix($c), $value ) );
482 return ( 'Path', $self->path_prefix($c) );
486 sub _parse_Chained_attr {
487 my ($self, $c, $name, $value) = @_;
489 if (defined($value) && length($value)) {
491 $value = '/'.$self->action_namespace($c);
492 } elsif (my ($rel, $rest) = $value =~ /^((?:\.{2}\/)+)(.*)$/) {
493 my @parts = split '/', $self->action_namespace($c);
494 my @levels = split '/', $rel;
496 $value = '/'.join('/', @parts[0 .. $#parts - @levels], $rest);
497 } elsif ($value !~ m/^\//) {
498 my $action_ns = $self->action_namespace($c);
501 $value = '/'.join('/', $action_ns, $value);
503 $value = '/'.$value; # special case namespace '' (root)
510 return Chained => $value;
513 sub _parse_ChainedParent_attr {
514 my ($self, $c, $name, $value) = @_;
515 return $self->_parse_Chained_attr($c, $name, '../'.$name);
518 sub _parse_PathPrefix_attr {
519 my ( $self, $c ) = @_;
520 return PathPart => $self->path_prefix($c);
523 sub _parse_ActionClass_attr {
524 my ( $self, $c, $name, $value ) = @_;
525 my $appname = $self->_application;
526 $value = Catalyst::Utils::resolve_namespace($appname . '::Action', $self->_action_class, $value);
527 return ( 'ActionClass', $value );
530 sub _parse_MyAction_attr {
531 my ( $self, $c, $name, $value ) = @_;
533 my $appclass = Catalyst::Utils::class2appclass($self);
534 $value = "+${appclass}::Action::${value}";
536 return ( 'ActionClass', $value );
539 sub _parse_Does_attr {
540 my ($self, $app, $name, $value) = @_;
541 return Does => $self->_expand_role_shortname($value);
544 sub _parse_GET_attr { Method => 'GET' }
545 sub _parse_POST_attr { Method => 'POST' }
546 sub _parse_PUT_attr { Method => 'PUT' }
547 sub _parse_DELETE_attr { Method => 'DELETE' }
548 sub _parse_OPTION_attr { Method => 'OPTION' }
549 sub _parse_HEAD_attr { Method => 'HEAD' }
551 sub _expand_role_shortname {
552 my ($self, @shortnames) = @_;
553 my $app = $self->_application;
555 my $prefix = $self->can('_action_role_prefix') ? $self->_action_role_prefix : ['Catalyst::ActionRole::'];
556 my @prefixes = (qq{${app}::ActionRole::}, @$prefix);
558 return String::RewritePrefix->rewrite(
560 my $loaded = load_first_existing_class(
561 map { "$_$_[0]" } @prefixes
563 return first { $loaded =~ /^$_/ }
564 sort { length $b <=> length $a } @prefixes;
572 __PACKAGE__->meta->make_immutable;
580 Like any other L<Catalyst::Component>, controllers have a config hash,
581 accessible through $self->config from the controller actions. Some
582 settings are in use by the Catalyst framework:
586 This specifies the internal namespace the controller should be bound
587 to. By default the controller is bound to the URI version of the
588 controller name. For instance controller 'MyApp::Controller::Foo::Bar'
589 will be bound to 'foo/bar'. The default Root controller is an example
590 of setting namespace to '' (the null string).
594 Sets 'path_prefix', as described below.
598 Allows you to set the attributes that the dispatcher creates actions out of.
599 This allows you to do 'rails style routes', or override some of the
600 attribute definitions of actions composed from Roles.
601 You can set arguments globally (for all actions of the controller) and
602 specifically (for a single action).
606 '*' => { Chained => 'base', Args => 0 },
607 base => { Chained => '/', PathPart => '', CaptureArgs => 0 },
611 In the case above every sub in the package would be made into a Chain
612 endpoint with a URI the same as the sub name for each sub, chained
613 to the sub named C<base>. Ergo dispatch to C</example> would call the
614 C<base> method, then the C<example> method.
618 Allows you to set constructor arguments on your actions. You can set arguments
619 globally and specifically (as above).
620 This is particularly useful when using C<ActionRole>s
621 (L<Catalyst::Controller::ActionRole>) and custom C<ActionClass>es.
625 '*' => { globalarg1 => 'hello', globalarg2 => 'goodbye' },
626 'specific_action' => { customarg => 'arg1' },
630 In the case above the action class associated with C<specific_action> would get
631 passed the following arguments, in addition to the normal action constructor
632 arguments, when it is instantiated:
634 (globalarg1 => 'hello', globalarg2 => 'goodbye', customarg => 'arg1')
638 =head2 BUILDARGS ($app, @args)
640 From L<Catalyst::Component::ApplicationAttribute>, stashes the application
641 instance as $self->_application.
643 =head2 $self->action_for('name')
645 Returns the Catalyst::Action object (if any) for a given method name
648 =head2 $self->action_namespace($c)
650 Returns the private namespace for actions in this component. Defaults
651 to a value from the controller name (for
652 e.g. MyApp::Controller::Foo::Bar becomes "foo/bar") or can be
653 overridden from the "namespace" config key.
656 =head2 $self->path_prefix($c)
658 Returns the default path prefix for :PathPrefix, :Local and
659 relative :Path actions in this component. Defaults to the action_namespace or
660 can be overridden from the "path" config key.
662 =head2 $self->register_actions($c)
664 Finds all applicable actions for this component, creates
665 Catalyst::Action objects (using $self->create_action) for them and
666 registers them with $c->dispatcher.
668 =head2 $self->get_action_methods()
670 Returns a list of L<Moose::Meta::Method> objects, doing the
671 L<MooseX::MethodAttributes::Role::Meta::Method> role, which are the set of
672 action methods for this package.
674 =head2 $self->register_action_methods($c, @methods)
676 Creates action objects for a set of action methods using C< create_action >,
677 and registers them with the dispatcher.
679 =head2 $self->action_class(%args)
681 Used when a controller is creating an action to determine the correct base
684 =head2 $self->create_action(%args)
686 Called with a hash of data to be use for construction of a new
687 Catalyst::Action (or appropriate sub/alternative class) object.
689 =head2 $self->gather_action_roles(\%action_args)
691 Gathers the list of roles to apply to an action with the given %action_args.
693 =head2 $self->gather_default_action_roles(\%action_args)
695 returns a list of action roles to be applied based on core, builtin rules.
696 Currently only the L<Catalyst::ActionRole::HTTPMethods> role is applied
699 =head2 $self->_application
703 Returns the application instance stored by C<new()>
705 =head1 ACTION SUBROUTINE ATTRIBUTES
707 Please see L<Catalyst::Manual::Intro> for more details
709 Think of action attributes as a sort of way to record metadata about an action,
710 similar to how annotations work in other languages you might have heard of.
711 Generally L<Catalyst> uses these to influence how the dispatcher sees your
712 action and when it will run it in response to an incoming request. They can
713 also be used for other things. Here's a summary, but you should refer to the
714 linked manual page for additional help.
718 sub homepage :Global { ... }
720 A global action defined in any controller always runs relative to your root.
721 So the above is the same as:
723 sub myaction :Path("/homepage") { ... }
727 Status: Deprecated alias to L</Global>.
731 Alias to "Path("$action_name"). The following two actions are the same:
733 sub myaction :Local { ... }
734 sub myaction :Path('myaction') { ... }
738 Status: Deprecated alias to L</Local>
742 Handle various types of paths:
744 package MyApp::Controller::Baz {
748 sub myaction1 :Path { ... } # -> /baz
749 sub myaction2 :Path('foo') { ... } # -> /baz/foo
750 sub myaction2 :Path('/bar') { ... } # -> /bar
753 This is a general toolbox for attaching your action to a given path.
760 B<Status: Deprecated.> Use Chained methods or other techniques.
761 If you really depend on this, install the standalone
762 L<Catalyst::DispatchType::Regex> distribution.
764 A global way to match a give regular expression in the incoming request path.
770 B<Status: Deprecated.> Use Chained methods or other techniques.
771 If you really depend on this, install the standalone
772 L<Catalyst::DispatchType::Regex> distribution.
774 Like L</Regex> but scoped under the namespace of the containing controller
786 Please see L<Catalyst::DispatchType::Chained>
790 Set the base class for the action, defaults to L</Catalyst::Action>. It is now
791 preferred to use L</Does>.
795 Set the ActionClass using a custom Action in your project namespace.
797 The following is exactly the same:
799 sub foo_action1 : Local ActionClass('+MyApp::Action::Bar') { ... }
800 sub foo_action2 : Local MyAction('Bar') { ... }
804 package MyApp::Controller::Zoo;
806 sub foo : Local Does('Moo') { ... } # Catalyst::ActionRole::
807 sub bar : Local Does('~Moo') { ... } # MyApp::ActionRole::Moo
808 sub baz : Local Does('+MyApp::ActionRole::Moo') { ... }
826 Sets the give action path to match the specified HTTP method, or via one of the
827 broadly accepted methods of overriding the 'true' method (see
828 L<Catalyst::ActionRole::HTTPMethods>).
832 When used with L</Path> indicates the number of arguments expected in
833 the path. However if no Args value is set, assumed to 'slurp' all
834 remaining path pars under this namespace.
836 =head2 Consumes('...')
838 Matches the current action against the content-type of the request. Typically
839 this is used when the request is a POST or PUT and you want to restrict the
840 submitted content type. For example, you might have an HTML for that either
841 returns classic url encoded form data, or JSON when Javascript is enabled. In
842 this case you may wish to match either incoming type to one of two different
843 actions, for properly processing.
847 sub is_json : Chained('start') Consumes('application/json') { ... }
848 sub is_urlencoded : Chained('start') Consumes('application/x-www-form-urlencoded') { ... }
849 sub is_multipart : Chained('start') Consumes('multipart/form-data') { ... }
851 To reduce boilerplate, we include the following content type shortcuts:
855 sub is_json : Chained('start') Consume(JSON) { ... }
856 sub is_urlencoded : Chained('start') Consumes(UrlEncoded) { ... }
857 sub is_multipart : Chained('start') Consumes(Multipart) { ... }
859 You may specify more than one match:
863 : Consumes('application/x-www-form-urlencoded')
864 : Consumes('multipart/form-data')
868 : Consumes(UrlEncoded)
869 : Consumes(Multipart)
871 Since it is a common case the shortcut C<HTMLForm> matches both
872 'application/x-www-form-urlencoded' and 'multipart/form-data'. Here's the full
873 list of available shortcuts:
875 JSON => 'application/json',
876 JS => 'application/javascript',
877 PERL => 'application/perl',
880 Plain => 'text/plain',
881 UrlEncoded => 'application/x-www-form-urlencoded',
882 Multipart => 'multipart/form-data',
883 HTMLForm => ['application/x-www-form-urlencoded','multipart/form-data'],
885 Please keep in mind that when dispatching, L<Catalyst> will match the first most
886 relevant case, so if you use the C<Consumes> attribute, you should place your
887 most accurate matches early in the Chain, and your 'catchall' actions last.
889 See L<Catalyst::ActionRole::ConsumesContent> for more.
891 =head1 OPTIONAL METHODS
893 =head2 _parse_[$name]_attr
895 Allows you to customize parsing of subroutine attributes.
897 sub myaction1 :Path TwoArgs { ... }
899 sub _parse_TwoArgs_attr {
900 my ( $self, $c, $name, $value ) = @_;
901 # $self -> controller instance
906 Please note that this feature does not let you actually assign new functions
907 to actions via subroutine attributes, but is really more for creating useful
908 aliases to existing core and extended attributes, and transforms based on
909 existing information (like from configuration). Code for actually doing
910 something meaningful with the subroutine attributes will be located in the
911 L<Catalyst::Action> classes (or your subclasses), L<Catalyst::Dispatcher> and
912 in subclasses of L<Catalyst::DispatchType>. Remember these methods only get
913 called basically once when the application is starting, not per request!
917 Catalyst Contributors, see Catalyst.pm
921 This library is free software. You can redistribute it and/or modify
922 it under the same terms as Perl itself.