Merge 'trunk' into 'namespace_handling_refactor'
Rafael Kitover [Thu, 25 Jun 2009 01:05:10 +0000 (01:05 +0000)]
r5375@hlagh (orig r10489):  caelum | 2009-06-09 05:46:43 -0700
added test for ->view() with one view not returning a blessed instance
r5452@hlagh (orig r10494):  t0m | 2009-06-10 08:21:32 -0700
Add conflict line to Makefile.PL for Component::ACCEPT_CONTEXT

r5453@hlagh (orig r10497):  rafl | 2009-06-10 13:16:25 -0700
This is version 5.80.
r5454@hlagh (orig r10498):  lukes | 2009-06-10 14:20:57 -0700
prevent encoding plus signs in uri_for args
r5455@hlagh (orig r10499):  dandv | 2009-06-10 23:59:56 -0700
Fixed typos, added parameters for content_like

r5456@hlagh (orig r10500):  dandv | 2009-06-11 00:10:46 -0700
Fixed run-on sentence in COPYRIGHT and s/program/library/

r5457@hlagh (orig r10501):  dandv | 2009-06-11 00:27:56 -0700
Cosmetic: removed trailing whitespace

r5458@hlagh (orig r10502):  caelum | 2009-06-11 05:42:00 -0700
fix $c->view() bug hopefully
r5540@hlagh (orig r10551):  hobbs | 2009-06-16 11:57:17 -0700
Doc patch warning of C<< $c->req->param >>'s fuzzy behavior.

r5541@hlagh (orig r10574):  t0m | 2009-06-17 09:03:51 -0700
Back out 10498 and 10097
r5542@hlagh (orig r10575):  jshirley | 2009-06-17 09:18:29 -0700
Adding failing test for uri_for behaviors
r5543@hlagh (orig r10576):  jshirley | 2009-06-17 09:19:53 -0700
Fixing test count
r5544@hlagh (orig r10579):  t0m | 2009-06-17 18:21:17 -0700
Test dinks
r5545@hlagh (orig r10581):  caelum | 2009-06-17 21:13:07 -0700
slight test fix, but test is still probably wrong
r5554@hlagh (orig r10583):  zarquon | 2009-06-18 03:47:36 -0700
attempt to test for the infamous repeating path-uri-escape evil
r5579@hlagh (orig r10594):  t0m | 2009-06-19 13:35:41 -0700
Just initialize a logger which only logs fatal errors, no mock needed
r5580@hlagh (orig r10595):  t0m | 2009-06-19 13:39:19 -0700
Remove Test::MockObject
r5581@hlagh (orig r10596):  t0m | 2009-06-19 13:39:58 -0700
Remove Test::MockObject
r5582@hlagh (orig r10597):  t0m | 2009-06-19 13:41:46 -0700
Remove MockObject
r5583@hlagh (orig r10598):  t0m | 2009-06-19 13:44:15 -0700
1 more MockObject removal
r5584@hlagh (orig r10599):  t0m | 2009-06-19 13:46:45 -0700
Remove MockObject from Makefile.PL
r5596@hlagh (orig r10605):  t0m | 2009-06-20 16:23:19 -0700
Re-add lukes specific regression test from r10498
r5597@hlagh (orig r10606):  t0m | 2009-06-20 16:25:31 -0700
Update test to be TODO, and note this case used to fail on 5.7
r5600@hlagh (orig r10609):  zarquon | 2009-06-20 17:31:39 -0700
this test is not for the regression which you seek
r5670@hlagh (orig r10612):  t0m | 2009-06-22 09:31:09 -0700
Test closures in config in the testapp. Makes everything go bang.
r5671@hlagh (orig r10613):  t0m | 2009-06-22 09:37:26 -0700
Use merge_hashes rather than dclone
r5672@hlagh (orig r10614):  t0m | 2009-06-22 11:06:48 -0700
Fix uri_for_action test by just reverting to as it was in 5.8003 before various lame tests were added and mismerged

Changes
Makefile.PL
TODO
lib/Catalyst.pm
lib/Catalyst/Controller.pm
lib/Catalyst/Dispatcher.pm
lib/Catalyst/Utils.pm
t/aggregate/live_component_controller_action_action.t
t/aggregate/live_component_controller_action_path.t
t/lib/TestApp/Controller/Action/Action.pm
t/lib/TestApp/Controller/Action/Path.pm

diff --git a/Changes b/Changes
index 98c8727..3b28c02 100644 (file)
--- a/Changes
+++ b/Changes
            ensuring child classes don't inherit their parent's config,
            except works correctly with closures.
 
+  New features:
+        -  Use ~ as prefix for plugins or action classes which are located in 
+           MyApp::Plugin / MyApp::Action (mo)
+        -  Controller methods without attributes are now considered actions if 
+           they are specified in config->{action(s)} (mo)
+
 5.80005 2009-06-06 14:40:00
 
   Behaviour changes:
index a1b635a..71898e1 100644 (file)
@@ -34,6 +34,7 @@ requires 'Tree::Simple::Visitor::FindByPath';
 requires 'URI' => '1.35';
 requires 'Text::Balanced'; # core in 5.8.x but mentioned for completeness
 requires 'MRO::Compat';
+requires 'String::RewritePrefix' => '0.004'; # Catalyst::Utils::resolve_namespace
 
 recommends 'B::Hooks::OP::Check::StashChange';
 
diff --git a/TODO b/TODO
index 8c5bc68..6e237a1 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,25 +1,12 @@
-Known Bugs:
+TODO for brach namespace_handling_refactor:
 
-   - Bug ->go or ->visit causes actions which have Args or CaptureArgs called
-     twice when called via ->go or ->visit.
-
-     Test app: http://github.com/bobtfish/catalyst-app-bug-go_chain/tree/master
-
-Compatibility warnings to add:
-
-   - $self->config should warn as config should only ever be called as a
-     class method.
-
-Proposed functionality / feature additions:
-
-    - Log setup needs to be less lame, so Catalyst::Plugin::Log::* can die
-      in a fire. Having $c->log_class would be a good start. kane volunteered
-      to do some of this.
-
-      Simple example: Catalyst::Plugin::Log::Colorful should just be a
-      subclass of Catalyst::Log, no ::Plugin:: needed.
-
-      See also: Catalyst::Plugin::Log::Dispatch and
-      http://github.com/willert/catalyst-plugin-log4perl-simple/tree
+- refactor code in
+  * Catalyst::Dispatcher::get_containers           # No Idea
+  * Catalyst::Dispatcher::dispatch_type            # DONE
 
+  * Catalyst::Controller::_parse_ActionClass_attr  # DONE
+  * Catalyst::Dispatcher::_load_dispatch_types     # DONE
+  * Catalyst::setup_plugins                        # DONE
+  to use the same namespacing method
 
+- Ok, so can you add tests for ->config(actions => { foo => { ActionClass => '+Bar' }});
\ No newline at end of file
index f9ab9c4..063ee32 100644 (file)
@@ -2509,8 +2509,8 @@ the plugin name does not begin with C<Catalyst::Plugin::>.
 
         $class->_plugins( {} ) unless $class->_plugins;
         $plugins ||= [];
-
-        my @plugins = map { s/\A\+// ? $_ : "Catalyst::Plugin::$_" } @$plugins;
+                
+        my @plugins = Catalyst::Utils::resolve_namespace($class . '::Plugin', 'Catalyst::Plugin', @$plugins);
 
         for my $plugin ( reverse @plugins ) {
             Class::MOP::load_class($plugin);
index dd1dca0..45feacb 100644 (file)
@@ -178,13 +178,28 @@ around path_prefix => sub {
 sub get_action_methods {
     my $self = shift;
     my $meta = find_meta($self);
-    confess("Metaclass for " . ref($meta) ." for " . $meta->name
-        . " cannot support register_actions.")
-        unless $meta->can('get_nearest_methods_with_attributes');
+    confess("Metaclass for "
+          . ref($meta) . " for "
+          . $meta->name
+          . " cannot support register_actions." )
+      unless $meta->can('get_nearest_methods_with_attributes');
     my @methods = $meta->get_nearest_methods_with_attributes;
+
+    # actions specified via config are also action_methods
+    push(
+        @methods,
+        map {
+            $meta->get_method($_)
+              || confess( 'Action "' 
+                  . $_
+                  . '" is not available from controller '
+                  . ( ref $self ) )
+          } keys %{ $self->_controller_actions }
+    ) if ( ref $self );
     return @methods;
 }
 
+
 sub register_actions {
     my ( $self, $c ) = @_;
     $self->register_action_methods( $c, $self->get_action_methods );
@@ -199,7 +214,6 @@ sub register_action_methods {
     foreach my $method (@methods) {
         my $name = $method->name;
         my $attributes = $method->attributes;
-        next unless $attributes;
         my $attrs = $self->_parse_attrs( $c, $name, @{ $attributes } );
         if ( $attrs->{Private} && ( keys %$attrs > 1 ) ) {
             $c->log->debug( 'Bad action definition "'
@@ -376,9 +390,8 @@ sub _parse_PathPrefix_attr {
 
 sub _parse_ActionClass_attr {
     my ( $self, $c, $name, $value ) = @_;
-    unless ( $value =~ s/^\+// ) {
-      $value = join('::', $self->_action_class, $value );
-    }
+    my $appname = $self->_application;
+    $value = Catalyst::Utils::resolve_namespace($appname . '::Action', $self->_action_class, $value);
     return ( 'ActionClass', $value );
 }
 
index 3a97c87..88ea7d5 100644 (file)
@@ -640,12 +640,11 @@ sub _load_dispatch_types {
     my ( $self, @types ) = @_;
 
     my @loaded;
-
     # Preload action types
     for my $type (@types) {
-        my $class =
-          ( $type =~ /^\+(.*)$/ ) ? $1 : "Catalyst::DispatchType::${type}";
-
+        # first param is undef because we cannot get the appclass
+        my $class = Catalyst::Utils::resolve_namespace(undef, 'Catalyst::DispatchType', $type);
+        
         eval { Class::MOP::load_class($class) };
         Catalyst::Exception->throw( message => qq/Couldn't load "$class"/ )
           if $@;
@@ -667,10 +666,9 @@ of course it's being used.)
 
 sub dispatch_type {
     my ($self, $name) = @_;
-
-    unless ($name =~ s/^\+//) {
-        $name = "Catalyst::DispatchType::" . $name;
-    }
+    
+    # first param is undef because we cannot get the appclass
+    $name = Catalyst::Utils::resolve_namespace(undef, 'Catalyst::DispatchType', $name);
 
     for (@{ $self->_dispatch_types }) {
         return $_ if ref($_) eq $name;
index f47909d..5bff574 100644 (file)
@@ -9,6 +9,8 @@ use URI;
 use Carp qw/croak/;
 use Cwd;
 
+use String::RewritePrefix;
+
 use namespace::clean;
 
 =head1 NAME
@@ -377,6 +379,28 @@ sub term_width {
     return $_term_width = $width;
 }
 
+
+=head2 resolve_namespace
+
+Method which adds the namespace for plugins and actions.
+
+  __PACKAGE__->setup(qw(MyPlugin));
+  
+  # will load Catalyst::Plugin::MyPlugin
+
+=cut
+
+
+sub resolve_namespace {
+    my $appnamespace = shift;
+    my $namespace = shift;
+    my @classes = @_;
+    return String::RewritePrefix->rewrite(
+        { '' => $namespace.'::', '+' => '', '~' => $appnamespace . '::' }, @classes,
+      );
+}
+
+
 =head1 AUTHORS
 
 Catalyst Contributors, see Catalyst.pm
index ea52e78..1e11b18 100644 (file)
@@ -10,7 +10,7 @@ our $iters;
 
 BEGIN { $iters = $ENV{CAT_BENCH_ITERS} || 1; }
 
-use Test::More tests => 28 * $iters;
+use Test::More tests => 42 * $iters;
 use Catalyst::Test 'TestApp';
 
 if ( $ENV{CAT_BENCHMARK} ) {
@@ -106,5 +106,46 @@ sub run_tests {
             'Content is a serialized Catalyst::Request'
         );
     }
+    
+    {
+        ok( my $response = request('http://localhost/action_action_five'),
+            'Request' );
+        ok( $response->is_success, 'Response Successful 2xx' );
+        is( $response->content_type, 'text/plain', 'Response Content-Type' );
+        is( $response->header('X-Catalyst-Action'),
+            'action_action_five', 'Test Action' );
+        is(
+            $response->header('X-Test-Class'),
+            'TestApp::Controller::Action::Action',
+            'Test Class'
+        );
+        is( $response->header('X-Action'), 'works' );
+        like(
+            $response->content,
+            qr/^bless\( .* 'Catalyst::Request' \)$/s,
+            'Content is a serialized Catalyst::Request'
+        );
+    }
+    
+
+    {
+        ok( my $response = request('http://localhost/action_action_six'),
+            'Request' );
+        ok( $response->is_success, 'Response Successful 2xx' );
+        is( $response->content_type, 'text/plain', 'Response Content-Type' );
+        is( $response->header('X-Catalyst-Action'),
+            'action_action_six', 'Test Action' );
+        is(
+            $response->header('X-Test-Class'),
+            'TestApp::Controller::Action::Action',
+            'Test Class'
+        );
+        is( $response->header('X-TestAppActionTestMyAction'), 'MyAction works' );
+        like(
+            $response->content,
+            qr/^bless\( .* 'Catalyst::Request' \)$/s,
+            'Content is a serialized Catalyst::Request'
+        );
+    }
 
 }
index 338e696..950b4ac 100644 (file)
@@ -10,7 +10,7 @@ our $iters;
 
 BEGIN { $iters = $ENV{CAT_BENCH_ITERS} || 1; }
 
-use Test::More tests => 36*$iters;
+use Test::More tests => 42*$iters;
 use Catalyst::Test 'TestApp';
 
 if ( $ENV{CAT_BENCHMARK} ) {
@@ -142,4 +142,22 @@ sub run_tests {
             'Content is a serialized Catalyst::Request'
         );
     }
+
+    {
+        ok( my $response = request('http://localhost/action/path/six'), 'Request' );
+        ok( $response->is_success, 'Response Successful 2xx' );
+        is( $response->content_type, 'text/plain', 'Response Content-Type' );
+        is( $response->header('X-Catalyst-Action'),
+            'action/path/six', 'Test Action' );
+        is(
+            $response->header('X-Test-Class'),
+            'TestApp::Controller::Action::Path',
+            'Test Class'
+        );
+        like(
+            $response->content,
+            qr/^bless\( .* 'Catalyst::Request' \)$/s,
+            'Content is a serialized Catalyst::Request'
+        );
+    }
 }
index 787bb8d..5049427 100644 (file)
@@ -3,6 +3,8 @@ package TestApp::Controller::Action::Action;
 use strict;
 use base 'TestApp::Controller::Action';
 
+__PACKAGE__->config( actions => { action_action_five => { ActionClass => '+Catalyst::Action::TestBefore' } } );
+
 sub action_action_one : Global : ActionClass('TestBefore') {
     my ( $self, $c ) = @_;
     $c->res->header( 'X-Action', $c->stash->{test} );
@@ -25,4 +27,15 @@ sub action_action_four : Global : MyAction('TestMyAction') {
     $c->forward('TestApp::View::Dump::Request');
 }
 
+sub action_action_five : Global {
+    my ( $self, $c ) = @_;
+    $c->res->header( 'X-Action', $c->stash->{test} );
+    $c->forward('TestApp::View::Dump::Request');
+}
+
+sub action_action_six : Global : ActionClass('~TestMyAction') {
+    my ( $self, $c ) = @_;
+    $c->forward('TestApp::View::Dump::Request');
+}
+
 1;
index 3a93525..18fa71b 100644 (file)
@@ -7,6 +7,7 @@ __PACKAGE__->config(
     actions => {
       'one' => { 'Path' => [ 'a path with spaces' ] },
       'two' => { 'Path' => "åäö" },
+      'six' => { 'Local' => undef },
     },
 );
 
@@ -35,4 +36,9 @@ sub five : Path( "spaces_near_parens_doubleq" ) {
     $c->forward('TestApp::View::Dump::Request');
 }
 
+sub six {
+    my ( $self, $c ) = @_;
+    $c->forward('TestApp::View::Dump::Request');
+}
+
 1;