0f112a0fb07292ec028638f646f610b45c0ec582
[catagits/Catalyst-Runtime.git] / lib / Catalyst / IOC / ConstructorInjection.pm
1 package Catalyst::IOC::ConstructorInjection;
2 use Moose;
3 use Catalyst::Utils ();
4 extends 'Bread::Board::ConstructorInjection';
5
6 with 'Bread::Board::Service::WithClass',
7      'Bread::Board::Service::WithParameters',
8      'Bread::Board::Service::WithDependencies';
9
10 has config_key => (
11     is         => 'ro',
12     isa        => 'Str',
13     lazy_build => 1,
14 );
15
16 sub _build_config_key { Catalyst::Utils::class2classsuffix( shift->class ) }
17
18 sub _build_constructor_name { 'COMPONENT' }
19
20 sub get {
21     my $self = shift;
22
23     my $constructor = $self->constructor_name;
24     my $component   = $self->class;
25     my $config      = $self->param('config')->{ $self->config_key } || {};
26     # FIXME - Is depending on the application name to pass into constructors here a good idea?
27     #         This makes app/ctx split harder I think.. Need to think more here, but I think
28     #         we want to pass the application in as a parameter when building the service
29     #         rather than depending on the app name, so that later, when the app becomes an instance
30     #         then it'll get passed in, and components can stash themselves 'per app instance'
31     my $app_name    = $self->param('application_name');
32
33     # Stash catalyst_component_name in the config here, so that custom COMPONENT
34     # methods also pass it. local to avoid pointlessly shitting in config
35     # for the debug screen, as $component is already the key name.
36     local $config->{catalyst_component_name} = $component;
37
38     unless ( $component->can( $constructor ) ) {
39         # FIXME - make some deprecation warnings
40         return $component;
41     }
42
43     my $instance = eval { $component->$constructor( $app_name, $config ) };
44
45     if ( my $error = $@ ) {
46         chomp $error;
47         Catalyst::Exception->throw(
48             message => qq/Couldn't instantiate component "$component", "$error"/
49         );
50     }
51     elsif (!blessed $instance) {
52         my $metaclass = Moose::Util::find_meta($component);
53         my $method_meta = $metaclass->find_method_by_name($constructor);
54         my $component_method_from = $method_meta->associated_metaclass->name;
55         my $value = defined($instance) ? $instance : 'undef';
56         Catalyst::Exception->throw(
57             message =>
58             qq/Couldn't instantiate component "$component", $constructor() method (from $component_method_from) didn't return an object-like value (value was $value)./
59         );
60     }
61
62     return $instance;
63 }
64
65 __PACKAGE__->meta->make_immutable;
66
67 no Moose; 1;
68
69 __END__
70
71 =pod
72
73 =head1 NAME
74
75 Catalyst::IOC::ConstructorInjection
76
77 =head1 SYNOPSIS
78
79 =head1 DESCRIPTION
80
81 =head1 AUTHORS
82
83 Catalyst Contributors, see Catalyst.pm
84
85 =head1 COPYRIGHT
86
87 This library is free software. You can redistribute it and/or modify it under
88 the same terms as Perl itself.
89
90 =cut