Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / Catalyst / Controller / ActionRole.pm
CommitLineData
3fea05b9 1package Catalyst::Controller::ActionRole;
2BEGIN {
3 $Catalyst::Controller::ActionRole::VERSION = '0.14';
4}
5# ABSTRACT: Apply roles to action instances
6
7use Moose;
8use Class::MOP;
9use Catalyst::Utils;
10use Moose::Meta::Class;
11use String::RewritePrefix;
12use MooseX::Types::Moose qw/ArrayRef Str RoleName/;
13use List::Util qw(first);
14
15use namespace::clean -except => 'meta';
16
17extends 'Catalyst::Controller';
18
19
20__PACKAGE__->mk_classdata(qw/_action_role_prefix/);
21__PACKAGE__->_action_role_prefix([ 'Catalyst::ActionRole::' ]);
22
23
24has _action_role_args => (
25 traits => [qw(Array)],
26 isa => ArrayRef[Str],
27 init_arg => 'action_roles',
28 default => sub { [] },
29 handles => {
30 _action_role_args => 'elements',
31 },
32);
33
34has _action_roles => (
35 traits => [qw(Array)],
36 isa => ArrayRef[RoleName],
37 init_arg => undef,
38 lazy_build => 1,
39 handles => {
40 _action_roles => 'elements',
41 },
42);
43
44sub _build__action_roles {
45 my $self = shift;
46 my @roles = $self->_expand_role_shortname($self->_action_role_args);
47 Class::MOP::load_class($_) for @roles;
48 return \@roles;
49}
50
51sub BUILD {
52 my $self = shift;
53 # force this to run at object creation time
54 $self->_action_roles;
55}
56
57sub create_action {
58 my ($self, %args) = @_;
59
60 my $class = exists $args{attributes}->{ActionClass}
61 ? $args{attributes}->{ActionClass}->[0]
62 : $self->_action_class;
63
64 Class::MOP::load_class($class);
65
66 my @roles = ($self->_action_roles, @{ $args{attributes}->{Does} || [] });
67 if (@roles) {
68 Class::MOP::load_class($_) for @roles;
69 my $meta = Moose::Meta::Class->initialize($class)->create_anon_class(
70 superclasses => [$class],
71 roles => \@roles,
72 cache => 1,
73 );
74 $meta->add_method(meta => sub { $meta });
75 $class = $meta->name;
76 }
77
78 return $class->new(\%args);
79}
80
81sub _expand_role_shortname {
82 my ($self, @shortnames) = @_;
83 my $app = $self->_application;
84
85 my $prefix = $self->can('_action_role_prefix') ? $self->_action_role_prefix : ['Catalyst::ActionRole::'];
86 my @prefixes = (qq{${app}::ActionRole::}, @$prefix);
87
88 return String::RewritePrefix->rewrite(
89 { '' => sub {
90 my $loaded = Class::MOP::load_first_existing_class(
91 map { "$_$_[0]" } @prefixes
92 );
93 return first { $loaded =~ /^$_/ }
94 sort { length $b <=> length $a } @prefixes;
95 },
96 '~' => $prefixes[0],
97 '+' => '' },
98 @shortnames,
99 );
100}
101
102sub _parse_Does_attr {
103 my ($self, $app, $name, $value) = @_;
104 return Does => $self->_expand_role_shortname($value);
105}
106
107
1081;
109
110__END__
111=pod
112
113=head1 NAME
114
115Catalyst::Controller::ActionRole - Apply roles to action instances
116
117=head1 VERSION
118
119version 0.14
120
121=head1 SYNOPSIS
122
123 package MyApp::Controller::Foo;
124
125 use parent qw/Catalyst::Controller::ActionRole/;
126
127 sub bar : Local Does('Moo') { ... }
128
129=head1 DESCRIPTION
130
131This module allows to apply roles to the C<Catalyst::Action>s for different
132controller methods.
133
134For that a C<Does> attribute is provided. That attribute takes an argument,
135that determines the role, which is going to be applied. If that argument is
136prefixed with C<+>, it is assumed to be the full name of the role. If it's
137prefixed with C<~>, the name of your application followed by
138C<::ActionRole::> is prepended. If it isn't prefixed with C<+> or C<~>,
139the role name will be searched for in C<@INC> according to the rules for
140L<role prefix searching|/ROLE PREFIX SEARCHING>.
141
142Additionally it's possible to to apply roles to B<all> actions of a controller
143without specifying the C<Does> keyword in every action definition:
144
145 package MyApp::Controller::Bar
146
147 use parent qw/Catalyst::Controller::ActionRole/;
148
149 __PACKAGE__->config(
150 action_roles => ['Foo', '~Bar'],
151 );
152
153 # has Catalyst::ActionRole::Foo and MyApp::ActionRole::Bar applied
154 # if MyApp::ActionRole::Foo exists and is loadable, it will take
155 # precedence over Catalyst::ActionRole::Foo
156 sub moo : Local { ... }
157
158=head1 ATTRIBUTES
159
160=head2 _action_role_prefix
161
162This class attribute stores an array reference of role prefixes to search for
163role names in if they aren't prefixed with C<+> or C<~>. It defaults to
164C<[ 'Catalyst::ActionRole::' ]>. See L</role prefix searching>.
165
166=head2 _action_roles
167
168This attribute stores an array reference of role names that will be applied to
169every action of this controller. It can be set by passing a C<action_roles>
170argument to the constructor. The same expansions as for C<Does> will be
171performed.
172
173=head1 ROLE PREFIX SEARCHING
174
175Roles specified with no prefix are looked up under a set of role prefixes. The
176first prefix is always C<MyApp::ActionRole::> (with C<MyApp> replaced as
177appropriate for your application); the following prefixes are taken from the
178C<_action_role_prefix> attribute.
179
180=for Pod::Coverage BUILD
181
182=head1 AUTHORS
183
184 Florian Ragwitz <rafl@debian.org>
185 Hans Dieter Pearcey <hdp@weftsoar.net>
186
187=head1 COPYRIGHT AND LICENSE
188
189This software is copyright (c) 2010 by Florian Ragwitz.
190
191This is free software; you can redistribute it and/or modify it under
192the same terms as the Perl 5 programming language system itself.
193
194=cut
195