X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Runtime.git;a=blobdiff_plain;f=lib%2FCatalyst.pm;h=56ee510c4d59b1c5d30fe230578f3627b08a2ea8;hp=5b1ae677b10c95e48d68473fc11c3f70e209c4ed;hb=636ec0c68dab3bc456963f7e94970827b39541b8;hpb=df861f8e6409c9516f00cb6b4fd6fc94a83fc8f5 diff --git a/lib/Catalyst.pm b/lib/Catalyst.pm index 5b1ae67..56ee510 100644 --- a/lib/Catalyst.pm +++ b/lib/Catalyst.pm @@ -7,6 +7,8 @@ use Moose::Util qw/find_meta/; use bytes; use B::Hooks::EndOfScope (); use Catalyst::Exception; +use Catalyst::Exception::Detach; +use Catalyst::Exception::Go; use Catalyst::Log; use Catalyst::Request; use Catalyst::Request::Upload; @@ -58,8 +60,8 @@ sub finalize_output { shift->finalize_body(@_) }; our $COUNT = 1; our $START = time; our $RECURSION = 1000; -our $DETACH = "catalyst_detach\n"; -our $GO = "catalyst_go\n"; +our $DETACH = Catalyst::Exception::Detach->new; +our $GO = Catalyst::Exception::Go->new; #I imagine that very few of these really need to be class variables. if any. #maybe we should just make them attributes with a default? @@ -76,7 +78,7 @@ __PACKAGE__->stats_class('Catalyst::Stats'); # Remember to update this in Catalyst::Runtime as well! -our $VERSION = '5.80003'; +our $VERSION = '5.80007'; { my $dev_version = $VERSION =~ /_\d{2}$/; @@ -101,12 +103,13 @@ sub import { } my $meta = Moose::Meta::Class->initialize($caller); - #Moose->import({ into => $caller }); #do we want to do this? - unless ( $caller->isa('Catalyst') ) { my @superclasses = ($meta->superclasses, $class, 'Catalyst::Controller'); $meta->superclasses(@superclasses); } + # Avoid possible C3 issues if 'Moose::Object' is already on RHS of MyApp + $meta->superclasses(grep { $_ ne 'Moose::Object' } $meta->superclasses); + unless( $meta->has_method('meta') ){ $meta->add_method(meta => sub { Moose::Meta::Class->initialize("${caller}") } ); } @@ -115,6 +118,8 @@ sub import { $caller->setup_home; } +sub _application { $_[0] } + =head1 NAME Catalyst - The Elegant MVC Web Application Framework @@ -493,8 +498,13 @@ sub clear_errors { $c->error(0); } -# search components given a name and some prefixes sub _comp_search_prefixes { + my $c = shift; + return map $c->components->{ $_ }, $c->_comp_names_search_prefixes(@_); +} + +# search components given a name and some prefixes +sub _comp_names_search_prefixes { my ( $c, $name, @prefixes ) = @_; my $appclass = ref $c || $c; my $filter = "^${appclass}::(" . join( '|', @prefixes ) . ')::'; @@ -510,18 +520,18 @@ sub _comp_search_prefixes { my $query = ref $name ? $name : qr/^$name$/i; my @result = grep { $eligible{$_} =~ m{$query} } keys %eligible; - return map { $c->components->{ $_ } } @result if @result; + return @result if @result; # if we were given a regexp to search against, we're done. return if ref $name; # regexp fallback $query = qr/$name/i; - @result = map { $c->components->{ $_ } } grep { $eligible{ $_ } =~ m{$query} } keys %eligible; + @result = grep { $eligible{ $_ } =~ m{$query} } keys %eligible; # no results? try against full names if( !@result ) { - @result = map { $c->components->{ $_ } } grep { m{$query} } keys %eligible; + @result = grep { m{$query} } keys %eligible; } # don't warn if we didn't find any results, it just might not exist @@ -558,7 +568,9 @@ sub _comp_names { my $filter = "^${appclass}::(" . join( '|', @prefixes ) . ')::'; - my @names = map { s{$filter}{}; $_; } $c->_comp_search_prefixes( undef, @prefixes ); + my @names = map { s{$filter}{}; $_; } + $c->_comp_names_search_prefixes( undef, @prefixes ); + return @names; } @@ -647,7 +659,7 @@ sub model { if( $rest ) { $c->log->warn( Carp::shortmess('Calling $c->model() will return a random model unless you specify one of:') ); - $c->log->warn( '* $c->config->{default_model} # the name of the default model to use' ); + $c->log->warn( '* $c->config(default_model => "the name of the default model to use")' ); $c->log->warn( '* $c->stash->{current_model} # the name of the model to use for this request' ); $c->log->warn( '* $c->stash->{current_model_instance} # the instance of the model to use for this request' ); $c->log->warn( 'NB: in version 5.81, the "random" behavior will not work at all.' ); @@ -700,7 +712,7 @@ sub view { if( $rest ) { $c->log->warn( 'Calling $c->view() will return a random view unless you specify one of:' ); - $c->log->warn( '* $c->config->{default_view} # the name of the default view to use' ); + $c->log->warn( '* $c->config(default_view => "the name of the default view to use")' ); $c->log->warn( '* $c->stash->{current_view} # the name of the view to use for this request' ); $c->log->warn( '* $c->stash->{current_view_instance} # the instance of the view to use for this request' ); $c->log->warn( 'NB: in version 5.81, the "random" behavior will not work at all.' ); @@ -810,7 +822,7 @@ You can also use a C, C or C config file like myapp.conf in your applications home directory. See L. -=head3 Cascading configuration. +=head3 Cascading configuration The config method is present on all Catalyst components, and configuration will be merged when an application is started. Configuration loaded with @@ -904,7 +916,9 @@ Returns the engine instance. See L. =head2 $c->path_to(@path) Merges C<@path> with C<< $c->config->{home} >> and returns a -L object. +L object. Note you can usually use this object as +a filename, but sometimes you will have to explicitly stringify it +yourself by calling the C<<->stringify>> method. For example: @@ -1095,21 +1109,25 @@ EOF $class->log->_flush() if $class->log->can('_flush'); # Make sure that the application class becomes immutable at this point, - # which ensures that it gets an inlined constructor. This means that it - # works even if the user has added a plugin which contains a new method. - # Note however that we have to do the work on scope end, so that method - # modifiers work correctly in MyApp (as you have to call setup _before_ - # applying modifiers). B::Hooks::EndOfScope::on_scope_end { return if $@; my $meta = Class::MOP::get_metaclass_by_name($class); - if ( $meta->is_immutable && ! { $meta->immutable_options }->{inline_constructor} ) { + if ( + $meta->is_immutable + && ! { $meta->immutable_options }->{replace_constructor} + && ( + $class->isa('Class::Accessor::Fast') + || $class->isa('Class::Accessor') + ) + ) { warn "You made your application class ($class) immutable, " - . "but did not inline the constructor.\n" - . "This will break catalyst, please pass " - . "(replace_constructor => 1) when making your class immutable.\n"; + . "but did not inline the\nconstructor. " + . "This will break catalyst, as your app \@ISA " + . "Class::Accessor(::Fast)?\nPlease pass " + . "(replace_constructor => 1)\nwhen making your class immutable.\n"; } - $meta->make_immutable(replace_constructor => 1) unless $meta->is_immutable; + $meta->make_immutable(replace_constructor => 1) + unless $meta->is_immutable; }; $class->setup_finalize; @@ -1161,7 +1179,7 @@ using C<< $c->req->captures >>. $c->uri_for($c->action, $c->req->captures); # For the Foo action in the Bar controller - $c->uri_for($c->controller->('Bar')->action_for('Foo'), $c->req->captures); + $c->uri_for($c->controller('Bar')->action_for('Foo'), $c->req->captures); =back @@ -1190,7 +1208,7 @@ sub uri_for { ( scalar @args && ref $args[$#args] eq 'HASH' ? pop @args : {} ); carp "uri_for called with undef argument" if grep { ! defined $_ } @args; - s/([^A-Za-z0-9\-_.!~*'()])/$URI::Escape::escapes{$1}/go for @args; + s/([^$URI::uric])/$URI::Escape::escapes{$1}/go for @args; unshift(@args, $path); @@ -1221,12 +1239,12 @@ sub uri_for { my $key = $_; $val = '' unless defined $val; (map { - $_ = "$_"; - utf8::encode( $_ ) if utf8::is_utf8($_); + my $param = "$_"; + utf8::encode( $param ) if utf8::is_utf8($param); # using the URI::Escape pattern here so utf8 chars survive - s/([^A-Za-z0-9\-_.!~*'()])/$URI::Escape::escapes{$1}/go; - s/ /+/g; - "${key}=$_"; } ( ref $val eq 'ARRAY' ? @$val : $val )); + $param =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go; + $param =~ s/ /+/g; + "${key}=$param"; } ( ref $val eq 'ARRAY' ? @$val : $val )); } @keys); } @@ -1500,11 +1518,11 @@ sub execute { my $last = pop( @{ $c->stack } ); if ( my $error = $@ ) { - if ( !ref($error) and $error eq $DETACH ) { - die $DETACH if($c->depth > 1); + if ( blessed($error) and $error->isa('Catalyst::Exception::Detach') ) { + $error->rethrow if $c->depth > 1; } - elsif ( !ref($error) and $error eq $GO ) { - die $GO if($c->depth > 0); + elsif ( blessed($error) and $error->isa('Catalyst::Exception::Go') ) { + $error->rethrow if $c->depth > 0; } else { unless ( ref $error ) { @@ -1588,25 +1606,6 @@ sub _stats_finish_execute { $c->stats->profile( end => $info ); } -=head2 $c->_localize_fields( sub { }, \%keys ); - -=cut - -#Why does this exist? This is no longer safe and WILL NOT WORK. -# it doesnt seem to be used anywhere. can we remove it? -sub _localize_fields { - my ( $c, $localized, $code ) = ( @_ ); - - my $request = delete $localized->{request} || {}; - my $response = delete $localized->{response} || {}; - - local @{ $c }{ keys %$localized } = values %$localized; - local @{ $c->request }{ keys %$request } = values %$request; - local @{ $c->response }{ keys %$response } = values %$response; - - $code->(); -} - =head2 $c->finalize Finalizes the request. @@ -2072,7 +2071,7 @@ Reads a chunk of data from the request body. This method is designed to be used in a while loop, reading C<$maxlength> bytes on every call. C<$maxlength> defaults to the size of the request if not specified. -You have to set C<< MyApp->config->{parse_on_demand} >> to use this +You have to set C<< MyApp->config(parse_on_demand => 1) >> to use this directly. Warning: If you use read(), Catalyst will not process the body, @@ -2501,11 +2500,10 @@ the plugin name does not begin with C. $class->_plugins( {} ) unless $class->_plugins; $plugins ||= []; - my @plugins = map { s/\A\+// ? $_ : "Catalyst::Plugin::$_" } @$plugins; - - Class::MOP::load_class($_) for @plugins; - + my @plugins = Catalyst::Utils::resolve_namespace($class . '::Plugin', 'Catalyst::Plugin', @$plugins); + for my $plugin ( reverse @plugins ) { + Class::MOP::load_class($plugin); my $meta = find_meta($plugin); next if $meta && $meta->isa('Moose::Meta::Role'); @@ -2517,7 +2515,7 @@ the plugin name does not begin with C. grep { $_ && blessed($_) && $_->isa('Moose::Meta::Role') } map { find_meta($_) } @plugins; - + Moose::Util::apply_all_roles( $class => @roles ) if @roles; @@ -2579,7 +2577,7 @@ Catalyst uses internal actions like C<_DISPATCH>, C<_BEGIN>, C<_AUTO>, C<_ACTION>, and C<_END>. These are by default not shown in the private action table, but you can make them visible with a config parameter. - MyApp->config->{show_internal_actions} = 1; + MyApp->config(show_internal_actions => 1); =head1 CASE SENSITIVITY @@ -2587,7 +2585,7 @@ By default Catalyst is not case sensitive, so C is mapped to C. You can activate case sensitivity with a config parameter. - MyApp->config->{case_sensitive} = 1; + MyApp->config(case_sensitive => 1); This causes C to map to C. @@ -2597,7 +2595,7 @@ The request body is usually parsed at the beginning of a request, but if you want to handle input yourself, you can enable on-demand parsing with a config parameter. - MyApp->config->{parse_on_demand} = 1; + MyApp->config(parse_on_demand => 1); =head1 PROXY SUPPORT @@ -2625,11 +2623,11 @@ frontend proxy server(s) on different machines, you will need to set a configuration option to tell Catalyst to read the proxied data from the headers. - MyApp->config->{using_frontend_proxy} = 1; + MyApp->config(using_frontend_proxy => 1); If you do not wish to use the proxy support at all, you may set: - MyApp->config->{ignore_frontend_proxy} = 1; + MyApp->config(ignore_frontend_proxy => 1); =head1 THREAD SAFETY @@ -2666,7 +2664,7 @@ Wiki: =head2 L - The Catalyst Manual -=head2 L, L - Base classes for components +=head2 L, L - Base classes for components =head2 L - Core engine @@ -2712,6 +2710,8 @@ dkubb: Dan Kubb Drew Taylor +dwc: Daniel Westermann-Clark + esskar: Sascha Kiefer fireartist: Carl Franks @@ -2726,6 +2726,8 @@ ilmari: Dagfinn Ilmari Mannsåker jcamacho: Juan Camacho +jester: Jesse Sheidlower + jhannah: Jay Hannah Jody Belka @@ -2764,8 +2766,6 @@ random: Roland Lammel sky: Arthur Bergman -the_jester: Jesse Sheidlower - t0m: Tomas Doran Ulf Edvinsson @@ -2774,7 +2774,7 @@ willert: Sebastian Willert =head1 LICENSE -This library is free software, you can redistribute it and/or modify it under +This library is free software. You can redistribute it and/or modify it under the same terms as Perl itself. =cut