Merging of gsoc_breadboard
André Walker [Wed, 6 Jul 2011 23:12:26 +0000 (20:12 -0300)]
1  2 
lib/Catalyst.pm
lib/Catalyst/Container.pm

diff --combined lib/Catalyst.pm
@@@ -536,6 -536,34 +536,6 @@@ sub clear_errors 
      $c->error(0);
  }
  
 -sub _find_component_regexp {
 -    my ( $c, $container, $name, $args ) = @_;
 -
 -    return
 -        if $c->config->{disable_component_resolution_regex_fallback} && !ref $name;
 -
 -    my $appclass = ref $c || $c;
 -    my $prefix   = ucfirst $container->name;
 -    my $p        = substr $prefix, 0, 1;
 -
 -    my $query = ref $name ? $name : qr{$name}i;
 -    $query =~ s/^${appclass}::($p|$prefix):://i;
 -
 -    my @comps  = $container->get_service_list;
 -    my @result = map {
 -        $container->resolve( service => $_, parameters => { context => $args } )
 -    } grep { m/$query/ } @comps;
 -
 -    if (!ref $name && $result[0]) {
 -        $c->log->warn( Carp::shortmess(qq(Found results for "${name}" using regexp fallback)) );
 -        $c->log->warn( 'Relying on the regexp fallback behavior for component resolution' );
 -        $c->log->warn( 'is unreliable and unsafe. You have been warned' );
 -        return $result[0];
 -    }
 -
 -    return @result;
 -}
 -
  =head2 COMPONENT ACCESSORS
  
  =head2 $c->controller($name)
@@@ -562,10 -590,10 +562,10 @@@ sub controller 
  
      if( $name ) {
          # Direct component hash lookup to avoid costly regexps
 -        return $c->container->get_component('controller', $name, \@args)
 +        return $container->get_component($name, \@args)
              if $container->has_service($name) && !ref $name;
  
 -        return $c->_find_component_regexp( $container, $name, \@args );
 +        return $container->get_component_regexp( $c, $name, \@args );
      }
  
      return $c->component( $c->action->class );
@@@ -600,10 -628,10 +600,10 @@@ sub model 
  
      if( $name ) {
          # Direct component hash lookup to avoid costly regexps
 -        return $c->container->get_component('model', $name, \@args)
 +        return $container->get_component($name, \@args)
              if $container->has_service($name) && !ref $name;
  
 -        return $c->_find_component_regexp( $container, $name, \@args );
 +        return $container->get_component_regexp( $c, $name, \@args );
      }
  
      if (ref $c) {
          $c->log->warn( 'NB: in version 5.81, the "random" behavior will not work at all.' );
      }
  
 -    return $container->resolve( service => $comp, parameters => { context => \@args } );
 +    return $container->get_component( $comp, \@args );
  }
  
  
@@@ -658,13 -686,16 +658,13 @@@ sub view 
      unshift @args, $c;
  
      if( $name ) {
 -        if ( !ref $name ) { # Direct component hash lookup to avoid costly regexps
 -            if ( $container->has_service($name) ) {
 -                return $c->container->get_component('view', $name, \@args);
 -            }
 -            else {
 -                $c->log->warn( "Attempted to use view '$name', but does not exist" );
 -            }
 -        }
 +        # Direct component hash lookup to avoid costly regexps
 +        return $container->get_component($name, \@args)
 +            if !ref $name && $container->has_service($name);
 +
 +        $c->log->warn( "Attempted to use view '$name', but does not exist" );
  
 -        return $c->_find_component_regexp( $container, $name, \@args );
 +        return $container->get_component_regexp( $c, $name, \@args );
      }
  
      if (ref $c) {
          $c->log->warn( 'NB: in version 5.81, the "random" behavior will not work at all.' );
      }
  
 -    return $container->resolve( service => $comp, parameters => { context => \@args } );
 +    return $container->get_component( $comp, \@args );
  }
  
  =head2 $c->controllers
@@@ -745,7 -776,6 +745,7 @@@ disable_component_resolution_regex_fall
  
  sub component {
      my ( $c, $component, @args ) = @_;
 +    unshift @args, $c;
  
      if ( $component ) {
          my ($type, $name) = _get_component_type_name($component);
              my $container = $c->container->get_sub_container($type);
  
              if( !ref $component && $container->has_service($name) ) {
 -                return $container->resolve( service => $name, parameters => { context => [ $c, @args ] } );
 +                return $container->get_component( $name, \@args );
              }
  
 -            return
 -                if $c->config->{disable_component_resolution_regex_fallback};
 -
 -            my $query      = qr{$name}i;
 -            my @components = $container->get_service_list;
 -            my @result     = grep { m{$query} } @components;
 -
 -            if (@result) {
 -                $c->log->warn( Carp::shortmess(qq(Found results for "${component}" using regexp fallback)) );
 -                $c->log->warn( 'Relying on the regexp fallback behavior for component resolution' );
 -                $c->log->warn( 'is unreliable and unsafe. You have been warned' );
 -
 -                return $container->resolve( service => $result[0], parameters => { context => [$c, @args] } );
 -            }
 +            return $container->get_component_regexp( $c, $name, \@args );
          }
  
          return
              my @result       = grep { m{$query} } @components;
  
              if (@result) {
 -                return map { $subcontainer->resolve( service => $_, parameters => { context => [$c, @args] } ) } @result
 +                return map { $subcontainer->get_component( $_, \@args ) } @result
                      if ref $component;
  
                  $c->log->warn( Carp::shortmess(qq(Found results for "${component}" using regexp fallback)) );
                  $c->log->warn( 'Relying on the regexp fallback behavior for component resolution' );
                  $c->log->warn( 'is unreliable and unsafe. You have been warned' );
  
 -                return $subcontainer->resolve( service => $result[0], parameters => { context => [$c, @args] } );
 +                return $subcontainer->get_component( $result[0], \@args );
              }
          }
  
@@@ -2373,7 -2416,7 +2373,7 @@@ sub setup_config 
      $class->finalize_config; # back-compat
  }
  
- =head $c->finalize_config
+ =head2 $c->finalize_config
  
  =cut
  
@@@ -43,314 -43,375 +43,375 @@@ has sub_container_class => 
      isa     => LoadableClass,
      is      => 'ro',
      coerce  => 1,
 -    default => 'Bread::Board::Container',
 +    default => 'Catalyst::SubContainer',
  );
  
+ =head1 NAME
+ Catalyst::Container - IOC for Catalyst components
+ =head1 METHODS
+ =cut
  sub BUILD {
      my $self = shift;
  
-     $self->build_root_container;
+     $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->build_model_subcontainer;
-     $self->build_view_subcontainer;
-     $self->build_controller_subcontainer;
+     $self->add_sub_container(
+         $self->${ \"build_${_}_subcontainer" }
+     ) for qw/ model view controller /;
  }
  
+ =head2 build_model_subcontainer
+ =cut
  sub build_model_subcontainer {
      my $self = shift;
  
-     $self->add_sub_container(
-         $self->sub_container_class->new( name => 'model' )
-     );
+     return $self->sub_container_class->new( name => 'model' );
  }
  
+ =head2 build_view_subcontainer
+ =cut
  sub build_view_subcontainer {
      my $self = shift;
  
-     $self->add_sub_container(
-         $self->sub_container_class->new( name => 'view' )
-     );
+     return $self->sub_container_class->new( name => 'view' );
  }
  
+ =head2 build_controller_subcontainer
+ =cut
  sub build_controller_subcontainer {
      my $self = shift;
  
-     $self->add_sub_container(
-         $self->sub_container_class->new( name => 'controller' )
-     );
+     return $self->sub_container_class->new( name => 'controller' );
  }
  
- sub build_root_container {
-     my $self = shift;
+ =head2 build_name_service
  
-     $self->build_substitutions_service();
-     $self->build_file_service();
-     $self->build_driver_service();
-     $self->build_name_service();
-     $self->build_prefix_service();
-     $self->build_extensions_service();
-     $self->build_path_service();
-     $self->build_config_service();
-     $self->build_raw_config_service();
-     $self->build_global_files_service();
-     $self->build_local_files_service();
-     $self->build_global_config_service();
-     $self->build_local_config_service();
-     $self->build_config_local_suffix_service();
-     $self->build_config_path_service();
- }
+ =cut
  
  sub build_name_service {
      my $self = shift;
-     $self->add_service(
-         Bread::Board::Literal->new( name => 'name', value => $self->name )
-     );
+     return Bread::Board::Literal->new( name => 'name', value => $self->name );
  }
  
+ =head2 build_driver_service
+ =cut
  sub build_driver_service {
      my $self = shift;
-     $self->add_service(
-         Bread::Board::Literal->new( name => 'driver', value => $self->driver )
-     );
+     return Bread::Board::Literal->new( name => 'driver', value => $self->driver );
  }
  
+ =head2 build_file_service
+ =cut
  sub build_file_service {
      my $self = shift;
-     $self->add_service(
-         Bread::Board::Literal->new( name => 'file', value => $self->file )
-     );
+     return Bread::Board::Literal->new( name => 'file', value => $self->file );
  }
  
+ =head2 build_substitutions_service
+ =cut
  sub build_substitutions_service {
      my $self = shift;
-     $self->add_service(
-         Bread::Board::Literal->new( name => 'substitutions', value => $self->substitutions )
-     );
+     return Bread::Board::Literal->new( name => 'substitutions', value => $self->substitutions );
  }
  
+ =head2 build_extensions_service
+ =cut
  sub build_extensions_service {
      my $self = shift;
-     $self->add_service(
-         Bread::Board::BlockInjection->new(
-             name => 'extensions',
-             block => sub {
-                 return \@{Config::Any->extensions};
-             },
-         )
+     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;
-     $self->add_service(
-         Bread::Board::BlockInjection->new(
-             name => 'prefix',
-             block => sub {
-                 return Catalyst::Utils::appprefix( shift->param('name') );
-             },
-             dependencies => [ depends_on('name') ],
-         )
+     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;
-     $self->add_service(
-         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') ],
-         )
+     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;
-     $self->add_service(
-         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'), $_ );
-                     }
-                 );
-                 $v->visit( $s->param('raw_config') );
-             },
-             dependencies => [ depends_on('name'), depends_on('raw_config'), depends_on('substitutions') ],
-         )
+     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'), $_ );
+                 }
+             );
+             $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;
-     $self->add_service(
-         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 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') ],
-         )
+             }
+             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;
-     $self->add_service(
-         Bread::Board::BlockInjection->new(
-             name => 'global_files',
-             block => sub {
-                 my $s = shift;
  
-                 my ( $path, $extension ) = @{$s->param('config_path')};
+     return Bread::Board::BlockInjection->new(
+         name => 'global_files',
+         block => sub {
+             my $s = shift;
  
-                 my @extensions = @{$s->param('extensions')};
+             my ( $path, $extension ) = @{$s->param('config_path')};
  
-                 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') ],
-         )
+             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;
-     $self->add_service(
-         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') ],
-         )
+     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;
-     $self->add_service(
-         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') ],
-         )
+     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;
-     $self->add_service(
-         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') ],
-         )
+     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;
-     $self->add_service(
-         Bread::Board::BlockInjection->new(
-             name => 'config_path',
-             block => sub {
-                 my $s = shift;
  
-                 my $path = $s->param('path');
-                 my $prefix = $s->param('prefix');
+     return Bread::Board::BlockInjection->new(
+         name => 'config_path',
+         block => sub {
+             my $s = shift;
  
-                 my ( $extension ) = ( $path =~ m{\.(.{1,4})$} );
+             my $path = $s->param('path');
+             my $prefix = $s->param('prefix');
  
-                 if ( -d $path ) {
-                     $path =~ s{[\/\\]$}{};
-                     $path .= "/$prefix";
-                 }
+             my ( $extension ) = ( $path =~ m{\.(.{1,4})$} );
+             if ( -d $path ) {
+                 $path =~ s{[\/\\]$}{};
+                 $path .= "/$prefix";
+             }
  
-                 return [ $path, $extension ];
-             },
-             dependencies => [ depends_on('prefix'), depends_on('path') ],
-         )
+             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;
-     $self->add_service(
-         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') ],
-         )
+     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 = (
      }
  }
  
+ =head2 _config_substitutions
+ =cut
  sub _config_substitutions {
      my ( $self, $name, $subs, $arg ) = @_;
  
      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;