reverting (most of) the whitespace changes
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Component.pm
CommitLineData
158c88c0 1package Catalyst::Component;
2
a7caa492 3use Moose;
4use MooseX::Adopt::Class::Accessor::Fast;
e8b9f2a9 5use Catalyst::Utils;
5595dd2f 6
158c88c0 7
a7caa492 8with 'MooseX::Emulate::Class::Accessor::Fast';
9with 'Catalyst::ClassData';
10
11
158c88c0 12=head1 NAME
13
14Catalyst::Component - Catalyst Component Base Class
15
16=head1 SYNOPSIS
17
18 # lib/MyApp/Model/Something.pm
19 package MyApp::Model::Something;
20
e7f1cf73 21 use base 'Catalyst::Component';
158c88c0 22
23 __PACKAGE__->config( foo => 'bar' );
24
25 sub test {
26 my $self = shift;
27 return $self->{foo};
28 }
29
30 sub forward_to_me {
31 my ( $self, $c ) = @_;
32 $c->response->output( $self->{foo} );
33 }
ac5c933b 34
158c88c0 35 1;
36
37 # Methods can be a request step
38 $c->forward(qw/MyApp::Model::Something forward_to_me/);
39
40 # Or just methods
41 print $c->comp('MyApp::Model::Something')->test;
42
43 print $c->comp('MyApp::Model::Something')->{foo};
44
45=head1 DESCRIPTION
46
ac5c933b 47This is the universal base class for Catalyst components
158c88c0 48(Model/View/Controller).
49
50It provides you with a generic new() for instantiation through Catalyst's
51component loader with config() support and a process() method placeholder.
52
7cd1a42b 53=cut
158c88c0 54
e8b9f2a9 55__PACKAGE__->mk_classdata($_) for qw/_config _plugins/;
56
a7caa492 57around new => sub {
58 my $orig = shift;
158c88c0 59 my ( $self, $c ) = @_;
60
61 # Temporary fix, some components does not pass context to constructor
62 my $arguments = ( ref( $_[-1] ) eq 'HASH' ) ? $_[-1] : {};
e8b9f2a9 63
a7caa492 64 my $args = $self->merge_config_hashes( $self->config, $arguments );
65 return $self->$orig( $args );
66};
158c88c0 67
22247e54 68sub COMPONENT {
69 my ( $self, $c ) = @_;
70
71 # Temporary fix, some components does not pass context to constructor
72 my $arguments = ( ref( $_[-1] ) eq 'HASH' ) ? $_[-1] : {};
a7caa492 73 $self->new($c, $arguments);
74
75# if ( my $new = $self->NEXT::COMPONENT( $c, $arguments ) ) {
76# return $new;
77# }
78# else {
79# if ( my $new = $self->new( $c, $arguments ) ) {
80# return $new;
81# }
82# else {
83# my $class = ref $self || $self;
84# my $new = $self->merge_config_hashes(
85# $self->config, $arguments );
86# return bless $new, $class;
87# }
88# }
22247e54 89}
90
158c88c0 91sub config {
92 my $self = shift;
300633a8 93 my $config_sub = $self->can('_config');
e8b9f2a9 94 my $config = $self->$config_sub() || {};
158c88c0 95 if (@_) {
baf6a3db 96 my $newconfig = { %{@_ > 1 ? {@_} : $_[0]} };
97 $self->_config(
98 $self->merge_config_hashes( $config, $newconfig )
99 );
300633a8 100 } else {
101 # this is a bit of a kludge, required to make
102 # __PACKAGE__->config->{foo} = 'bar';
103 # work in a subclass. Calling the Class::Data::Inheritable setter
104 # will create a new _config method in the current class if it's
105 # currently inherited from the superclass. So, the can() call will
106 # return a different subref in that case and that means we know to
107 # copy and reset the value stored in the class data.
108
109 $self->_config( $config );
110
111 if ((my $config_sub_now = $self->can('_config')) ne $config_sub) {
112
113 $config = $self->merge_config_hashes( $config, {} );
114 $self->$config_sub_now( $config );
115 }
158c88c0 116 }
5e707396 117 return $config;
158c88c0 118}
119
7cd1a42b 120sub merge_config_hashes {
121 my ( $self, $lefthash, $righthash ) = @_;
158c88c0 122
7cd1a42b 123 return Catalyst::Utils::merge_hashes( $lefthash, $righthash );
124}
158c88c0 125
126sub process {
127
128 Catalyst::Exception->throw( message => ( ref $_[0] || $_[0] )
129 . " did not override Catalyst::Component::process" );
130}
131
7cd1a42b 1321;
baf6a3db 133
7cd1a42b 134__END__
baf6a3db 135
7cd1a42b 136=head1 METHODS
baf6a3db 137
7cd1a42b 138=head2 new($c, $arguments)
baf6a3db 139
7cd1a42b 140Called by COMPONENT to instantiate the component; should return an object
141to be stored in the application's component hash.
142
143=head2 COMPONENT($c, $arguments)
144
145If this method is present (as it is on all Catalyst::Component subclasses,
146it is called by Catalyst during setup_components with the application class
147as $c and any config entry on the application for this component (for example,
148in the case of MyApp::Controller::Foo this would be
ac5c933b 149MyApp->config->{'Controller::Foo'}). The arguments are expected to be a
150hashref and are merged with the __PACKAGE__->config hashref before calling
7cd1a42b 151->new to instantiate the component.
152
153=head2 $c->config
154
155=head2 $c->config($hashref)
156
157=head2 $c->config($key, $value, ...)
158
ac5c933b 159Accessor for this component's config hash. Config values can be set as
7cd1a42b 160key value pair, or you can specify a hashref. In either case the keys
ac5c933b 161will be merged with any existing config settings. Each component in
7cd1a42b 162a Catalyst application has it's own config hash.
163
164=head2 $c->process()
165
166This is the default method called on a Catalyst component in the dispatcher.
ac5c933b 167For instance, Views implement this action to render the response body
7cd1a42b 168when you forward to them. The default is an abstract method.
169
170=head2 $c->merge_config_hashes( $hashref, $hashref )
171
172Merges two hashes together recursively, giving right-hand precedence.
173Alias for the method in L<Catalyst::Utils>.
baf6a3db 174
825dbf85 175=head1 OPTIONAL METHODS
176
177=head2 ACCEPT_CONTEXT($c, @args)
178
179Catalyst components are normally initalized during server startup, either
180as a Class or a Instance. However, some components require information about
181the current request. To do so, they can implement an ACCEPT_CONTEXT method.
182
183If this method is present, it is called during $c->comp/controller/model/view
184with the current $c and any additional args (e.g. $c->model('Foo', qw/bar baz/)
185would cause your MyApp::Model::Foo instance's ACCEPT_CONTEXT to be called with
186($c, 'bar', 'baz')) and the return value of this method is returned to the
187calling code in the application rather than the component itself.
188
158c88c0 189=head1 SEE ALSO
190
e7f1cf73 191L<Catalyst>, L<Catalyst::Model>, L<Catalyst::View>, L<Catalyst::Controller>.
158c88c0 192
193=head1 AUTHOR
194
195Sebastian Riedel, C<sri@cpan.org>
196Marcus Ramberg, C<mramberg@cpan.org>
197Matt S Trout, C<mst@shadowcatsystems.co.uk>
198
199=head1 COPYRIGHT
200
201This program is free software, you can redistribute it and/or modify it under
202the same terms as Perl itself.
203
85d9fce6 204=cut