1 package Catalyst::Container;
5 use Data::Visitor::Callback;
6 use Catalyst::Utils ();
7 use MooseX::Types::LoadableClass qw/ LoadableClass /;
8 use Catalyst::BlockInjection;
10 extends 'Bread::Board::Container';
12 has config_local_suffix => (
21 default => sub { +{} },
30 has substitutions => (
33 default => sub { +{} },
42 has sub_container_class => (
46 default => 'Catalyst::SubContainer',
51 Catalyst::Container - IOC for Catalyst components
61 $self->${\"build_${_}_service"}
80 $self->add_sub_container(
81 $self->${ \"build_${_}_subcontainer" }
82 ) for qw/ model view controller /;
85 =head2 build_model_subcontainer
89 sub build_model_subcontainer {
92 return $self->sub_container_class->new( name => 'model' );
95 =head2 build_view_subcontainer
99 sub build_view_subcontainer {
102 return $self->sub_container_class->new( name => 'view' );
105 =head2 build_controller_subcontainer
109 sub build_controller_subcontainer {
112 return $self->sub_container_class->new( name => 'controller' );
115 =head2 build_name_service
119 sub build_name_service {
122 return Bread::Board::Literal->new( name => 'name', value => $self->name );
125 =head2 build_driver_service
129 sub build_driver_service {
132 return Bread::Board::Literal->new( name => 'driver', value => $self->driver );
135 =head2 build_file_service
139 sub build_file_service {
142 return Bread::Board::Literal->new( name => 'file', value => $self->file );
145 =head2 build_substitutions_service
149 sub build_substitutions_service {
152 return Bread::Board::Literal->new( name => 'substitutions', value => $self->substitutions );
155 =head2 build_extensions_service
159 sub build_extensions_service {
162 return Bread::Board::BlockInjection->new(
163 name => 'extensions',
165 return \@{Config::Any->extensions};
170 =head2 build_prefix_service
174 sub build_prefix_service {
177 return Bread::Board::BlockInjection->new(
180 return Catalyst::Utils::appprefix( shift->param('name') );
182 dependencies => [ depends_on('name') ],
186 =head2 build_path_service
190 sub build_path_service {
193 return Bread::Board::BlockInjection->new(
198 return Catalyst::Utils::env_value( $s->param('name'), 'CONFIG' )
200 || $s->param('name')->path_to( $s->param('prefix') );
202 dependencies => [ depends_on('file'), depends_on('name'), depends_on('prefix') ],
206 =head2 build_config_service
210 sub build_config_service {
213 return Bread::Board::BlockInjection->new(
218 my $v = Data::Visitor::Callback->new(
220 return unless defined $_;
221 return $self->_config_substitutions( $s->param('name'), $s->param('substitutions'), $_ );
225 $v->visit( $s->param('raw_config') );
227 dependencies => [ depends_on('name'), depends_on('raw_config'), depends_on('substitutions') ],
231 =head2 build_raw_config_service
235 sub build_raw_config_service {
238 return Bread::Board::BlockInjection->new(
239 name => 'raw_config',
243 my @global = @{$s->param('global_config')};
244 my @locals = @{$s->param('local_config')};
247 for my $cfg (@global, @locals) {
249 $config = Catalyst::Utils::merge_hashes( $config, $cfg->{$_} );
254 dependencies => [ depends_on('global_config'), depends_on('local_config') ],
258 =head2 build_global_files_service
262 sub build_global_files_service {
265 return Bread::Board::BlockInjection->new(
266 name => 'global_files',
270 my ( $path, $extension ) = @{$s->param('config_path')};
272 my @extensions = @{$s->param('extensions')};
276 die "Unable to handle files with the extension '${extension}'" unless grep { $_ eq $extension } @extensions;
279 @files = map { "$path.$_" } @extensions;
283 dependencies => [ depends_on('extensions'), depends_on('config_path') ],
287 =head2 build_local_files_service
291 sub build_local_files_service {
294 return Bread::Board::BlockInjection->new(
295 name => 'local_files',
299 my ( $path, $extension ) = @{$s->param('config_path')};
300 my $suffix = $s->param('config_local_suffix');
302 my @extensions = @{$s->param('extensions')};
306 die "Unable to handle files with the extension '${extension}'" unless grep { $_ eq $extension } @extensions;
307 $path =~ s{\.$extension}{_$suffix.$extension};
310 @files = map { "${path}_${suffix}.$_" } @extensions;
314 dependencies => [ depends_on('extensions'), depends_on('config_path'), depends_on('config_local_suffix') ],
318 =head2 build_global_config_service
322 sub build_global_config_service {
325 return Bread::Board::BlockInjection->new(
326 name => 'global_config',
330 return Config::Any->load_files({
331 files => $s->param('global_files'),
332 filter => \&_fix_syntax,
334 driver_args => $s->param('driver'),
337 dependencies => [ depends_on('global_files') ],
341 =head2 build_local_config_service
345 sub build_local_config_service {
348 return Bread::Board::BlockInjection->new(
349 name => 'local_config',
353 return Config::Any->load_files({
354 files => $s->param('local_files'),
355 filter => \&_fix_syntax,
357 driver_args => $s->param('driver'),
360 dependencies => [ depends_on('local_files') ],
364 =head2 build_config_path_service
368 sub build_config_path_service {
371 return Bread::Board::BlockInjection->new(
372 name => 'config_path',
376 my $path = $s->param('path');
377 my $prefix = $s->param('prefix');
379 my ( $extension ) = ( $path =~ m{\.(.{1,4})$} );
382 $path =~ s{[\/\\]$}{};
386 return [ $path, $extension ];
388 dependencies => [ depends_on('prefix'), depends_on('path') ],
392 =head2 build_config_local_suffix_service
396 sub build_config_local_suffix_service {
399 return Bread::Board::BlockInjection->new(
400 name => 'config_local_suffix',
403 my $suffix = Catalyst::Utils::env_value( $s->param('name'), 'CONFIG_LOCAL_SUFFIX' ) || $self->config_local_suffix;
407 dependencies => [ depends_on('name') ],
419 prefix => $_ eq 'Component' ? '' : $_ . '::',
420 values => delete $config->{ lc $_ } || delete $config->{ $_ }
422 grep { ref $config->{ lc $_ } || ref $config->{ $_ } }
423 qw( Component Model M View V Controller C Plugin )
426 foreach my $comp ( @components ) {
427 my $prefix = $comp->{ prefix };
428 foreach my $element ( keys %{ $comp->{ values } } ) {
429 $config->{ "$prefix$element" } = $comp->{ values }->{ $element };
434 =head2 _config_substitutions
438 sub _config_substitutions {
439 my ( $self, $name, $subs, $arg ) = @_;
441 $subs->{ HOME } ||= sub { shift->path_to( '' ); };
445 if (! defined($ENV{$v})) {
446 Catalyst::Exception->throw( message =>
447 "Missing environment variable: $v" );
453 $subs->{ path_to } ||= sub { shift->path_to( @_ ); };
454 $subs->{ literal } ||= sub { return $_[ 1 ]; };
455 my $subsre = join( '|', keys %$subs );
457 $arg =~ s{__($subsre)(?:\((.+?)\))?__}{ $subs->{ $1 }->( $name, $2 ? split( /,/, $2 ) : () ) }eg;
465 =item Justin Hunter (arcanez)
467 =item André Walker (andrewalker)
471 Based on L<Catalyst::Plugin::ConfigLoader>, by Brian Cassidy.
475 This library is free software. You can redistribute it and/or modify it under
476 the same terms as Perl itself.