fix default_component behavior
[catagits/Catalyst-Runtime.git] / lib / Catalyst / IOC / Container.pm
CommitLineData
a6c13ff4 1package Catalyst::IOC::Container;
b4a6fa62 2use Bread::Board;
3use Moose;
4use Config::Any;
5use Data::Visitor::Callback;
6use Catalyst::Utils ();
d3742403 7use Devel::InnerPackage ();
b4410fc3 8use Hash::Util qw/lock_hash/;
2bb0da6d 9use MooseX::Types::LoadableClass qw/ LoadableClass /;
0dff29e2 10use Moose::Util;
ff0e9735 11use Catalyst::IOC::BlockInjection;
b7da37bd 12use Catalyst::IOC::ConstructorInjection;
2f32de9a 13use Module::Pluggable::Object ();
8b749525 14use namespace::autoclean;
b4a6fa62 15
16extends 'Bread::Board::Container';
17
18has config_local_suffix => (
442ab13e 19 is => 'ro',
b4a6fa62 20 isa => 'Str',
21 default => 'local',
22);
23
24has driver => (
442ab13e 25 is => 'ro',
b4a6fa62 26 isa => 'HashRef',
27 default => sub { +{} },
28);
29
30has file => (
442ab13e 31 is => 'ro',
b4a6fa62 32 isa => 'Str',
33 default => '',
34);
35
36has substitutions => (
442ab13e 37 is => 'ro',
b4a6fa62 38 isa => 'HashRef',
39 default => sub { +{} },
40);
41
6c743f02 42has application_name => (
55f417ad 43 is => 'ro',
44 isa => 'Str',
45 required => 1,
b4a6fa62 46);
47
2bb0da6d 48has sub_container_class => (
49 isa => LoadableClass,
50 is => 'ro',
51 coerce => 1,
a6c13ff4 52 default => 'Catalyst::IOC::SubContainer',
8b749525 53 handles => {
54 new_sub_container => 'new',
55 }
2bb0da6d 56);
57
b4a6fa62 58sub BUILD {
a2c0d071 59 my ( $self, $params ) = @_;
b4a6fa62 60
292277c1 61 $self->add_service(
62 $self->${\"build_${_}_service"}
63 ) for qw/
7451d1ea 64 substitutions
65 file
66 driver
6c743f02 67 application_name
7451d1ea 68 prefix
69 extensions
70 path
71 config
72 raw_config
73 global_files
74 local_files
75 global_config
76 local_config
0fcf9a51 77 class_config
7451d1ea 78 config_local_suffix
79 config_path
3e4f5406 80 locate_components
7451d1ea 81 /;
f04816ce 82
0fcf9a51 83 my $config = $self->resolve( service => 'config' );
84
cd20de09 85 # don't force default_component to be undef if the config wasn't set
86 my @default_view = $config->{default_view}
87 ? ( default_component => $config->{default_view} )
88 : ( )
89 ;
90 my @default_model = $config->{default_model}
91 ? ( default_component => $config->{default_model} )
92 : ( )
93 ;
94
292277c1 95 $self->add_sub_container(
ff0e9735 96 $self->build_component_subcontainer
97 );
98
99 $self->add_sub_container(
a2c0d071 100 $self->build_controller_subcontainer
101 );
102
103 $self->add_sub_container(
cd20de09 104 $self->build_view_subcontainer( @default_view )
a2c0d071 105 );
106
107 $self->add_sub_container(
cd20de09 108 $self->build_model_subcontainer( @default_model )
a2c0d071 109 );
f04816ce 110}
111
112sub build_model_subcontainer {
113 my $self = shift;
114
a2c0d071 115 return $self->new_sub_container( @_,
5a53ef3d 116 name => 'model',
b06ded69 117 );
f04816ce 118}
119
120sub build_view_subcontainer {
121 my $self = shift;
122
a2c0d071 123 return $self->new_sub_container( @_,
5a53ef3d 124 name => 'view',
b06ded69 125 );
f04816ce 126}
127
128sub build_controller_subcontainer {
129 my $self = shift;
130
b06ded69 131 return $self->new_sub_container(
5a53ef3d 132 name => 'controller',
b06ded69 133 );
f04816ce 134}
135
ff0e9735 136sub build_component_subcontainer {
137 my $self = shift;
138
139 return Bread::Board::Container->new(
140 name => 'component',
141 );
142}
143
5b47e4a9 144sub build_application_name_service {
f04816ce 145 my $self = shift;
292277c1 146
6c743f02 147 return Bread::Board::Literal->new( name => 'application_name', value => $self->application_name );
f04816ce 148}
149
150sub build_driver_service {
151 my $self = shift;
292277c1 152
153 return Bread::Board::Literal->new( name => 'driver', value => $self->driver );
f04816ce 154}
155
156sub build_file_service {
157 my $self = shift;
292277c1 158
159 return Bread::Board::Literal->new( name => 'file', value => $self->file );
f04816ce 160}
161
162sub build_substitutions_service {
163 my $self = shift;
292277c1 164
165 return Bread::Board::Literal->new( name => 'substitutions', value => $self->substitutions );
f04816ce 166}
167
168sub build_extensions_service {
169 my $self = shift;
292277c1 170
171 return Bread::Board::BlockInjection->new(
7a267bb5 172 lifecycle => 'Singleton',
292277c1 173 name => 'extensions',
174 block => sub {
175 return \@{Config::Any->extensions};
176 },
f04816ce 177 );
178}
b4a6fa62 179
f04816ce 180sub build_prefix_service {
181 my $self = shift;
292277c1 182
183 return Bread::Board::BlockInjection->new(
7a267bb5 184 lifecycle => 'Singleton',
292277c1 185 name => 'prefix',
186 block => sub {
dca40344 187 return Catalyst::Utils::appprefix( shift->param('application_name') );
292277c1 188 },
dca40344 189 dependencies => [ depends_on('application_name') ],
f04816ce 190 );
191}
b4a6fa62 192
f04816ce 193sub build_path_service {
194 my $self = shift;
292277c1 195
196 return Bread::Board::BlockInjection->new(
7a267bb5 197 lifecycle => 'Singleton',
292277c1 198 name => 'path',
199 block => sub {
200 my $s = shift;
201
dca40344 202 return Catalyst::Utils::env_value( $s->param('application_name'), 'CONFIG' )
292277c1 203 || $s->param('file')
6c743f02 204 || $s->param('application_name')->path_to( $s->param('prefix') );
292277c1 205 },
6c743f02 206 dependencies => [ depends_on('file'), depends_on('application_name'), depends_on('prefix') ],
f04816ce 207 );
208}
b4a6fa62 209
f04816ce 210sub build_config_service {
211 my $self = shift;
292277c1 212
213 return Bread::Board::BlockInjection->new(
7a267bb5 214 lifecycle => 'Singleton',
292277c1 215 name => 'config',
216 block => sub {
217 my $s = shift;
218
219 my $v = Data::Visitor::Callback->new(
220 plain_value => sub {
221 return unless defined $_;
6c743f02 222 return $self->_config_substitutions( $s->param('application_name'), $s->param('substitutions'), $_ );
292277c1 223 }
224
225 );
226 $v->visit( $s->param('raw_config') );
227 },
6c743f02 228 dependencies => [ depends_on('application_name'), depends_on('raw_config'), depends_on('substitutions') ],
f04816ce 229 );
230}
b4a6fa62 231
f04816ce 232sub build_raw_config_service {
233 my $self = shift;
292277c1 234
235 return Bread::Board::BlockInjection->new(
7a267bb5 236 lifecycle => 'Singleton',
292277c1 237 name => 'raw_config',
238 block => sub {
239 my $s = shift;
240
241 my @global = @{$s->param('global_config')};
242 my @locals = @{$s->param('local_config')};
243
0fcf9a51 244 my $config = $s->param('class_config');
245
292277c1 246 for my $cfg (@global, @locals) {
247 for (keys %$cfg) {
248 $config = Catalyst::Utils::merge_hashes( $config, $cfg->{$_} );
b4a6fa62 249 }
292277c1 250 }
0fcf9a51 251
292277c1 252 return $config;
253 },
0fcf9a51 254 dependencies => [ depends_on('global_config'), depends_on('local_config'), depends_on('class_config') ],
f04816ce 255 );
256}
b4a6fa62 257
f04816ce 258sub build_global_files_service {
259 my $self = shift;
b4a6fa62 260
292277c1 261 return Bread::Board::BlockInjection->new(
7a267bb5 262 lifecycle => 'Singleton',
292277c1 263 name => 'global_files',
264 block => sub {
265 my $s = shift;
b4a6fa62 266
292277c1 267 my ( $path, $extension ) = @{$s->param('config_path')};
b4a6fa62 268
292277c1 269 my @extensions = @{$s->param('extensions')};
270
271 my @files;
272 if ( $extension ) {
273 die "Unable to handle files with the extension '${extension}'" unless grep { $_ eq $extension } @extensions;
274 push @files, $path;
275 } else {
276 @files = map { "$path.$_" } @extensions;
277 }
278 return \@files;
279 },
280 dependencies => [ depends_on('extensions'), depends_on('config_path') ],
f04816ce 281 );
282}
b4a6fa62 283
f04816ce 284sub build_local_files_service {
285 my $self = shift;
292277c1 286
287 return Bread::Board::BlockInjection->new(
7a267bb5 288 lifecycle => 'Singleton',
292277c1 289 name => 'local_files',
290 block => sub {
291 my $s = shift;
292
293 my ( $path, $extension ) = @{$s->param('config_path')};
294 my $suffix = $s->param('config_local_suffix');
295
296 my @extensions = @{$s->param('extensions')};
297
298 my @files;
299 if ( $extension ) {
300 die "Unable to handle files with the extension '${extension}'" unless grep { $_ eq $extension } @extensions;
301 $path =~ s{\.$extension}{_$suffix.$extension};
302 push @files, $path;
303 } else {
304 @files = map { "${path}_${suffix}.$_" } @extensions;
305 }
306 return \@files;
307 },
308 dependencies => [ depends_on('extensions'), depends_on('config_path'), depends_on('config_local_suffix') ],
f04816ce 309 );
310}
b4a6fa62 311
0fcf9a51 312sub build_class_config_service {
313 my $self = shift;
314
315 return Bread::Board::BlockInjection->new(
316 lifecycle => 'Singleton',
317 name => 'class_config',
318 block => sub {
319 my $s = shift;
320 my $app = $s->param('application_name');
321
322 # Container might be called outside Catalyst context
323 return {} unless Class::MOP::is_class_loaded($app);
324
325 # config might not have been defined
326 return $app->config || {};
327 },
328 dependencies => [ depends_on('application_name') ],
329 );
330}
331
f04816ce 332sub build_global_config_service {
333 my $self = shift;
292277c1 334
335 return Bread::Board::BlockInjection->new(
7a267bb5 336 lifecycle => 'Singleton',
292277c1 337 name => 'global_config',
338 block => sub {
339 my $s = shift;
340
341 return Config::Any->load_files({
342 files => $s->param('global_files'),
343 filter => \&_fix_syntax,
344 use_ext => 1,
345 driver_args => $s->param('driver'),
346 });
347 },
348 dependencies => [ depends_on('global_files') ],
f04816ce 349 );
350}
b4a6fa62 351
f04816ce 352sub build_local_config_service {
353 my $self = shift;
292277c1 354
355 return Bread::Board::BlockInjection->new(
7a267bb5 356 lifecycle => 'Singleton',
292277c1 357 name => 'local_config',
358 block => sub {
359 my $s = shift;
360
361 return Config::Any->load_files({
362 files => $s->param('local_files'),
363 filter => \&_fix_syntax,
364 use_ext => 1,
365 driver_args => $s->param('driver'),
366 });
367 },
368 dependencies => [ depends_on('local_files') ],
f04816ce 369 );
370}
b4a6fa62 371
f04816ce 372sub build_config_path_service {
373 my $self = shift;
b4a6fa62 374
292277c1 375 return Bread::Board::BlockInjection->new(
7a267bb5 376 lifecycle => 'Singleton',
292277c1 377 name => 'config_path',
378 block => sub {
379 my $s = shift;
b4a6fa62 380
292277c1 381 my $path = $s->param('path');
382 my $prefix = $s->param('prefix');
b4a6fa62 383
292277c1 384 my ( $extension ) = ( $path =~ m{\.(.{1,4})$} );
385
386 if ( -d $path ) {
387 $path =~ s{[\/\\]$}{};
388 $path .= "/$prefix";
389 }
b4a6fa62 390
292277c1 391 return [ $path, $extension ];
392 },
393 dependencies => [ depends_on('prefix'), depends_on('path') ],
f04816ce 394 );
395}
b4a6fa62 396
f04816ce 397sub build_config_local_suffix_service {
398 my $self = shift;
292277c1 399
400 return Bread::Board::BlockInjection->new(
7a267bb5 401 lifecycle => 'Singleton',
292277c1 402 name => 'config_local_suffix',
403 block => sub {
404 my $s = shift;
6c743f02 405 my $suffix = Catalyst::Utils::env_value( $s->param('application_name'), 'CONFIG_LOCAL_SUFFIX' ) || $self->config_local_suffix;
292277c1 406
407 return $suffix;
408 },
6c743f02 409 dependencies => [ depends_on('application_name') ],
f04816ce 410 );
b4a6fa62 411}
412
3e4f5406 413sub build_locate_components_service {
414 my $self = shift;
415
416 return Bread::Board::BlockInjection->new(
417 lifecycle => 'Singleton',
418 name => 'locate_components',
419 block => sub {
420 my $s = shift;
421 my $class = $s->param('application_name');
422 my $config = $s->param('config')->{ setup_components };
423
424 Catalyst::Exception->throw(
425 qq{You are using search_extra config option. That option is\n} .
426 qq{deprecated, please refer to the documentation for\n} .
427 qq{other ways of achieving the same results.\n}
428 ) if delete $config->{ search_extra };
429
430 my @paths = qw( ::Controller ::C ::Model ::M ::View ::V );
431
432 my $locator = Module::Pluggable::Object->new(
433 search_path => [ map { s/^(?=::)/$class/; $_; } @paths ],
434 %$config
435 );
436
b47ed80b 437 return [ $locator->plugins ];
3e4f5406 438 },
439 dependencies => [ depends_on('application_name'), depends_on('config') ],
440 );
441}
442
88d81c1b 443sub setup_components {
fa6607ec 444 my $self = shift;
88d81c1b 445 my $class = $self->resolve( service => 'application_name' );
446 my @comps = @{ $self->resolve( service => 'locate_components' ) };
447 my %comps = map { $_ => 1 } @comps;
448 my $deprecatedcatalyst_component_names = 0;
fa6607ec 449
88d81c1b 450 for my $component ( @comps ) {
fa6607ec 451
88d81c1b 452 # We pass ignore_loaded here so that overlay files for (e.g.)
453 # Model::DBI::Schema sub-classes are loaded - if it's in @comps
454 # we know M::P::O found a file on disk so this is safe
fa6607ec 455
88d81c1b 456 Catalyst::Utils::ensure_class_loaded( $component, { ignore_loaded => 1 } );
457 }
fa6607ec 458
88d81c1b 459 for my $component (@comps) {
6e2a1222 460 $self->add_component( $component );
88d81c1b 461 # FIXME - $instance->expand_modules() is broken
462 my @expanded_components = $self->expand_component_module( $component );
463
464 if (
465 !$deprecatedcatalyst_component_names &&
466 ($deprecatedcatalyst_component_names = $component =~ m/::[CMV]::/) ||
467 ($deprecatedcatalyst_component_names = grep { /::[CMV]::/ } @expanded_components)
468 ) {
469 # FIXME - should I be calling warn here?
6e2a1222 470 # Maybe it's time to remove it, or become fatal
88d81c1b 471 $class->log->warn(qq{Your application is using the deprecated ::[MVC]:: type naming scheme.\n}.
472 qq{Please switch your class names to ::Model::, ::View:: and ::Controller: as appropriate.\n}
473 );
474 }
fa6607ec 475
88d81c1b 476 for my $component (@expanded_components) {
6e2a1222 477 $self->add_component( $component )
88d81c1b 478 unless $comps{$component};
479 }
480 }
fa6607ec 481}
482
b4a6fa62 483sub _fix_syntax {
484 my $config = shift;
485 my @components = (
486 map +{
487 prefix => $_ eq 'Component' ? '' : $_ . '::',
488 values => delete $config->{ lc $_ } || delete $config->{ $_ }
489 },
490 grep { ref $config->{ lc $_ } || ref $config->{ $_ } }
491 qw( Component Model M View V Controller C Plugin )
492 );
493
494 foreach my $comp ( @components ) {
495 my $prefix = $comp->{ prefix };
496 foreach my $element ( keys %{ $comp->{ values } } ) {
497 $config->{ "$prefix$element" } = $comp->{ values }->{ $element };
498 }
499 }
500}
501
502sub _config_substitutions {
6682389c 503 my ( $self, $name, $subs, $arg ) = @_;
b4a6fa62 504
505 $subs->{ HOME } ||= sub { shift->path_to( '' ); };
506 $subs->{ ENV } ||=
507 sub {
508 my ( $c, $v ) = @_;
509 if (! defined($ENV{$v})) {
510 Catalyst::Exception->throw( message =>
511 "Missing environment variable: $v" );
512 return "";
513 } else {
514 return $ENV{ $v };
515 }
516 };
517 $subs->{ path_to } ||= sub { shift->path_to( @_ ); };
518 $subs->{ literal } ||= sub { return $_[ 1 ]; };
519 my $subsre = join( '|', keys %$subs );
520
6682389c 521 $arg =~ s{__($subsre)(?:\((.+?)\))?__}{ $subs->{ $1 }->( $name, $2 ? split( /,/, $2 ) : () ) }eg;
522 return $arg;
b4a6fa62 523}
524
a17e0ff8 525sub get_component_from_sub_container {
526 my ( $self, $sub_container_name, $name, $c, @args ) = @_;
527
528 my $sub_container = $self->get_sub_container( $sub_container_name );
529
0e747f0c 530 if (!$name) {
a2c0d071 531 my $default = $sub_container->default_component;
0e747f0c 532
533 return $sub_container->get_component( $default, $c, @args )
534 if $default && $sub_container->has_service( $default );
535
a0146296 536 # FIXME - should I be calling $c->log->warn here?
0e747f0c 537 # this is never a controller, so this is safe
538 $c->log->warn( "Calling \$c->$sub_container_name() is not supported unless you specify one of:" );
539 $c->log->warn( "* \$c->config(default_$sub_container_name => 'the name of the default $sub_container_name to use')" );
540 $c->log->warn( "* \$c->stash->{current_$sub_container_name} # the name of the view to use for this request" );
541 $c->log->warn( "* \$c->stash->{current_${sub_container_name}_instance} # the instance of the $sub_container_name to use for this request" );
a2c0d071 542
543 return;
0e747f0c 544 }
545
a17e0ff8 546 return $sub_container->get_component_regexp( $name, $c, @args )
547 if ref $name;
548
549 return $sub_container->get_component( $name, $c, @args )
550 if $sub_container->has_service( $name );
551
552 $c->log->warn(
553 "Attempted to use $sub_container_name '$name', " .
554 "but it does not exist"
555 );
556
557 return;
558}
559
c4aedec7 560sub find_component {
ec17c391 561 my ( $self, $component, @args ) = @_;
f147e6c2 562 my ( $type, $name ) = _get_component_type_name($component);
c4aedec7 563 my @result;
564
d0f954b4 565 return $self->get_component_from_sub_container(
ec17c391 566 $type, $name, @args
d0f954b4 567 ) if $type;
568
c4aedec7 569 my $query = ref $component
570 ? $component
571 : qr{^$component$}
572 ;
573
574 for my $subcontainer_name (qw/model view controller/) {
a0146296 575 my $subcontainer = $self->get_sub_container( $subcontainer_name );
c4aedec7 576 my @components = $subcontainer->get_service_list;
577 @result = grep { m{$component} } @components;
578
ec17c391 579 return map { $subcontainer->get_component( $_, @args ) } @result
c4aedec7 580 if @result;
581 }
582
d0f954b4 583 # one last search for things like $c->comp(qr/::M::/)
584 @result = $self->find_component_regexp(
ec17c391 585 $component, @args
d0f954b4 586 ) if !@result and ref $component;
587
c4aedec7 588 # it expects an empty list on failed searches
589 return @result;
590}
591
4e2b302e 592sub find_component_regexp {
ec17c391 593 my ( $self, $component, @args ) = @_;
4e2b302e 594 my @result;
595
ec17c391 596 my @components = grep { m{$component} } keys %{ $self->get_all_components };
4e2b302e 597
598 for (@components) {
f147e6c2 599 my ($type, $name) = _get_component_type_name($_);
4e2b302e 600
601 push @result, $self->get_component_from_sub_container(
602 $type, $name, @args
603 ) if $type;
604 }
605
606 return @result;
607}
608
b4410fc3 609sub get_all_components {
610 my $self = shift;
611 my %components;
612
ec17c391 613 my $container = $self->get_sub_container('component');
b4410fc3 614
ec17c391 615 for my $component ($container->get_service_list) {
616 my $comp = $container->resolve(
617 service => $component
618 );
619 my $comp_name = ref $comp || $comp;
620 $components{$comp_name} = $comp;
b4410fc3 621 }
622
623 return lock_hash %components;
624}
625
f147e6c2 626sub add_component {
6e2a1222 627 my ( $self, $component ) = @_;
f147e6c2 628 my ( $type, $name ) = _get_component_type_name($component);
629
630 return unless $type;
631
ff0e9735 632 my $component_service_name = "${type}_${name}";
633
b844dcad 634 # The 'component' sub-container will create the object, and store it's
635 # instance, which, by default, will live throughout the application.
636 # The model/view/controller sub-containers only reference the instance
637 # held in the aforementioned sub-container, and execute the ACCEPT_CONTEXT
638 # sub every time they are called, when it exists.
639 my $instance_container = $self->get_sub_container('component');
640 my $accept_context_container = $self->get_sub_container($type);
641
642 $instance_container->add_service(
b7da37bd 643 Catalyst::IOC::ConstructorInjection->new(
ff0e9735 644 name => $component_service_name,
b7da37bd 645 class => $component,
ff0e9735 646 lifecycle => 'Singleton',
bf142143 647 dependencies => [
648 depends_on( '/application_name' ),
649 depends_on( '/config' ),
650 ],
ff0e9735 651 )
b844dcad 652 ) unless $instance_container->has_service( $component_service_name );
653 # ^ custom containers might have added the service already.
654 # we don't want to override that.
ff0e9735 655
b844dcad 656 $accept_context_container->add_service(
ff0e9735 657 Catalyst::IOC::BlockInjection->new(
658 name => $name,
659 dependencies => [
660 depends_on( "/component/$component_service_name" ),
661 ],
b844dcad 662 block => sub { shift->param($component_service_name) },
f147e6c2 663 )
b844dcad 664 ) unless $accept_context_container->has_service( $name );
665 # ^ same as above
f147e6c2 666}
667
668# FIXME: should this sub exist?
669# should it be moved to Catalyst::Utils,
670# or replaced by something already existing there?
671sub _get_component_type_name {
672 my ( $component ) = @_;
673
674 my @parts = split /::/, $component;
675
a3901a8a 676 while (scalar @parts > 1) {
677 my $type = shift @parts;
678
f147e6c2 679 return ('controller', join '::', @parts)
680 if $type =~ /^(c|controller)$/i;
681
682 return ('model', join '::', @parts)
683 if $type =~ /^(m|model)$/i;
684
685 return ('view', join '::', @parts)
686 if $type =~ /^(v|view)$/i;
687 }
688
689 return (undef, $component);
690}
691
d3742403 692sub expand_component_module {
693 my ( $class, $module ) = @_;
694 return Devel::InnerPackage::list_packages( $module );
695}
0dff29e2 696
2402ef14 697# copied from stevan's OX
698sub flush_request_services {
699 my $self = shift;
700 my @services = $self->get_service_list;
701
702 foreach my $service (@services) {
703 my $injection = $self->get_service($service);
704 if ($injection->does('Catalyst::IOC::LifeCycle::Request')) {
705 $injection->flush_instance;
706 }
707 }
708}
709
d057ddb9 7101;
711
712__END__
713
714=pod
715
716=head1 NAME
717
718Catalyst::Container - IOC for Catalyst components
719
2c2ed473 720=head1 SYNOPSIS
721
722=head1 DESCRIPTION
723
d057ddb9 724=head1 METHODS
725
bbb306a9 726=head1 Building Containers
a0146296 727
309caf39 728=head2 build_component_subcontainer
729
730Container that stores all components, i.e. all models, views and controllers
731together. Each service is an instance of the actual component, and by default
732it lives while the application is running. Retrieving components from this
733subcontainer will instantiate the component, if it hasn't been instantiated
734already, but will not execute ACCEPT_CONTEXT.
735
d057ddb9 736=head2 build_model_subcontainer
737
309caf39 738Container that stores references for all models that are inside the components
739subcontainer. Retrieving a model triggers ACCEPT_CONTEXT, if it exists.
a0146296 740
d057ddb9 741=head2 build_view_subcontainer
742
309caf39 743Same as L<build_model_subcontainer>, but for views.
a0146296 744
d057ddb9 745=head2 build_controller_subcontainer
746
59221ae6 747Same as L<build_model_subcontainer>, but for controllers.
a0146296 748
bbb306a9 749=head1 Building Services
a0146296 750
a4541222 751=head2 build_application_name_service
d057ddb9 752
a4541222 753Name of the application (such as MyApp).
a0146296 754
d057ddb9 755=head2 build_driver_service
756
a0146296 757Config options passed directly to the driver being used.
758
d057ddb9 759=head2 build_file_service
760
a0146296 761?
762
d057ddb9 763=head2 build_substitutions_service
764
bbb306a9 765This method substitutes macros found with calls to a function. There are a
766number of default macros:
767
768=over
769
770=item * C<__HOME__> - replaced with C<$c-E<gt>path_to('')>
771
772=item * C<__ENV(foo)__> - replaced with the value of C<$ENV{foo}>
773
774=item * C<__path_to(foo/bar)__> - replaced with C<$c-E<gt>path_to('foo/bar')>
775
776=item * C<__literal(__FOO__)__> - leaves __FOO__ alone (allows you to use
777C<__DATA__> as a config value, for example)
778
779=back
780
781The parameter list is split on comma (C<,>). You can override this method to
782do your own string munging, or you can define your own macros in
5faa454d 783C<< <MyApp->config( 'Plugin::ConfigLoader' => { substitutions => { ... } } ) >>.
bbb306a9 784Example:
785
5faa454d 786 MyApp->config( 'Plugin::ConfigLoader' => {
787 substitutions => {
788 baz => sub { my $c = shift; qux( @_ ); },
789 },
790 });
bbb306a9 791
792The above will respond to C<__baz(x,y)__> in config strings.
a0146296 793
d057ddb9 794=head2 build_extensions_service
795
bbb306a9 796Config::Any's available config file extensions (e.g. xml, json, pl, etc).
797
d057ddb9 798=head2 build_prefix_service
799
bbb306a9 800The prefix, based on the application name, that will be used to lookup the
801config files (which will be in the format $prefix.$extension). If the app is
802MyApp::Foo, the prefix will be myapp_foo.
803
d057ddb9 804=head2 build_path_service
805
bbb306a9 806The path to the config file (or environment variable, if defined).
807
d057ddb9 808=head2 build_config_service
809
bbb306a9 810The resulting configuration for the application, after it has successfully
811been loaded, and all substitutions have been made.
812
d057ddb9 813=head2 build_raw_config_service
814
bbb306a9 815The merge of local_config and global_config hashes, before substitutions.
816
d057ddb9 817=head2 build_global_files_service
818
bbb306a9 819Gets all files for config that don't have the local_suffix, such as myapp.conf.
820
d057ddb9 821=head2 build_local_files_service
822
bbb306a9 823Gets all files for config that have the local_suffix, such as myapp_local.conf.
824
d057ddb9 825=head2 build_global_config_service
826
bbb306a9 827Reads config from global_files.
828
d057ddb9 829=head2 build_local_config_service
830
bbb306a9 831Reads config from local_files.
832
800a31b0 833=head2 build_class_config_service
834
835Reads config set from the application's class attribute config,
836i.e. MyApp->config( name => 'MyApp', ... )
837
d057ddb9 838=head2 build_config_path_service
839
bbb306a9 840Splits the path to the config file, and returns on array ref containing
841the path to the config file minus the extension in the first position,
842and the extension in the second.
843
d057ddb9 844=head2 build_config_local_suffix_service
845
a0146296 846Determines the suffix of files used to override the main config. By default
847this value is C<local>, which will load C<myapp_local.conf>. The suffix can
848be specified in the following order of preference:
849
850=over
851
852=item * C<$ENV{ MYAPP_CONFIG_LOCAL_SUFFIX }>
853
854=item * C<$ENV{ CATALYST_CONFIG_LOCAL_SUFFIX }>
855
856=back
857
858The first one of these values found replaces the default of C<local> in the
859name of the local config file to be loaded.
860
861For example, if C< $ENV{ MYAPP_CONFIG_LOCAL_SUFFIX }> is set to C<testing>,
862ConfigLoader will try and load C<myapp_testing.conf> instead of
863C<myapp_local.conf>.
864
bbb306a9 865=head2 build_locate_components_service
866
867This method is meant to provide a list of component modules that should be
868setup for the application. By default, it will use L<Module::Pluggable>.
869
870Specify a C<setup_components> config option to pass additional options directly
871to L<Module::Pluggable>.
872
873=head1 Other methods
874
a0146296 875=head2 get_component_from_sub_container($sub_container, $name, $c, @args)
876
164a0b2b 877Looks for components in a given subcontainer (such as controller, model or
878view), and returns the searched component. If $name is undef, it returns the
879default component (such as default_view, if $sub_container is 'view'). If
880$name is a regexp, it returns an array of matching components. Otherwise, it
881looks for the component with name $name.
8dc2fca3 882
9f4997cf 883=head2 get_components_names_types
884
164a0b2b 885Gets all components from all containers and returns them as an array of
886arrayrefs containing the component name and the component type (i.e., whether
887it's an instance or a class).
409db9cb 888
b4410fc3 889=head2 get_all_components
890
164a0b2b 891Fetches all the components, in each of the sub_containers model, view and
892controller, and returns a readonly hash. The keys are the class names, and
893the values are the blessed objects. This is what is returned by $c->components.
a0146296 894
f147e6c2 895=head2 add_component
896
164a0b2b 897Adds a component to the appropriate subcontainer. The subcontainer is guessed
898by the component name given.
a0146296 899
c4aedec7 900=head2 find_component
901
164a0b2b 902Searches for components in all containers. If $component is the full class
903name, the subcontainer is guessed, and it gets the searched component in there.
904Otherwise, it looks for a component with that name in all subcontainers. If
905$component is a regexp, it calls the method below, find_component_regexp,
906and matches all components against that regexp.
a0146296 907
4e2b302e 908=head2 find_component_regexp
909
a0146296 910Finds components that match a given regexp. Used internally, by find_component.
911
6e2a1222 912=head2 expand_component_module
d3742403 913
914Components found by C<locate_components> will be passed to this method, which
915is expected to return a list of component (package) names to be set up.
916
2402ef14 917=head2 flush_request_services
918
ebf7f0a5 919=head2 setup_components
fa6607ec 920
bf3c8088 921=head1 AUTHORS
922
e8ed391e 923Catalyst Contributors, see Catalyst.pm
bf3c8088 924
e8ed391e 925=head1 COPYRIGHT
bf3c8088 926
927This library is free software. You can redistribute it and/or modify it under
928the same terms as Perl itself.
929
930=cut