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