X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FIOC%2FContainer.pm;h=d3d67e298e4b7ad22b6e6de52a4cff785f8bc0ba;hb=5faa454d2d70f44f01c0cd5cab9861768d303225;hp=fc4109893179b7bf31926571d8532d81ec8d5466;hpb=1b5451ef09edf0638b6932d697f43b5dd8ede6d8;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/IOC/Container.pm b/lib/Catalyst/IOC/Container.pm index fc41098..d3d67e2 100644 --- a/lib/Catalyst/IOC/Container.pm +++ b/lib/Catalyst/IOC/Container.pm @@ -8,6 +8,7 @@ use Devel::InnerPackage (); use Hash::Util qw/lock_hash/; use MooseX::Types::LoadableClass qw/ LoadableClass /; use Moose::Util; +use Catalyst::IOC::BlockInjection; use Catalyst::IOC::ConstructorInjection; use Module::Pluggable::Object (); use namespace::autoclean; @@ -39,9 +40,9 @@ has substitutions => ( ); has application_name => ( - is => 'ro', - isa => 'Str', - default => 'MyApp', + is => 'ro', + isa => 'Str', + required => 1, ); has sub_container_class => ( @@ -82,6 +83,10 @@ sub BUILD { my $config = $self->resolve( service => 'config' ); $self->add_sub_container( + $self->build_component_subcontainer + ); + + $self->add_sub_container( $self->build_controller_subcontainer ); @@ -122,6 +127,14 @@ sub build_controller_subcontainer { ); } +sub build_component_subcontainer { + my $self = shift; + + return Bread::Board::Container->new( + name => 'component', + ); +} + sub build_application_name_service { my $self = shift; @@ -542,12 +555,12 @@ sub get_component_from_sub_container { } sub find_component { - my ( $self, $component, $c, @args ) = @_; + my ( $self, $component, @args ) = @_; my ( $type, $name ) = _get_component_type_name($component); my @result; return $self->get_component_from_sub_container( - $type, $name, $c, @args + $type, $name, @args ) if $type; my $query = ref $component @@ -560,14 +573,13 @@ sub find_component { my @components = $subcontainer->get_service_list; @result = grep { m{$component} } @components; - return map { $subcontainer->get_component( $_, $c, @args ) } @result + return map { $subcontainer->get_component( $_, @args ) } @result if @result; } - # FIXME - I guess I shouldn't be calling $c->components here # one last search for things like $c->comp(qr/::M::/) @result = $self->find_component_regexp( - $c->components, $component, $c, @args + $component, @args ) if !@result and ref $component; # it expects an empty list on failed searches @@ -575,10 +587,10 @@ sub find_component { } sub find_component_regexp { - my ( $self, $components, $component, @args ) = @_; + my ( $self, $component, @args ) = @_; my @result; - my @components = grep { m{$component} } keys %{ $components }; + my @components = grep { m{$component} } keys %{ $self->get_all_components }; for (@components) { my ($type, $name) = _get_component_type_name($_); @@ -614,18 +626,14 @@ sub get_all_components { my $self = shift; my %components; - my $containers = { - map { $_ => $self->get_sub_container($_) } qw(model view controller) - }; + my $container = $self->get_sub_container('component'); - for my $container (keys %$containers) { - for my $component ($containers->{$container}->get_service_list) { - my $comp = $containers->{$container}->resolve( - service => $component - ); - my $comp_name = ref $comp || $comp; - $components{$comp_name} = $comp; - } + for my $component ($container->get_service_list) { + my $comp = $container->resolve( + service => $component + ); + my $comp_name = ref $comp || $comp; + $components{$comp_name} = $comp; } return lock_hash %components; @@ -637,27 +645,40 @@ sub add_component { return unless $type; - $self->get_sub_container($type)->add_service( + my $component_service_name = "${type}_${name}"; + + # The 'component' sub-container will create the object, and store it's + # instance, which, by default, will live throughout the application. + # The model/view/controller sub-containers only reference the instance + # held in the aforementioned sub-container, and execute the ACCEPT_CONTEXT + # sub every time they are called, when it exists. + my $instance_container = $self->get_sub_container('component'); + my $accept_context_container = $self->get_sub_container($type); + + $instance_container->add_service( Catalyst::IOC::ConstructorInjection->new( - name => $name, + name => $component_service_name, class => $component, + lifecycle => 'Singleton', dependencies => [ depends_on( '/application_name' ), depends_on( '/config' ), ], - parameters => { - suffix => { - isa => 'Str', - default => Catalyst::Utils::class2classsuffix( $component ), - }, - accept_context_args => { - isa => 'ArrayRef|Undef', - required => 0, - default => undef, - }, - }, ) - ); + ) unless $instance_container->has_service( $component_service_name ); + # ^ custom containers might have added the service already. + # we don't want to override that. + + $accept_context_container->add_service( + Catalyst::IOC::BlockInjection->new( + name => $name, + dependencies => [ + depends_on( "/component/$component_service_name" ), + ], + block => sub { shift->param($component_service_name) }, + ) + ) unless $accept_context_container->has_service( $name ); + # ^ same as above } # FIXME: should this sub exist? @@ -705,17 +726,27 @@ Catalyst::Container - IOC for Catalyst components =head1 Building Containers +=head2 build_component_subcontainer + +Container that stores all components, i.e. all models, views and controllers +together. Each service is an instance of the actual component, and by default +it lives while the application is running. Retrieving components from this +subcontainer will instantiate the component, if it hasn't been instantiated +already, but will not execute ACCEPT_CONTEXT. + =head2 build_model_subcontainer -Container that stores all models. +Container that stores references for all models that are inside the components +subcontainer. Retrieving a model triggers ACCEPT_CONTEXT, if it exists. =head2 build_view_subcontainer -Container that stores all views. +Same as L, but for views. =head2 build_controller_subcontainer -Container that stores all controllers. +Same as L, but for controllers. The difference is +that there is no ACCEPT_CONTEXT for controllers. =head1 Building Services @@ -751,12 +782,14 @@ C<__DATA__> as a config value, for example) The parameter list is split on comma (C<,>). You can override this method to do your own string munging, or you can define your own macros in -Cconfig-E{ 'Plugin::ConfigLoader' }-E{ substitutions }>. +C<< config( 'Plugin::ConfigLoader' => { substitutions => { ... } } ) >>. Example: - MyApp->config->{ 'Plugin::ConfigLoader' }->{ substitutions } = { - baz => sub { my $c = shift; qux( @_ ); } - } + MyApp->config( 'Plugin::ConfigLoader' => { + substitutions => { + baz => sub { my $c = shift; qux( @_ ); }, + }, + }); The above will respond to C<__baz(x,y)__> in config strings.