A little POD
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Container.pm
index 58a2702..ba71092 100644 (file)
@@ -4,6 +4,8 @@ use Moose;
 use Config::Any;
 use Data::Visitor::Callback;
 use Catalyst::Utils ();
+use MooseX::Types::LoadableClass qw/ LoadableClass /;
+use Catalyst::BlockInjection;
 
 extends 'Bread::Board::Container';
 
@@ -37,183 +39,379 @@ has name => (
     default => 'TestApp',
 );
 
+has sub_container_class => (
+    isa     => LoadableClass,
+    is      => 'ro',
+    coerce  => 1,
+    default => 'Bread::Board::Container',
+);
+
+=head1 NAME
+
+Catalyst::Container - IOC for Catalyst components
+
+=head1 METHODS
+
+=cut
+
 sub BUILD {
     my $self = shift;
 
-    container $self => as {
-        service name => $self->name;
-        service driver => $self->driver;
-        service file => $self->file;
-        service substitutions => $self->substitutions;
-
-        service extensions => (
-            block => sub {
-                return \@{Config::Any->extensions};
-            },
-        );
-
-        service prefix => (
-            block => sub {
-                return Catalyst::Utils::appprefix( shift->param('name') );
-            },
-            dependencies => [ depends_on('name') ],
-         );
-
-        service path => (
-            block => sub {
-                my $s = shift;
-
-                return Catalyst::Utils::env_value( $s->param('name'), 'CONFIG' )
-                || $s->param('file')
-                || $s->param('name')->path_to( $s->param('prefix') );
-            },
-            dependencies => [ depends_on('file'), depends_on('name'), depends_on('prefix') ],
-        );
-
-        service config => (
-            block => sub {
-                my $s = shift;
-
-                my $v = Data::Visitor::Callback->new(
-                    plain_value => sub {
-                        return unless defined $_;
-                        return $self->_config_substitutions( $s->param('name'), $s->param('substitutions'), $_ );
-                    }
-
-                );
-                $v->visit( $s->param('raw_config') );
-            },
-            dependencies => [ depends_on('name'), depends_on('raw_config'), depends_on('substitutions') ],
-        );
-
-        service raw_config => (
-            block => sub {
-                my $s = shift;
-
-                my @global = @{$s->param('global_config')};
-                my @locals = @{$s->param('local_config')};
-
-                my $config = {};
-                for my $cfg (@global, @locals) {
-                    for (keys %$cfg) {
-                        $config = Catalyst::Utils::merge_hashes( $config, $cfg->{$_} );
-                    }
-                }
-                return $config;
-            },
-            dependencies => [ depends_on('global_config'), depends_on('local_config') ],
-        );
+    $self->add_service(
+        $self->${\"build_${_}_service"}
+    ) for qw/
+        substitutions
+        file
+        driver
+        name
+        prefix
+        extensions
+        path
+        config
+        raw_config
+        global_files
+        local_files
+        global_config
+        local_config
+        config_local_suffix
+        config_path
+    /;
+
+    $self->add_sub_container(
+        $self->${ \"build_${_}_subcontainer" }
+    ) for qw/ model view controller /;
+}
 
-        service global_files => (
-            block => sub {
-                my $s = shift;
+=head2 build_model_subcontainer
 
-                my ( $path, $extension ) = @{$s->param('config_path')};
+=cut
 
-                my @extensions = @{$s->param('extensions')};
+sub build_model_subcontainer {
+    my $self = shift;
 
-                my @files;
-                if ( $extension ) {
-                    die "Unable to handle files with the extension '${extension}'" unless grep { $_ eq $extension } @extensions;
-                    push @files, $path;
-                } else {
-                    @files = map { "$path.$_" } @extensions;
-                }
-                return \@files;
-            },
-            dependencies => [ depends_on('extensions'), depends_on('config_path') ],
-        );
-
-        service local_files => (
-            block => sub {
-                my $s = shift;
-
-                my ( $path, $extension ) = @{$s->param('config_path')};
-                my $suffix = $s->param('config_local_suffix');
-
-                my @extensions = @{$s->param('extensions')};
-
-                my @files;
-                if ( $extension ) {
-                    die "Unable to handle files with the extension '${extension}'" unless grep { $_ eq $extension } @extensions;
-                    $path =~ s{\.$extension}{_$suffix.$extension};
-                    push @files, $path;
-                } else {
-                    @files = map { "${path}_${suffix}.$_" } @extensions;
+    return $self->sub_container_class->new( name => 'model' );
+}
+
+=head2 build_view_subcontainer
+
+=cut
+
+sub build_view_subcontainer {
+    my $self = shift;
+
+    return $self->sub_container_class->new( name => 'view' );
+}
+
+=head2 build_controller_subcontainer
+
+=cut
+
+sub build_controller_subcontainer {
+    my $self = shift;
+
+    return $self->sub_container_class->new( name => 'controller' );
+}
+
+=head2 build_name_service
+
+=cut
+
+sub build_name_service {
+    my $self = shift;
+
+    return Bread::Board::Literal->new( name => 'name', value => $self->name );
+}
+
+=head2 build_driver_service
+
+=cut
+
+sub build_driver_service {
+    my $self = shift;
+
+    return Bread::Board::Literal->new( name => 'driver', value => $self->driver );
+}
+
+=head2 build_file_service
+
+=cut
+
+sub build_file_service {
+    my $self = shift;
+
+    return Bread::Board::Literal->new( name => 'file', value => $self->file );
+}
+
+=head2 build_substitutions_service
+
+=cut
+
+sub build_substitutions_service {
+    my $self = shift;
+
+    return Bread::Board::Literal->new( name => 'substitutions', value => $self->substitutions );
+}
+
+=head2 build_extensions_service
+
+=cut
+
+sub build_extensions_service {
+    my $self = shift;
+
+    return Bread::Board::BlockInjection->new(
+        name => 'extensions',
+        block => sub {
+            return \@{Config::Any->extensions};
+        },
+    );
+}
+
+=head2 build_prefix_service
+
+=cut
+
+sub build_prefix_service {
+    my $self = shift;
+
+    return Bread::Board::BlockInjection->new(
+        name => 'prefix',
+        block => sub {
+            return Catalyst::Utils::appprefix( shift->param('name') );
+        },
+        dependencies => [ depends_on('name') ],
+    );
+}
+
+=head2 build_path_service
+
+=cut
+
+sub build_path_service {
+    my $self = shift;
+
+    return Bread::Board::BlockInjection->new(
+        name => 'path',
+        block => sub {
+            my $s = shift;
+
+            return Catalyst::Utils::env_value( $s->param('name'), 'CONFIG' )
+            || $s->param('file')
+            || $s->param('name')->path_to( $s->param('prefix') );
+        },
+        dependencies => [ depends_on('file'), depends_on('name'), depends_on('prefix') ],
+    );
+}
+
+=head2 build_config_service
+
+=cut
+
+sub build_config_service {
+    my $self = shift;
+
+    return Bread::Board::BlockInjection->new(
+        name => 'config',
+        block => sub {
+            my $s = shift;
+
+            my $v = Data::Visitor::Callback->new(
+                plain_value => sub {
+                    return unless defined $_;
+                    return $self->_config_substitutions( $s->param('name'), $s->param('substitutions'), $_ );
                 }
-                return \@files;
-            },
-            dependencies => [ depends_on('extensions'), depends_on('config_path'), depends_on('config_local_suffix') ],
-        );
-
-        service global_config => (
-            block => sub {
-                my $s = shift;
-                my @files = @{$s->param('global_files')};
-
-                my $cfg = Config::Any->load_files({
-                    files       => \@files,
-                    filter      => \&_fix_syntax,
-                    use_ext     => 1,
-                    driver_args => $s->param('driver'),
-                });
-
-                return $cfg;
-            },
-            dependencies => [ depends_on('global_files') ],
-        );
-
-        service local_config => (
-            block => sub {
-                my $s = shift;
-
-                my @files = @{$s->param('local_files')};
-
-                my $cfg = Config::Any->load_files({
-                    files       => \@files,
-                    filter      => \&_fix_syntax,
-                    use_ext     => 1,
-                    driver_args => $s->param('driver'),
-                });
-
-                 return $cfg;
-            },
-            dependencies => [ depends_on('local_files') ],
-        );
-
-        service config_path => (
-            block => sub {
-                my $s = shift;
-
-                my $path = $s->param('path');
-                my $prefix = $s->param('prefix');
-
-                my ( $extension ) = ( $path =~ m{\.(.{1,4})$} );
-
-                if ( -d $path ) {
-                    $path =~ s{[\/\\]$}{};
-                    $path .= "/$prefix";
+
+            );
+            $v->visit( $s->param('raw_config') );
+        },
+        dependencies => [ depends_on('name'), depends_on('raw_config'), depends_on('substitutions') ],
+    );
+}
+
+=head2 build_raw_config_service
+
+=cut
+
+sub build_raw_config_service {
+    my $self = shift;
+
+    return Bread::Board::BlockInjection->new(
+        name => 'raw_config',
+        block => sub {
+            my $s = shift;
+
+            my @global = @{$s->param('global_config')};
+            my @locals = @{$s->param('local_config')};
+
+            my $config = {};
+            for my $cfg (@global, @locals) {
+                for (keys %$cfg) {
+                    $config = Catalyst::Utils::merge_hashes( $config, $cfg->{$_} );
                 }
+            }
+            return $config;
+        },
+        dependencies => [ depends_on('global_config'), depends_on('local_config') ],
+    );
+}
+
+=head2 build_global_files_service
+
+=cut
+
+sub build_global_files_service {
+    my $self = shift;
 
-                return [ $path, $extension ];
-            },
-            dependencies => [ depends_on('prefix'), depends_on('path') ],
-        );
+    return Bread::Board::BlockInjection->new(
+        name => 'global_files',
+        block => sub {
+            my $s = shift;
 
-        service config_local_suffix => (
-            block => sub {
-                my $s = shift;
-                my $suffix = Catalyst::Utils::env_value( $s->param('name'), 'CONFIG_LOCAL_SUFFIX' ) || $self->config_local_suffix;
+            my ( $path, $extension ) = @{$s->param('config_path')};
 
-                return $suffix;
-            },
-            dependencies => [ depends_on('name') ],
-        );
+            my @extensions = @{$s->param('extensions')};
 
-    };
+            my @files;
+            if ( $extension ) {
+                die "Unable to handle files with the extension '${extension}'" unless grep { $_ eq $extension } @extensions;
+                push @files, $path;
+            } else {
+                @files = map { "$path.$_" } @extensions;
+            }
+            return \@files;
+        },
+        dependencies => [ depends_on('extensions'), depends_on('config_path') ],
+    );
 }
 
+=head2 build_local_files_service
+
+=cut
+
+sub build_local_files_service {
+    my $self = shift;
+
+    return Bread::Board::BlockInjection->new(
+        name => 'local_files',
+        block => sub {
+            my $s = shift;
+
+            my ( $path, $extension ) = @{$s->param('config_path')};
+            my $suffix = $s->param('config_local_suffix');
+
+            my @extensions = @{$s->param('extensions')};
+
+            my @files;
+            if ( $extension ) {
+                die "Unable to handle files with the extension '${extension}'" unless grep { $_ eq $extension } @extensions;
+                $path =~ s{\.$extension}{_$suffix.$extension};
+                push @files, $path;
+            } else {
+                @files = map { "${path}_${suffix}.$_" } @extensions;
+            }
+            return \@files;
+        },
+        dependencies => [ depends_on('extensions'), depends_on('config_path'), depends_on('config_local_suffix') ],
+    );
+}
+
+=head2 build_global_config_service
+
+=cut
+
+sub build_global_config_service {
+    my $self = shift;
+
+    return Bread::Board::BlockInjection->new(
+        name => 'global_config',
+        block => sub {
+            my $s = shift;
+
+            return Config::Any->load_files({
+                files       => $s->param('global_files'),
+                filter      => \&_fix_syntax,
+                use_ext     => 1,
+                driver_args => $s->param('driver'),
+            });
+        },
+        dependencies => [ depends_on('global_files') ],
+    );
+}
+
+=head2 build_local_config_service
+
+=cut
+
+sub build_local_config_service {
+    my $self = shift;
+
+    return Bread::Board::BlockInjection->new(
+        name => 'local_config',
+        block => sub {
+            my $s = shift;
+
+            return Config::Any->load_files({
+                files       => $s->param('local_files'),
+                filter      => \&_fix_syntax,
+                use_ext     => 1,
+                driver_args => $s->param('driver'),
+            });
+        },
+        dependencies => [ depends_on('local_files') ],
+    );
+}
+
+=head2 build_config_path_service
+
+=cut
+
+sub build_config_path_service {
+    my $self = shift;
+
+    return Bread::Board::BlockInjection->new(
+        name => 'config_path',
+        block => sub {
+            my $s = shift;
+
+            my $path = $s->param('path');
+            my $prefix = $s->param('prefix');
+
+            my ( $extension ) = ( $path =~ m{\.(.{1,4})$} );
+
+            if ( -d $path ) {
+                $path =~ s{[\/\\]$}{};
+                $path .= "/$prefix";
+            }
+
+            return [ $path, $extension ];
+        },
+        dependencies => [ depends_on('prefix'), depends_on('path') ],
+    );
+}
+
+=head2 build_config_local_suffix_service
+
+=cut
+
+sub build_config_local_suffix_service {
+    my $self = shift;
+
+    return Bread::Board::BlockInjection->new(
+        name => 'config_local_suffix',
+        block => sub {
+            my $s = shift;
+            my $suffix = Catalyst::Utils::env_value( $s->param('name'), 'CONFIG_LOCAL_SUFFIX' ) || $self->config_local_suffix;
+
+            return $suffix;
+        },
+        dependencies => [ depends_on('name') ],
+    );
+}
+
+=head2 _fix_syntax
+
+=cut
+
 sub _fix_syntax {
     my $config     = shift;
     my @components = (
@@ -233,8 +431,12 @@ sub _fix_syntax {
     }
 }
 
+=head2 _config_substitutions
+
+=cut
+
 sub _config_substitutions {
-    my ($self, $name, $subs) = (shift, shift, shift);
+    my ( $self, $name, $subs, $arg ) = @_;
 
     $subs->{ HOME } ||= sub { shift->path_to( '' ); };
     $subs->{ ENV } ||=
@@ -252,11 +454,36 @@ sub _config_substitutions {
     $subs->{ literal } ||= sub { return $_[ 1 ]; };
     my $subsre = join( '|', keys %$subs );
 
-    for ( @_ ) {
-        my $arg = $_;
-        $arg =~ s{__($subsre)(?:\((.+?)\))?__}{ $subs->{ $1 }->( $name, $2 ? split( /,/, $2 ) : () ) }eg;
-        return $arg;
-    }
+    $arg =~ s{__($subsre)(?:\((.+?)\))?__}{ $subs->{ $1 }->( $name, $2 ? split( /,/, $2 ) : () ) }eg;
+    return $arg;
 }
 
+=head2 get_component
+
+=cut
+
+sub get_component {
+    my ( $self, $type, $name, $args ) = @_;
+    return $self->get_sub_container($type)->resolve( service => $name, parameters => { context => $args } );
+}
+
+=head1 AUTHORS
+
+=over 4
+
+=item Justin Hunter (arcanez)
+
+=item AndrĂ© Walker (andrewalker)
+
+=back
+
+Based on L<Catalyst::Plugin::ConfigLoader>, by Brian Cassidy.
+
+=head1 LICENSE
+
+This library is free software. You can redistribute it and/or modify it under
+the same terms as Perl itself.
+
+=cut
+
 1;