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