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