package Catalyst::IOC::Container;
-use Bread::Board;
+use Bread::Board qw/depends_on/;
use Moose;
use Config::Any;
use Data::Visitor::Callback;
default => sub { +{} },
);
-has application_name => (
- is => 'ro',
- isa => 'Str',
- required => 1,
-);
-
has sub_container_class => (
isa => LoadableClass,
is => 'ro',
substitutions
file
driver
- application_name
+ catalyst_application
prefix
extensions
path
config_local_suffix
config_path
locate_components
+ home
+ root_dir
/;
my $config = $self->resolve( service => 'config' );
lifecycle => 'Singleton',
name => 'home',
block => sub {
- my $self = shift;
- my $class = $self->param('application_name');
- my $home;
+ my $self = shift;
+ my $class = $self->param('catalyst_application');
if ( my $env = Catalyst::Utils::env_value( $class, 'HOME' ) ) {
- $home = $env;
+ return $env;
}
- $home ||= Catalyst::Utils::home($class);
- $class->config(home => $home); # FIXME - Needed to make path_to work.
- return $home;
+ if ( my $home = $self->param('home_flag') ) {
+ return $home;
+ }
+
+ return Catalyst::Utils::home($class);
+ },
+ parameters => {
+ home_flag => { is => 'ro', isa => 'Str|Undef', required => 0 }
},
- dependencies => [ depends_on('application_name') ],
+ dependencies => [ depends_on('catalyst_application') ],
);
}
-# FIXME: very ambiguous - maybe root_dir?
-sub build_root_service {
+sub build_root_dir_service {
my $self = shift;
return Bread::Board::BlockInjection->new(
lifecycle => 'Singleton',
- name => 'root',
+ name => 'root_dir',
block => sub {
my $self = shift;
);
}
-sub build_application_name_service {
+sub build_catalyst_application_service {
my $self = shift;
- return Bread::Board::Literal->new( name => 'application_name', value => $self->application_name );
+ return Bread::Board::Literal->new( name => 'catalyst_application', value => $self->name );
}
sub build_driver_service {
lifecycle => 'Singleton',
name => 'prefix',
block => sub {
- return Catalyst::Utils::appprefix( shift->param('application_name') );
+ return Catalyst::Utils::appprefix( shift->param('catalyst_application') );
},
- dependencies => [ depends_on('application_name') ],
+ dependencies => [ depends_on('catalyst_application') ],
);
}
block => sub {
my $s = shift;
- return Catalyst::Utils::env_value( $s->param('application_name'), 'CONFIG' )
+ return Catalyst::Utils::env_value( $s->param('catalyst_application'), 'CONFIG' )
|| $s->param('file')
- || $s->param('application_name')->path_to( $s->param('prefix') );
+ || $s->param('catalyst_application')->path_to( $s->param('prefix') );
},
- dependencies => [ depends_on('file'), depends_on('application_name'), depends_on('prefix') ],
+ dependencies => [ depends_on('file'), depends_on('catalyst_application'), depends_on('prefix') ],
);
}
my $v = Data::Visitor::Callback->new(
plain_value => sub {
return unless defined $_;
- return $self->_config_substitutions( $s->param('application_name'), $s->param('substitutions'), $_ );
+ return $self->_config_substitutions( $s->param('catalyst_application'), $s->param('substitutions'), $_ );
}
);
$v->visit( $s->param('raw_config') );
},
- dependencies => [ depends_on('application_name'), depends_on('raw_config'), depends_on('substitutions') ],
+ dependencies => [ depends_on('catalyst_application'), depends_on('raw_config'), depends_on('substitutions') ],
);
}
name => 'class_config',
block => sub {
my $s = shift;
- my $app = $s->param('application_name');
+ my $app = $s->param('catalyst_application');
# Container might be called outside Catalyst context
return {} unless Class::MOP::is_class_loaded($app);
# config might not have been defined
return $app->config || {};
},
- dependencies => [ depends_on('application_name') ],
+ dependencies => [ depends_on('catalyst_application') ],
);
}
name => 'config_local_suffix',
block => sub {
my $s = shift;
- my $suffix = Catalyst::Utils::env_value( $s->param('application_name'), 'CONFIG_LOCAL_SUFFIX' ) || $self->config_local_suffix;
+ my $suffix = Catalyst::Utils::env_value( $s->param('catalyst_application'), 'CONFIG_LOCAL_SUFFIX' ) || $self->config_local_suffix;
return $suffix;
},
- dependencies => [ depends_on('application_name') ],
+ dependencies => [ depends_on('catalyst_application') ],
);
}
name => 'locate_components',
block => sub {
my $s = shift;
- my $class = $s->param('application_name');
+ my $class = $s->param('catalyst_application');
my $config = $s->param('config')->{ setup_components };
Catalyst::Exception->throw(
return [ $locator->plugins ];
},
- dependencies => [ depends_on('application_name'), depends_on('config') ],
+ dependencies => [ depends_on('catalyst_application'), depends_on('config') ],
);
}
sub setup_components {
my $self = shift;
- my $class = $self->resolve( service => 'application_name' );
+ my $class = $self->resolve( service => 'catalyst_application' );
my @comps = @{ $self->resolve( service => 'locate_components' ) };
my %comps = map { $_ => 1 } @comps;
my $deprecatedcatalyst_component_names = 0;
return @result;
}
+# FIXME
+# what exactly should this method return?
+# By default, for back-compatibility, we have two services for each component:
+# - one in the model|view|controller sub-container
+# - and another in the component sub-container
+# the latter is a Singleton, it executes the COMPONENT method, and the first
+# is executed at every call, executing ACCEPT_CONTEXT. It's just a layer.
+#
+# So the one in $type sub-container is pretty useless by default. But when the
+# user overrides the container (which is what we want), the sub-container they
+# will use is precisely $type, not 'component'. So for now, I'm returning both
+# services, to decide later what to do.
+sub get_all_component_services {
+ my $self = shift;
+
+ my %components;
+ my $components_container = $self->get_sub_container('component');
+
+ foreach my $type (qw/model view controller /) {
+ my $container = $self->get_sub_container($type);
+
+ for my $component ($container->get_service_list) {
+ my $comp_service = $container->get_service($component);
+
+ my $key = $comp_service->catalyst_component_name;
+ my %values = (
+ type => $type,
+ service => $comp_service,
+ );
+
+ my $comp_name = "${type}_${component}";
+ if ($components_container->has_service($comp_name)) {
+ $values{backcompat_service} = $components_container->get_service($comp_name);
+ }
+
+ $components{$key} = \%values;
+ }
+ }
+
+ return lock_hash %components;
+}
+
+sub get_all_singleton_lifecycle_components {
+ my $self = shift;
+
+ my %components;
+ my $components_container = $self->get_sub_container('component');
+
+ foreach my $type (qw/model view controller /) {
+ my $container = $self->get_sub_container($type);
+
+ for my $component ($container->get_service_list) {
+ my $comp_service = $container->get_service($component);
+
+ my $key = $comp_service->catalyst_component_name;
+ my $lifecycle = $comp_service->lifecycle;
+ my $comp_name = "${type}_${component}";
+
+ if (defined $lifecycle && $lifecycle eq 'Singleton') {
+ $components{$key} = $comp_service->get;
+ }
+ elsif ($components_container->has_service($comp_name)) {
+ $components{$key} = $components_container->get_service($comp_name)->get;
+ }
+ }
+ }
+
+ return lock_hash %components;
+}
+
sub get_all_components {
my ($self, $class) = @_;
my %components;
class => $component,
lifecycle => 'Singleton',
dependencies => [
- depends_on( '/application_name' ),
+ depends_on( '/catalyst_application' ),
],
),
);
return Devel::InnerPackage::list_packages( $module );
}
+__PACKAGE__->meta->make_immutable;
+
1;
__END__
=head1 Methods for Building Services
-=head2 build_application_name_service
+=head2 build_catalyst_application_service
Name of the application (such as MyApp).
+=head2 build_home_service
+
+The application home directory. All the files (including classes, scripts, etc)
+created for this application are in this directory, or in a sub-directory below
+this one.
+
+=head2 build_root_dir_service
+
+Inside the application home (as explained in L</build_home_service>), there is
+a root directory. This is where all templates and static files are.
+
=head2 build_driver_service
Config options passed directly to the driver being used.