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