extended uri_for, added uri_for_action to dispatcher
[catagits/Catalyst-Runtime.git] / lib / Catalyst.pm
index c894fed..8cccb9a 100644 (file)
@@ -3,7 +3,6 @@ package Catalyst;
 use strict;
 use base 'Catalyst::Component';
 use bytes;
-use UNIVERSAL::require;
 use Catalyst::Exception;
 use Catalyst::Log;
 use Catalyst::Request;
@@ -25,6 +24,8 @@ use attributes;
 use utf8;
 use Carp qw/croak/;
 
+BEGIN { require 5.008001; }
+
 __PACKAGE__->mk_accessors(
     qw/counter request response state action stack namespace stats/
 );
@@ -49,9 +50,6 @@ our $DETACH    = "catalyst_detach\n";
 
 require Module::Pluggable::Fast;
 
-# Helper script generation
-our $CATALYST_SCRIPT_GEN = 27;
-
 __PACKAGE__->mk_classdata($_)
   for qw/components arguments dispatcher engine log dispatcher_class
   engine_class context_class request_class response_class setup_finished/;
@@ -104,7 +102,7 @@ Catalyst - The Elegant MVC Web Application Framework
     ### in lib/MyApp.pm
     use Catalyst qw/-Debug/; # include plugins here as well
     
-       ### In libMyApp/Controller/Root.pm (autocreated)
+       ### In lib/MyApp/Controller/Root.pm (autocreated)
     sub foo : Global { # called for /foo, /foo/1, /foo/1/2, etc.
         my ( $self, $c, @args ) = @_; # args are qw/1 2/ for /foo/1/2
         $c->stash->{template} = 'foo.tt'; # set the template
@@ -202,7 +200,9 @@ The following flags are supported:
 
 =head2 -Debug
 
-Enables debug output.
+Enables debug output. You can also force this setting from the system
+environment with CATALYST_DEBUG or <MYAPP>_DEBUG. The environment settings
+override the app, with <MYAPP>_DEBUG having highest priority.
 
 =head2 -Engine
 
@@ -319,8 +319,9 @@ sub stash {
     my $c = shift;
     if (@_) {
         my $stash = @_ > 1 ? {@_} : $_[0];
-        while ( my ( $key, $val ) = each %$stash ) {
-            $c->{stash}->{$key} = $val;
+       croak('stash takes a hash or hashref') unless ref $stash;
+        foreach my $key ( keys %$stash ) {
+            $c->{stash}->{$key} = $stash->{$key};
         }
     }
     return $c->{stash};
@@ -488,7 +489,7 @@ Gets a L<Catalyst::Model> instance by name.
     $c->model('Foo')->do_stuff;
 
 If the name is omitted, it will look for a config setting 'default_model',
-or check if there is only one model, and forward to it if that's the case.
+or check if there is only one view, and return it if that's the case.
 
 =cut
 
@@ -645,6 +646,9 @@ L<Catalyst::Log> man page.
 
 Overload to enable debug messages (same as -Debug option).
 
+Note that this is a static method, not an accessor and should be overloaded
+by declaring "sub debug { 1 }" in your MyApp.pm, not by calling $c->debug(1).
+
 =cut
 
 sub debug { 0 }
@@ -772,8 +776,9 @@ sub setup {
         }
     }
 
-    $class->log->warn(
-        <<"EOF") if ( $ENV{CATALYST_SCRIPT_GEN} && ( $ENV{CATALYST_SCRIPT_GEN} < $Catalyst::CATALYST_SCRIPT_GEN ) );
+    eval { require Catalyst::Devel; };
+    if( !$@ && $ENV{CATALYST_SCRIPT_GEN} && ( $ENV{CATALYST_SCRIPT_GEN} < $Catalyst::Devel::CATALYST_SCRIPT_GEN ) ) {
+        $class->log->warn(<<"EOF");
 You are running an old script!
 
   Please update by running (this will overwrite existing files):
@@ -782,7 +787,8 @@ You are running an old script!
   or (this will not overwrite existing files):
     catalyst.pl -scripts $class
 EOF
-
+    }
+    
     if ( $class->debug ) {
 
         my @plugins = ();
@@ -859,6 +865,11 @@ end of the path.  If the last argument to uri_for is a hash reference,
 it is assumed to contain GET parameter key/value pairs, which will be
 appended to the URI in standard fashion.
 
+Instead of $path, you can also optionally pass a $action object which will
+be resolved to a path using $c->dispatcher->uri_for_action; if the first
+element of @args is an arrayref it is treated as a list of captures to be
+passed to uri_for_action.
+
 =cut
 
 sub uri_for {
@@ -869,6 +880,14 @@ sub uri_for {
     $basepath .= '/';
     my $namespace = $c->namespace || '';
 
+    if ( Scalar::Util::blessed($path) ) { # action object
+        my $captures = ( scalar @args && ref $args[0] eq 'ARRAY'
+                         ? shift(@args)
+                         : [] );
+        $path = $c->dispatcher->uri_for_action($path, $captures);
+        return undef unless defined($path);
+    }
+
     # massage namespace, empty if absolute path
     $namespace =~ s/^\/// if $namespace;
     $namespace .= '/' if $namespace;
@@ -1868,11 +1887,8 @@ sub setup_dispatcher {
         $dispatcher = $class->dispatcher_class;
     }
 
-    $dispatcher->require;
-
-    if ($@) {
-        Catalyst::Exception->throw(
-            message => qq/Couldn't load dispatcher "$dispatcher", "$@"/ );
+    unless (Class::Inspector->loaded($dispatcher)) {
+        require Class::Inspector->filename($dispatcher);
     }
 
     # dispatcher instance
@@ -1963,12 +1979,8 @@ sub setup_engine {
         $engine = $class->engine_class;
     }
 
-    $engine->require;
-
-    if ($@) {
-        Catalyst::Exception->throw( message =>
-qq/Couldn't load engine "$engine" (maybe you forgot to install it?), "$@"/
-        );
+    unless (Class::Inspector->loaded($engine)) {
+        require Class::Inspector->filename($engine);
     }
 
     # check for old engines that are no longer compatible
@@ -2096,12 +2108,8 @@ the plugin name does not begin with C<Catalyst::Plugin::>.
         my ( $proto, $plugin, $instant ) = @_;
         my $class = ref $proto || $proto;
 
-        $plugin->require;
-
-        if ( my $error = $@ ) {
-            my $type = $instant ? "instant " : '';
-            Catalyst::Exception->throw(
-                message => qq/Couldn't load ${type}plugin "$plugin", $error/ );
+        unless (Class::Inspector->loaded($plugin)) {
+            require Class::Inspector->filename($plugin);
         }
 
         $proto->_plugins->{$plugin} = 1;