language: perl
sudo: false
perl:
+ - "5.24"
+ - "5.22"
- "5.20"
- "5.18"
- "5.16"
- cpanm --test-only --metacpan Catalyst::Component::InstancePerContext
- cpanm --test-only --metacpan Catalyst::Plugin::Session
- cpanm --test-only --metacpan Catalyst::Plugin::Session::State::Cookie
- - cpanm --test-only --metacpan Catalyst::Plugin::Static::Simple
+ - cpanm --test-only --verbose --metacpan Catalyst::Plugin::Static::Simple
- cpanm --test-only --metacpan Catalyst::Plugin::ConfigLoader
- cpanm --test-only --metacpan Catalyst::Plugin::ConfigLoader
- cpanm --test-only --metacpan Catalyst::Authentication::Credential::HTTP
# This file documents the revision history for Perl extension Catalyst.
+5.90115 - 2017-05-01
+ - fixes for silent bad behavior in Catalyst::ScriptRole and 'ensure_class_loaded'
+ (hobbs++)
+ - do not require MXRWO if Moose is new enough to have cored it (ether++)
+ - documentation improvements (ether++)
+ - Encoding documentation improvements (colinnewell++)
+
+5.90114 - 2016-12-19
+ - Fixed regression introduced in the last version (5.90113) which caused
+ application to hang when the action private name contained a string
+ like 'foo/bar..html'. If you are running 5.90113 you should consider this
+ a required update.
+ - Tweaked travis CI script.
+
+5.90113 - 2016-12-15
+ - Fixed issue with $controller->action_for when targeting an action in
+ a namespace nested inside the current controller and the current controller
+ is a 'root' controller.
+ - Enhanced $controller->action_for so that you can reference the 'parent'
+ controller via relative path (eg ->action_for('../foo')).
+ - Backcompat fix for people that made the mistake of doing $c->{stash}
+ - Sort controllers in setup_actions so cross-controller precedence is
+ consistent.
+
5.90112 - 2016-07-25
- Spelling fixes from Debian group.
- Fixed regression introduced in last release that caused the code to crap out
requires 'Data::OptList';
requires 'Moose' => '1.03';
requires 'MooseX::MethodAttributes::Role::AttrContainer::Inheritable' => '0.24';
-requires 'MooseX::Role::WithOverloading' => '0.09';
+requires 'MooseX::Role::WithOverloading' => '0.09' unless can_use('Moose', '2.1300');
requires 'Carp' => '1.25';
requires 'Class::C3::Adopt::NEXT' => '0.07';
requires 'CGI::Simple::Cookie' => '1.109';
'license', => 'http://dev.perl.org/licenses/',
'homepage', => 'http://dev.catalyst.perl.org/',
# r/w: catagits@git.shadowcat.co.uk:Catalyst-Runtime.git
+ # web: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits/Catalyst-Runtime.git;a=summary
'repository', => 'git://git.shadowcat.co.uk/catagits/Catalyst-Runtime.git',
);
use Plack::Util;
use Class::Load 'load_class';
use Encode 2.21 'decode_utf8', 'encode_utf8';
+use Scalar::Util;
BEGIN { require 5.008003; }
__PACKAGE__->_encode_check(Encode::FB_CROAK | Encode::LEAVE_SRC);
# Remember to update this in Catalyst::Runtime as well!
-our $VERSION = '5.90112';
+our $VERSION = '5.90114';
$VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
sub import {
and access it from the stash.
-Keep in mind that the C<end> method used is that of the caller action. So a C<$c-E<gt>detach> inside a forwarded action would run the C<end> method from the original action requested.
+Keep in mind that the C<end> method used is that of the caller action. So a C<< $c->detach >> inside a forwarded action would run the C<end> method from the original action requested.
=cut
(defined($res->body)) and
(ref(\$res->body) eq 'SCALAR')
) {
+ # if you are finding yourself here and your body is already encoded correctly
+ # and you want to turn this off, use $c->clear_encoding to prevent encoding
+ # at this step, or set encoding to undef in the config to do so for the whole
+ # application. See the ENCODING documentaiton for better notes.
$c->res->body( $c->encoding->encode( $c->res->body, $c->_encode_check ) );
# Set the charset if necessary. This might be a bit bonkers since encodable response
};
$c->log_request;
+ $c->{stash} = $c->stash;
+ Scalar::Util::weaken($c->{stash});
return $c;
}
This is recommended for temporary backwards compatibility only.
+To turn it off for a single request use the L<clear_encoding>
+method to turn off encoding for this request. This can be useful
+when you are setting the body to be an arbitrary block of bytes,
+especially if that block happens to be a block of UTF8 text.
+
Encoding is automatically applied when the content-type is set to
a type that can be encoded. Currently we encode when the content type
matches the following regular expression:
Andrew Bramble
-Andrew Ford E<lt>A.Ford@ford-mason.co.ukE<gt>
+Andrew Ford <A.Ford@ford-mason.co.uk>
Andrew Ruthven
davewood: David Schmidt <davewood@cpan.org>
-David Kamholz E<lt>dkamholz@cpan.orgE<gt>
+David Kamholz <dkamholz@cpan.org>
David Naughton, C<naughton@umn.edu>
=head1 AUTHOR
-Florian Ragwitz E<lt>rafl@debian.orgE<gt>
+Florian Ragwitz <rafl@debian.org>
=end stopwords
From L<Catalyst::Component::ApplicationAttribute>, stashes the application
instance as $self->_application.
-=head2 $self->action_for('name')
+=head2 $self->action_for($action_name)
-Returns the Catalyst::Action object (if any) for a given method name
-in this component.
+Returns the Catalyst::Action object (if any) for a given action in this
+controller or relative to it. You may refer to actions in controllers
+nested under the current controllers namespace, or in controllers 'up'
+from the current controller namespace. For example:
+
+ package MyApp::Controller::One::Two;
+ use base 'Catalyst::Controller';
+
+ sub foo :Local {
+ my ($self, $c) = @_;
+ $self->action_for('foo'); # action 'foo' in Controller 'One::Two'
+ $self->action_for('three/bar'); # action 'bar' in Controller 'One::Two::Three'
+ $self->action_for('../boo'); # action 'boo' in Controller 'One'
+ }
+
+This returns 'undef' if there is no action matching the requested action
+name (after any path normalization) so you should check for this as needed.
=head2 $self->action_namespace($c)
its arguments. If it doesn't expect any, just specify
C<:CaptureArgs(0)>. The captures get passed to the action's C<@_> right
after the context, but you can also find them as array references in
-C<$c-E<gt>request-E<gt>captures-E<gt>[$level]>. The C<$level> is the
+C<< $c->request->captures->[$level] >>. The C<$level> is the
level of the action in the chain that captured the parts of the path.
An action that is part of a chain (that is, one that has a C<:Chained>
Just as with C<:CaptureArgs>, the arguments get passed to the action in
C<@_> after the context object. They can also be reached through
-C<$c-E<gt>request-E<gt>arguments>.
+C<< $c->request->arguments >>.
You should see 'Args' in L<Catalyst::Controller> for more details on using
type constraints in your Args declarations.
if ( $c->debug && @args );
}
-=head2 $self->get_action( $action, $namespace )
+=head2 $self->get_action( $action_name, $namespace )
-returns a named action from a given namespace.
+returns a named action from a given namespace. C<$action_name>
+may be a relative path on that C<$namespace> such as
+
+ $self->get_action('../bar', 'foo/baz');
+
+In which case we look for the action at 'foo/bar'.
=cut
$namespace = join( "/", grep { length } split '/', ( defined $namespace ? $namespace : "" ) );
- return $self->_action_hash->{"${namespace}/${name}"};
+ return $self->get_action_by_path("${namespace}/${name}");
}
=head2 $self->get_action_by_path( $path );
Returns the named action by its full private path.
+This method performs some normalization on C<$path> so that if
+it includes '..' it will do the right thing (for example if
+C<$path> is '/foo/../bar' that is normalized to '/bar'.
+
=cut
sub get_action_by_path {
my ( $self, $path ) = @_;
+ $path =~s/[^\/]+\/\.\.\/// while $path=~m/[^\/]+\/\.\.\//;
$path =~ s/^\///;
$path = "/$path" unless $path =~ /\//;
$self->_action_hash->{$path};
$self->_load_dispatch_types( @{ $self->preload_dispatch_types } );
@{ $self->_registered_dispatch_types }{@classes} = (1) x @classes;
- foreach my $comp ( values %{ $c->components } ) {
+ foreach my $comp ( map @{$_}{sort keys %$_}, $c->components ) {
$comp = $comp->() if ref($comp) eq 'CODE';
$comp->register_actions($c) if $comp->can('register_actions');
}
package Catalyst::Exception::Basic;
-use MooseX::Role::WithOverloading;
+use Moose::Role;
+use if !eval { require Moose; Moose->VERSION('2.1300') },
+ 'MooseX::Role::WithOverloading';
use Carp;
use namespace::clean -except => 'meta';
package Catalyst::Exception::Interface;
-use MooseX::Role::WithOverloading;
+use Moose::Role;
+use if !eval { require Moose; Moose->VERSION('2.1300') },
+ 'MooseX::Role::WithOverloading';
use namespace::clean -except => 'meta';
use overload
# Remember to update this in Catalyst as well!
-our $VERSION = '5.90112';
+our $VERSION = '5.90114';
$VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
=head1 NAME
use MooseX::Getopt;
use Catalyst::EngineLoader;
use Moose::Util::TypeConstraints;
-use Catalyst::Utils qw/ ensure_class_loaded /;
-use Class::Load 'load_class';
+use Catalyst::Utils;
use namespace::autoclean;
subtype 'Catalyst::ScriptRole::LoadableClass',
as 'ClassName';
coerce 'Catalyst::ScriptRole::LoadableClass',
from 'Str',
- via { ensure_class_loaded($_); 1 };
+ via { Catalyst::Utils::ensure_class_loaded($_); $_ };
with 'MooseX::Getopt' => {
-version => 0.48,
sub _run_application {
my $self = shift;
my $app = $self->application_name;
- load_class($app);
+ Catalyst::Utils::ensure_class_loaded($app);
my $server;
if (my $e = $self->_plack_engine_name ) {
$server = $self->load_engine($e, $self->_plack_loader_args);
--- /dev/null
+use warnings;
+use strict;
+use Test::More;
+
+{
+ package MyApp::Controller::Root;
+ $INC{'MyApp/Controller/Root.pm'} = __FILE__;
+
+ use base 'Catalyst::Controller';
+
+ sub root :Path('') Args(0) {
+ my ($self, $c) = @_;
+ $c->{stash}->{foo} = 'bar';
+ $c->stash(baz=>'boor');
+ $c->{stash}->{baz} = $c->stash->{baz} . 2;
+
+ Test::More::is($c->stash->{foo}, 'bar');
+ Test::More::is($c->stash->{baz}, 'boor2');
+ Test::More::is($c->{stash}->{foo}, 'bar');
+ Test::More::is($c->{stash}->{baz}, 'boor2');
+
+ $c->res->body('return');
+ }
+
+ package MyApp;
+ use Catalyst;
+ MyApp->setup;
+}
+
+use HTTP::Request::Common;
+use Catalyst::Test 'MyApp';
+
+{
+ ok my $res = request POST 'root/';
+}
+
+done_testing();
--- /dev/null
+use warnings;
+use strict;
+use Test::More;
+
+{
+ package MyApp::Controller::Root;
+ $INC{'MyApp/Controller/Root.pm'} = __FILE__;
+
+ use Moose;
+ use MooseX::MethodAttributes;
+
+ extends 'Catalyst::Controller';
+
+ sub root :Chained(/) PathPart('') CaptureArgs(0) {
+ my ($self, $c) = @_;
+ }
+
+ sub top :Chained('root') Args(0) {
+ my ($self, $c) = @_;
+ Test::More::is $self->action_for('top'), 'top';
+ Test::More::is $self->action_for('story/story'), 'story/story';
+ }
+
+ sub default : Path {
+
+ my ($self, $c) = @_;
+ $c->response->body("Ok");
+ }
+
+ MyApp::Controller::Root->config(namespace=>'');
+
+ package MyApp::Controller::Story;
+ $INC{'MyApp/Controller/Story.pm'} = __FILE__;
+
+ use Moose;
+ use MooseX::MethodAttributes;
+
+ extends 'Catalyst::Controller';
+
+ sub root :Chained(/root) PathPart('') CaptureArgs(0) {
+ my ($self, $c) = @_;
+ }
+
+ sub story :Chained(root) Args(0) {
+ my ($self, $c) = @_;
+
+ Test::More::is $self->action_for('story'), 'story/story';
+ Test::More::is $self->action_for('author/author'), 'story/author/author';
+ }
+
+ __PACKAGE__->meta->make_immutable;
+
+ package MyApp::Controller::Story::Author;
+ $INC{'MyApp/Controller/Story/Author.pm'} = __FILE__;
+
+ use Moose;
+ use MooseX::MethodAttributes;
+
+ extends 'Catalyst::Controller';
+
+ sub root :Chained(/story/root) PathPart('') CaptureArgs(0) {
+ my ($self, $c) = @_;
+ }
+
+ sub author :Chained(root) Args(0) {
+ my ($self, $c, $id) = @_;
+ Test::More::is $self->action_for('author'), 'story/author/author';
+ Test::More::is $self->action_for('../story'), 'story/story';
+ Test::More::is $self->action_for('../../top'), 'top';
+ }
+
+ __PACKAGE__->meta->make_immutable;
+
+ package MyApp;
+ $INC{'MyApp.pm'} = __FILE__;
+
+ use Catalyst;
+
+ MyApp->setup;
+}
+
+use Catalyst::Test 'MyApp';
+
+ok request '/top';
+ok request '/story';
+ok request '/author';
+ok request '/double';
+ok request '/double/file.ext';
+ok request '/double/file..ext';
+
+
+done_testing(13);
+