X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Runtime.git;a=blobdiff_plain;f=lib%2FCatalyst.pm;h=981b20fb339ea4c68f0ae81f5e360af0add7159b;hp=179c7ac3e0b81b7af0aec8c343e82f4be8985759;hb=97b58e1798479e2df8d050e72e87453f6ad81668;hpb=9e7673af3a03f61edd17142d1ebfd415119e48be diff --git a/lib/Catalyst.pm b/lib/Catalyst.pm index 179c7ac..981b20f 100644 --- a/lib/Catalyst.pm +++ b/lib/Catalyst.pm @@ -21,7 +21,6 @@ use Scalar::Util qw/weaken/; use Tree::Simple qw/use_weak_refs/; use Tree::Simple::Visitor::FindByUID; use attributes; -use YAML (); __PACKAGE__->mk_accessors( qw/counter request response state action stack namespace/ @@ -48,18 +47,18 @@ our $DETACH = "catalyst_detach\n"; require Module::Pluggable::Fast; # Helper script generation -our $CATALYST_SCRIPT_GEN = 25; +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/; + engine_class context_class request_class response_class setup_finished/; __PACKAGE__->dispatcher_class('Catalyst::Dispatcher'); __PACKAGE__->engine_class('Catalyst::Engine::CGI'); __PACKAGE__->request_class('Catalyst::Request'); __PACKAGE__->response_class('Catalyst::Response'); -our $VERSION = '5.62'; +our $VERSION = '5.66'; sub import { my ( $class, @arguments ) = @_; @@ -179,6 +178,14 @@ C. use Catalyst qw/My::Module/; +If your plugin starts with a name other than C, you can +fully qualify the name by using a unary plus: + + use Catalyst qw/ + My::Module + +Fully::Qualified::Plugin::Name + /; + Special flags like C<-Debug> and C<-Engine> can also be specified as arguments when Catalyst is loaded: @@ -246,7 +253,10 @@ in an arrayref. The action will receive the arguments in C<@_> and C<$c-Ereq-Eargs>. Upon returning from the function, C<$c-Ereq-Eargs> will be restored to the previous values. - $c->forward('/foo'); +Any data Ced from the action forwarded to, will be returned by the +call to forward. + + my $foodata = $c->forward('/foo'); $c->forward('index'); $c->forward(qw/MyApp::Model::CDBI::Foo do_stuff/); $c->forward('MyApp::View::TT'); @@ -369,7 +379,7 @@ sub component { if ( exists $c->components->{$try} ) { my $comp = $c->components->{$try}; - if ( ref $comp && $comp->can('ACCEPT_CONTEXT') ) { + if ( eval { $comp->can('ACCEPT_CONTEXT'); } ) { return $comp->ACCEPT_CONTEXT($c); } else { return $comp } @@ -443,7 +453,7 @@ sub view { Returns or takes a hashref containing the application's configuration. - __PACKAGE__->config({ db => 'dsn:SQLite:foo.db' }); + __PACKAGE__->config( { db => 'dsn:SQLite:foo.db' } ); You can also use a L config file like myapp.yml in your applications home directory. @@ -451,6 +461,17 @@ applications home directory. --- db: dsn:SQLite:foo.db +=cut + +sub config { + my $c = shift; + + $c->log->warn("Setting config after setup has been run is not a good idea.") + if ( @_ and $c->setup_finished ); + + $c->NEXT::config(@_); +} + =head2 $c->debug Overload to enable debug messages (same as -Debug option). @@ -521,12 +542,7 @@ loads and instantiates the given class. sub plugin { my ( $class, $name, $plugin, @args ) = @_; - $plugin->require; - - if ( my $error = $UNIVERSAL::require::ERROR ) { - Catalyst::Exception->throw( - message => qq/Couldn't load instant plugin "$plugin", "$error"/ ); - } + $class->_register_plugin( $plugin, 1 ); eval { $plugin->import }; $class->mk_classdata($name); @@ -587,15 +603,6 @@ sub setup { $class->setup_home( delete $flags->{home} ); - # YAML config support - my $confpath = $class->config->{file} - || $class->path_to( - ( Catalyst::Utils::appprefix( ref $class || $class ) . '.yml' ) ); - my $conf = {}; - $conf = YAML::LoadFile($confpath) if -f $confpath; - my $oldconf = $class->config; - $class->config( { %$oldconf, %$conf } ); - $class->setup_log( delete $flags->{log} ); $class->setup_plugins( delete $flags->{plugins} ); $class->setup_dispatcher( delete $flags->{dispatcher} ); @@ -685,6 +692,8 @@ EOF $class->log->info("$name powered by Catalyst $Catalyst::VERSION"); } $class->log->_flush() if $class->log->can('_flush'); + + $class->setup_finished(1); } =head2 $c->uri_for( $path, [ @args ] ) @@ -692,7 +701,9 @@ EOF Merges path with C<$c-Erequest-Ebase> for absolute uri's and with C<$c-Enamespace> for relative uri's, then returns a normalized L object. If any args are passed, they are added at the -end of the path. +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. =cut @@ -711,12 +722,16 @@ sub uri_for { $namespace = '' if $path =~ /^\//; $path =~ s/^\///; + my $params = + ( scalar @args && ref $args[$#args] eq 'HASH' ? pop @args : {} ); + # join args with '/', or a blank string my $args = ( scalar @args ? '/' . join( '/', @args ) : '' ); $args =~ s/^\/// unless $path; my $res = URI->new_abs( URI->new_abs( "$path$args", "$basepath$namespace" ), $base ) ->canonical; + $res->query_form(%$params); $res; } @@ -827,6 +842,7 @@ sub welcome_message {

If you want to jump right into web development with Catalyst you might want to check out the documentation.

perldoc Catalyst::Manual::Intro
+perldoc Catalyst::Manual::Tutorial
 perldoc Catalyst::Manual

What to do next?

Next it's time to write an actual application. Use the @@ -923,7 +939,7 @@ via $c->error. sub execute { my ( $c, $class, $code ) = @_; - $class = $c->components->{$class} || $class; + $class = $c->component($class) || $class; $c->state(0); if ( $c->debug ) { @@ -1576,7 +1592,7 @@ sub setup_components { } Catalyst::Exception->throw( message => -qq/Couldn't instantiate component "$component", "new() didn't return a object"/ +qq/Couldn't instantiate component "$component", "COMPONENT() didn't return a object"/ ) unless ref $instance; return $instance; @@ -1831,25 +1847,64 @@ Sets up plugins. =cut -sub setup_plugins { - my ( $class, $plugins ) = @_; +=head2 $c->registered_plugins - $plugins ||= []; - for my $plugin ( reverse @$plugins ) { +Returns a sorted list of the plugins which have either been stated in the +import list or which have been added via C<< MyApp->plugin(@args); >>. - $plugin = "Catalyst::Plugin::$plugin"; +If passed a given plugin name, it will report a boolean value indicating +whether or not that plugin is loaded. A fully qualified name is required if +the plugin name does not begin with C. + + if ($c->registered_plugins('Some::Plugin')) { + ... + } + +=cut + +{ + my %PLUGINS; + + sub registered_plugins { + my $proto = shift; + return sort keys %PLUGINS unless @_; + my $plugin = shift; + return 1 if exists $PLUGINS{$plugin}; + return exists $PLUGINS{"Catalyst::Plugin::$plugin"}; + } + + sub _register_plugin { + my ( $proto, $plugin, $instant ) = @_; + my $class = ref $proto || $proto; $plugin->require; - if ($@) { + if ( my $error = $@ ) { + my $type = $instant ? "instant " : ''; Catalyst::Exception->throw( - message => qq/Couldn't load plugin "$plugin", "$@"/ ); + message => qq/Couldn't load ${type}plugin "$plugin", $error/ ); } - { + $PLUGINS{$plugin} = 1; + unless ($instant) { no strict 'refs'; unshift @{"$class\::ISA"}, $plugin; } + return $class; + } + + sub setup_plugins { + my ( $class, $plugins ) = @_; + + $plugins ||= []; + for my $plugin ( reverse @$plugins ) { + + unless ( $plugin =~ s/\A\+// ) { + $plugin = "Catalyst::Plugin::$plugin"; + } + + $class->_register_plugin($plugin); + } } }