1 package Catalyst::Controller;
4 use base qw/Catalyst::Component Catalyst::AttrContainer Class::Accessor::Fast/;
6 use Catalyst::Exception;
13 Catalyst::Controller - Catalyst Controller base class
17 package MyApp::Controller::Search
18 use base qw/Catalyst::Controller/;
21 my ($self,$c,@args) = @_;
23 } # Dispatches to /search/foo
27 Controllers are where the actions in the Catalyst framework
28 reside. Each action is represented by a function with an attribute to
29 identify what kind of action it is. See the L<Catalyst::Dispatcher>
30 for more info about how Catalyst dispatches to actions.
34 __PACKAGE__->mk_classdata($_) for qw/_dispatch_steps _action_class/;
36 __PACKAGE__->_dispatch_steps( [qw/_BEGIN _AUTO _ACTION/] );
37 __PACKAGE__->_action_class('Catalyst::Action');
39 __PACKAGE__->mk_accessors( qw/_application/ );
42 *_app = *_application;
44 sub _DISPATCH : Private {
45 my ( $self, $c ) = @_;
47 foreach my $disp ( @{ $self->_dispatch_steps } ) {
48 last unless $c->forward($disp);
54 sub _BEGIN : Private {
55 my ( $self, $c ) = @_;
56 my $begin = ( $c->get_actions( 'begin', $c->namespace ) )[-1];
57 return 1 unless $begin;
58 $begin->dispatch( $c );
59 return !@{ $c->error };
63 my ( $self, $c ) = @_;
64 my @auto = $c->get_actions( 'auto', $c->namespace );
65 foreach my $auto (@auto) {
66 $auto->dispatch( $c );
67 return 0 unless $c->state;
72 sub _ACTION : Private {
73 my ( $self, $c ) = @_;
75 && $c->action->can('execute')
76 && defined $c->req->action )
78 $c->action->dispatch( $c );
80 return !@{ $c->error };
84 my ( $self, $c ) = @_;
85 my $end = ( $c->get_actions( 'end', $c->namespace ) )[-1];
88 return !@{ $c->error };
94 my $new = $self->NEXT::new(@_);
95 $new->_application( $app );
101 my ( $self, $name ) = @_;
102 my $app = ($self->isa('Catalyst') ? $self : $self->_application);
103 return $app->dispatcher->get_action($name, $self->action_namespace);
106 sub action_namespace {
107 my ( $self, $c ) = @_;
109 $c = ($self->isa('Catalyst') ? $self : $self->_application);
111 my $hash = (ref $self ? $self : $self->config); # hate app-is-class
112 return $hash->{namespace} if exists $hash->{namespace};
113 return Catalyst::Utils::class2prefix( ref($self) || $self,
114 $c->config->{case_sensitive} )
119 my ( $self, $c ) = @_;
121 $c = ($self->isa('Catalyst') ? $self : $self->_application);
123 my $hash = (ref $self ? $self : $self->config); # hate app-is-class
124 return $hash->{path} if exists $hash->{path};
125 return shift->action_namespace(@_);
129 sub register_actions {
130 my ( $self, $c ) = @_;
131 my $class = ref $self || $self;
132 my $namespace = $self->action_namespace($c);
134 $methods{ $self->can($_) } = $_
135 for @{ Class::Inspector->methods($class) || [] };
137 # Advanced inheritance support for plugins and the like
141 for my $isa ( @{"$class\::ISA"}, $class ) {
142 push @action_cache, @{ $isa->_action_cache }
143 if $isa->can('_action_cache');
147 foreach my $cache (@action_cache) {
148 my $code = $cache->[0];
149 my $method = delete $methods{$code}; # avoid dupe registers
151 my $attrs = $self->_parse_attrs( $c, $method, @{ $cache->[1] } );
152 if ( $attrs->{Private} && ( keys %$attrs > 1 ) ) {
153 $c->log->debug( 'Bad action definition "'
154 . join( ' ', @{ $cache->[1] } )
155 . qq/" for "$class->$method"/ )
159 my $reverse = $namespace ? "$namespace/$method" : $method;
160 my $action = $self->create_action(
164 namespace => $namespace,
166 attributes => $attrs,
169 $c->dispatcher->register( $c, $action );
177 my $class = (exists $args{attributes}{ActionClass}
178 ? $args{attributes}{ActionClass}[0]
179 : $self->_action_class);
181 unless ( Class::Inspector->loaded($class) ) {
182 require Class::Inspector->filename($class);
185 return $class->new( \%args );
189 my ( $self, $c, $name, @attrs ) = @_;
193 foreach my $attr (@attrs) {
195 # Parse out :Foo(bar) into Foo => bar etc (and arrayify)
197 if ( my ( $key, $value ) = ( $attr =~ /^(.*?)(?:\(\s*(.+?)\s*\))?$/ ) )
200 if ( defined $value ) {
201 ( $value =~ s/^'(.*)'$/$1/ ) || ( $value =~ s/^"(.*)"/$1/ );
203 push( @{ $raw_attributes{$key} }, $value );
207 my $hash = (ref $self ? $self : $self->config); # hate app-is-class
209 if (exists $hash->{actions} || exists $hash->{action}) {
210 my $a = $hash->{actions} || $hash->{action};
211 %raw_attributes = ((exists $a->{'*'} ? %{$a->{'*'}} : ()),
213 (exists $a->{$name} ? %{$a->{$name}} : ()));
216 my %final_attributes;
218 foreach my $key (keys %raw_attributes) {
220 my $raw = $raw_attributes{$key};
222 foreach my $value (ref($raw) eq 'ARRAY' ? @$raw : $raw) {
224 my $meth = "_parse_${key}_attr";
225 if ( $self->can($meth) ) {
226 ( $key, $value ) = $self->$meth( $c, $name, $value );
228 push( @{ $final_attributes{$key} }, $value );
232 return \%final_attributes;
235 sub _parse_Global_attr {
236 my ( $self, $c, $name, $value ) = @_;
237 return $self->_parse_Path_attr( $c, $name, "/$name" );
240 sub _parse_Absolute_attr { shift->_parse_Global_attr(@_); }
242 sub _parse_Local_attr {
243 my ( $self, $c, $name, $value ) = @_;
244 return $self->_parse_Path_attr( $c, $name, $name );
247 sub _parse_Relative_attr { shift->_parse_Local_attr(@_); }
249 sub _parse_Path_attr {
250 my ( $self, $c, $name, $value ) = @_;
251 $value = '' if !defined $value;
252 if ( $value =~ m!^/! ) {
253 return ( 'Path', $value );
255 elsif ( length $value ) {
256 return ( 'Path', join( '/', $self->path_prefix($c), $value ) );
259 return ( 'Path', $self->path_prefix($c) );
263 sub _parse_Regex_attr {
264 my ( $self, $c, $name, $value ) = @_;
265 return ( 'Regex', $value );
268 sub _parse_Regexp_attr { shift->_parse_Regex_attr(@_); }
270 sub _parse_LocalRegex_attr {
271 my ( $self, $c, $name, $value ) = @_;
272 unless ( $value =~ s/^\^// ) { $value = "(?:.*?)$value"; }
274 my $prefix = $self->path_prefix( $c );
275 $prefix .= '/' if length( $prefix );
277 return ( 'Regex', "^${prefix}${value}" );
280 sub _parse_LocalRegexp_attr { shift->_parse_LocalRegex_attr(@_); }
282 sub _parse_Chained_attr {
283 my ($self, $c, $name, $value) = @_;
285 if (defined($value) && length($value)) {
287 $value = '/'.$self->action_namespace($c);
288 } elsif (my ($rel, $rest) = $value =~ /^((?:\.{2}\/)+)(.*)$/) {
289 my @parts = split '/', $self->action_namespace($c);
290 my @levels = split '/', $rel;
292 $value = '/'.join('/', @parts[0 .. $#parts - @levels], $rest);
293 } elsif ($value !~ m/^\//) {
294 my $action_ns = $self->action_namespace($c);
297 $value = '/'.join('/', $action_ns, $value);
299 $value = '/'.$value; # special case namespace '' (root)
306 return Chained => $value;
309 sub _parse_ChainedParent_attr {
310 my ($self, $c, $name, $value) = @_;
311 return $self->_parse_Chained_attr($c, $name, '../'.$name);
314 sub _parse_PathPrefix_attr {
316 return PathPart => $self->path_prefix;
319 sub _parse_ActionClass_attr {
320 my ( $self, $c, $name, $value ) = @_;
321 unless ( $value =~ s/^\+// ) {
322 $value = join('::', $self->_action_class, $value );
324 return ( 'ActionClass', $value );
327 sub _parse_MyAction_attr {
328 my ( $self, $c, $name, $value ) = @_;
330 my $appclass = Catalyst::Utils::class2appclass($self);
331 $value = "${appclass}::Action::${value}";
333 return ( 'ActionClass', $value );
342 Like any other L<Catalyst::Component>, controllers have a config hash,
343 accessible through $self->config from the controller actions. Some
344 settings are in use by the Catalyst framework:
348 This specifies the internal namespace the controller should be bound
349 to. By default the controller is bound to the URI version of the
350 controller name. For instance controller 'MyApp::Controller::Foo::Bar'
351 will be bound to 'foo/bar'. The default Root controller is an example
352 of setting namespace to '' (the null string).
356 Sets 'path_prefix', as described below.
360 =head2 $class->new($app, @args)
362 Proxies through to NEXT::new and stashes the application instance as
365 =head2 $self->action_for('name')
367 Returns the Catalyst::Action object (if any) for a given method name
370 =head2 $self->register_actions($c)
372 Finds all applicable actions for this component, creates
373 Catalyst::Action objects (using $self->create_action) for them and
374 registers them with $c->dispatcher.
376 =head2 $self->action_namespace($c)
378 Returns the private namespace for actions in this component. Defaults
379 to a value from the controller name (for
380 e.g. MyApp::Controller::Foo::Bar becomes "foo/bar") or can be
381 overridden from the "namespace" config key.
384 =head2 $self->path_prefix($c)
386 Returns the default path prefix for :PathPrefix, :Local, :LocalRegex and
387 relative :Path actions in this component. Defaults to the action_namespace or
388 can be overridden from the "path" config key.
390 =head2 $self->create_action(%args)
392 Called with a hash of data to be use for construction of a new
393 Catalyst::Action (or appropriate sub/alternative class) object.
395 Primarily designed for the use of register_actions.
397 =head2 $self->_application
401 Returns the application instance stored by C<new()>
405 Catalyst Contributors, see Catalyst.pm
409 This program is free software, you can redistribute it and/or modify
410 it under the same terms as Perl itself.