Merge branch 'master' into gsoc_breadboard
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Controller.pm
index bb4ce8b..1bc8e2a 100644 (file)
@@ -2,6 +2,7 @@ package Catalyst::Controller;
 
 use Moose;
 use Class::MOP;
+use Class::Load ':all';
 use String::RewritePrefix;
 use Moose::Util qw/find_meta/;
 use List::Util qw/first/;
@@ -83,7 +84,7 @@ sub BUILD {
 sub _build__action_roles {
     my $self = shift;
     my @roles = $self->_expand_role_shortname($self->_action_role_args);
-    Class::MOP::load_class($_) for @roles;
+    load_class($_) for @roles;
     return \@roles;
 }
 
@@ -186,6 +187,12 @@ around action_namespace => sub {
 
     my $class = ref($self) || $self;
     my $appclass = ref($c) || $c;
+
+    # FIXME - catalyst_component_name is no longer a class accessor, because
+    # 'MyApp as a controller' behavior is removed. But is this call to
+    # catalyst_component_name necessary, or is it always the same as $class?
+    my $component_name = ref($self) ? $self->catalyst_component_name : $self;
+
     if( ref($self) ){
         return $self->$orig if $self->has_action_namespace;
     } else {
@@ -207,7 +214,7 @@ around action_namespace => sub {
         }
     }
 
-    my $namespace = Catalyst::Utils::class2prefix($self->catalyst_component_name, $case_s) || '';
+    my $namespace = Catalyst::Utils::class2prefix($component_name, $case_s) || '';
     $self->$orig($namespace) if ref($self);
     return $namespace;
 };
@@ -274,7 +281,7 @@ sub register_action_methods {
         my $attributes = $method->can('attributes') ? $method->attributes : [];
         my $attrs = $self->_parse_attrs( $c, $name, @{ $attributes } );
         if ( $attrs->{Private} && ( keys %$attrs > 1 ) ) {
-            $c->log->debug( 'Bad action definition "'
+            $c->log->warn( 'Bad action definition "'
                   . join( ' ', @{ $attributes } )
                   . qq/" for "$class->$name"/ )
               if $c->debug;
@@ -297,7 +304,7 @@ sub register_action_methods {
 sub _apply_action_class_roles {
     my ($self, $class, @roles) = @_;
 
-    Class::MOP::load_class($_) for @roles;
+    load_class($_) for @roles;
     my $meta = Moose::Meta::Class->initialize($class)->create_anon_class(
         superclasses => [$class],
         roles        => \@roles,
@@ -406,16 +413,30 @@ sub _parse_attrs {
 
     my %final_attributes;
 
-    foreach my $key (keys %raw_attributes) {
+    while (my ($key, $value) = each %raw_attributes){
+        my $new_attrs = $self->_parse_attr($c, $name, $key => $value );
+        push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
+    }
 
-        my $raw = $raw_attributes{$key};
+    return \%final_attributes;
+}
 
-        foreach my $value (ref($raw) eq 'ARRAY' ? @$raw : $raw) {
+sub _parse_attr {
+    my ($self, $c, $name, $key, $values) = @_;
 
-            my $meth = "_parse_${key}_attr";
-            if ( my $code = $self->can($meth) ) {
-                ( $key, $value ) = $self->$code( $c, $name, $value );
+    my %final_attributes;
+    foreach my $value (ref($values) eq 'ARRAY' ? @$values : $values) {
+        my $meth = "_parse_${key}_attr";
+        if ( my $code = $self->can($meth) ) {
+            my %new_attrs = $self->$code( $c, $name, $value );
+            while (my ($new_key, $value) = each %new_attrs){
+                my $new_attrs = $key eq $new_key ?
+                    { $new_key => [$value] } :
+                    $self->_parse_attr($c, $name, $new_key => $value );
+                push @{ $final_attributes{$_} }, @{ $new_attrs->{$_} } for keys %$new_attrs;
             }
+        }
+        else {
             push( @{ $final_attributes{$key} }, $value );
         }
     }
@@ -425,14 +446,16 @@ sub _parse_attrs {
 
 sub _parse_Global_attr {
     my ( $self, $c, $name, $value ) = @_;
-    return $self->_parse_Path_attr( $c, $name, "/$name" );
+    # _parse_attr will call _parse_Path_attr for us
+    return Path => "/$name";
 }
 
 sub _parse_Absolute_attr { shift->_parse_Global_attr(@_); }
 
 sub _parse_Local_attr {
     my ( $self, $c, $name, $value ) = @_;
-    return $self->_parse_Path_attr( $c, $name, $name );
+    # _parse_attr will call _parse_Path_attr for us
+    return Path => $name;
 }
 
 sub _parse_Relative_attr { shift->_parse_Local_attr(@_); }
@@ -518,7 +541,7 @@ sub _parse_MyAction_attr {
     my ( $self, $c, $name, $value ) = @_;
 
     my $appclass = Catalyst::Utils::class2appclass($self);
-    $value = "${appclass}::Action::${value}";
+    $value = "+${appclass}::Action::${value}";
 
     return ( 'ActionClass', $value );
 }
@@ -537,7 +560,7 @@ sub _expand_role_shortname {
 
     return String::RewritePrefix->rewrite(
         { ''  => sub {
-            my $loaded = Class::MOP::load_first_existing_class(
+            my $loaded = load_first_existing_class(
                 map { "$_$_[0]" } @prefixes
             );
             return first { $loaded =~ /^$_/ }