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