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;
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?
# Remember to update this in Catalyst::Runtime as well!
-our $VERSION = '5.80005';
+our $VERSION = '5.80007';
{
my $dev_version = $VERSION =~ /_\d{2}$/;
}
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}") } );
}
$caller->setup_home;
}
+sub _application { $_[0] }
+
=head1 NAME
Catalyst - The Elegant MVC Web Application Framework
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.' );
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.' );
like myapp.conf in your applications home directory. See
L<Catalyst::Plugin::ConfigLoader>.
-=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
$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;
( 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);
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);
}
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 ) {
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,
$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);
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
mapped to C</foo/bar>. You can activate case sensitivity with a config
parameter.
- MyApp->config->{case_sensitive} = 1;
+ MyApp->config(case_sensitive => 1);
This causes C<MyApp::C::Foo::Bar> to map to C</Foo/Bar>.
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
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