# This file documents the revision history for Perl extension Catalyst.
+ Bug fixes:
+ - Fix so that CATALYST_EXCEPTION_CLASS in MyApp is always respected by
+ not loading Catalyst::Exception in Utils.pm BEGIN, because some Scripts::*
+ load Utils before MyApp.pm
+
+ - Fix warnings with new Moose versions about "excludes" during role
+ application
+
+ - Fix warning from MooseX::Getopt regarding duplicate "help" aliases.
+
+ - parse_on_demand fixed when used in conjunction with debug mode.
+ A regression was introduced in 5.80022 which would cause the body
+ to always be parsed for logging at the end of the request when in
+ debug mode. This has been fixed so that if the body has not been parsed
+ by the time the request is logged, then the body is omitted.
+
+ - Fix show_internal_actions config setting producing warnings in debug
+ mode (RT#59738)
+
+ Refactoring:
+ - moved component name sort that happens in setup_components to
+ locate_components to allow methods to wrap around locate_components
+
+ Documentation:
+ - Fix some typos
+
+ - Advertise Catalyst::Plugin::SmartURI
+
+
5.80025 2010-07-29 01:50:00
New features:
- Fix controllers with no method attributes (where the action definitions
are entirely contained in config). RT#58057
- Fix running as a CGI under IIS at non-root locations.
+ - Fix warning about "excludes" during role application
+ - Fix warning from MooseX::Getopt regarding duplicate "help" aliases
Documentation:
- Fix missing - in the docs when describing the --mechanize option at one
requires 'Task::Weaken';
requires 'Text::Balanced'; # core in 5.8.x but mentioned for completeness
requires 'MRO::Compat';
-requires 'MooseX::Getopt' => '0.25';
+requires 'MooseX::Getopt' => '0.30';
requires 'MooseX::Types';
requires 'MooseX::Types::Common::Numeric';
requires 'String::RewritePrefix' => '0.004'; # Catalyst::Utils::resolve_namespace
grep { $_ ne 't/aggregate.t' }
map { glob } qw[t/*.t t/aggregate/*.t];
}
-author_requires 'CatalystX::LeakChecker', '0.05'; # Skipped if this isn't installed
+author_requires 'CatalystX::LeakChecker', '0.05';
author_requires 'File::Copy::Recursive'; # For http server test
author_tests 't/author';
my $parent = $c->stack->[-1];
# forward, locate the caller
- if ( exists $c->counter->{"$parent"} ) {
+ if ( defined $parent && exists $c->counter->{"$parent"} ) {
$c->stats->profile(
begin => $action,
parent => "$parent" . $c->counter->{"$parent"},
$c->log->debug("Query keywords are: $keywords");
}
- $c->log_request_parameters( query => $request->query_parameters, body => $request->body_parameters );
+ $c->log_request_parameters( query => $request->query_parameters, $request->_has_body ? (body => $request->body_parameters) : () );
$c->log_request_uploads($request);
}
my $config = $class->config->{ setup_components };
- my @comps = sort { length $a <=> length $b }
- $class->locate_components($config);
+ my @comps = $class->locate_components($config);
my %comps = map { $_ => 1 } @comps;
my $deprecatedcatalyst_component_names = grep { /::[CMV]::/ } @comps;
%$config
);
- my @comps = $locator->plugins;
+ # XXX think about ditching this sort entirely
+ my @comps = sort { length $a <=> length $b } $locator->plugins;
return @comps;
}
myapp_cgi.pl [options]
Options:
- -h --help display this help and exits
+ -? --help display this help and exits
=head1 DESCRIPTION
with 'Catalyst::ScriptRole';
-__PACKAGE__->meta->get_attribute('help')->cmd_aliases('?');
-
has debug => (
traits => [qw(Getopt)],
cmd_aliases => 'd',
use namespace::autoclean;
with 'MooseX::Getopt' => {
- excludes => [qw/
+ -excludes => [qw/
_getopt_spec_warnings
_getopt_spec_exception
_getopt_full_usage
required => 1,
);
-has help => (
- traits => ['Getopt'],
- isa => Bool,
- is => 'ro',
- documentation => 'Display this help and exit',
- cmd_aliases => ['?', 'h'],
-);
-
sub _getopt_spec_exception {}
sub _getopt_spec_warnings {
exit 0;
}
-before run => sub {
- my $self = shift;
- $self->_getopt_full_usage if $self->help;
-};
-
sub run {
my $self = shift;
$self->_run_application;
package Catalyst::Utils;
use strict;
-use Catalyst::Exception;
use File::Spec;
use HTTP::Request;
use Path::Class;
eval { $tmpdir->mkpath };
if ($@) {
+ # don't load Catalyst::Exception as a BEGIN in Utils,
+ # because Utils often gets loaded before MyApp.pm, and if
+ # Catalyst::Exception is loaded before MyApp.pm, it does
+ # not honor setting
+ # $Catalyst::Exception::CATALYST_EXCEPTION_CLASS in
+ # MyApp.pm
+ require Catalyst::Exception;
Catalyst::Exception->throw(
message => qq/Couldn't create tmpdir '$tmpdir', "$@"/ );
}
--- /dev/null
+use strict;
+use warnings;
+use FindBin qw/$Bin/;
+use lib "$Bin/../lib";
+use Catalyst::Test 'ChainedActionsApp';
+use Test::More;
+
+content_like('/', qr/Application Home Page/, 'Application home');
+content_like('/15/GoldFinger', qr/List project GoldFinger pages/, 'GoldFinger Project Index');
+content_like('/15/GoldFinger/4/007', qr/This is 007 page of GoldFinger project/, '007 page in GoldFinger Project');
+content_like('/account', qr/New account o login/, 'no account');
+content_like('/account/ferz', qr/This is account ferz/, 'account');
+content_like('/account/123', qr/This is account 123/, 'account');
+action_notfound('/c');
+
+done_testing;
+
sub _getopt_full_usage { $help++ }
}
-test('-h');
test('--help');
test('-?');
} "new_with_options";
ok $i;
my $saved;
- open( $saved, '<&'. STDIN->fileno )
- or croak("Can't dup stdin: $!");
+ open( $saved, '>&'. STDOUT->fileno )
+ or croak("Can't dup stdout: $!");
open( STDOUT, '>&='. $fh->fileno )
or croak("Can't open stdout: $!");
eval { $i->run };
use Pod::Coverage 0.19;
use Test::Pod::Coverage 1.04;
-all_pod_coverage_ok(
- {
- also_private => ['BUILD']
- }
-);
+my @modules = all_modules;
+our @private = ( 'BUILD' );
+foreach my $module (@modules) {
+ local @private = (@private, 'run') if $module =~ /^Catalyst::Script::/;
+ pod_coverage_ok($module, { also_private => \@private });
+}
+
+done_testing;
use warnings;
use FindBin qw/$Bin/;
use lib "$Bin/lib";
-use Test::More tests => 1;
+use Test::More tests => 2;
use Test::Exception;
lives_ok {
require TestAppClassExceptionSimpleTest;
} 'Can load application';
+
+
+lives_ok {
+ Catalyst::Exception->throw
+} 'throw is properly stubbed out';
+
+
+
--- /dev/null
+package ChainedActionsApp;
+use Moose;
+use namespace::autoclean;
+
+use Catalyst::Runtime 5.80;
+
+use Catalyst qw//;
+
+extends 'Catalyst';
+
+our $VERSION = "0.01";
+$VERSION = eval $VERSION;
+
+__PACKAGE__->config(
+ name => 'ChainedActionsApp',
+ disable_component_regex_fallback => 1,
+);
+
+__PACKAGE__->setup;
+
+1;
--- /dev/null
+package ChainedActionsApp::Controller::Root;
+use Moose;
+use namespace::autoclean;
+
+BEGIN { extends 'Catalyst::Controller' }
+
+#
+# Sets the actions in this controller to be registered with no prefix
+# so they function identically to actions created in MyApp.pm
+#
+__PACKAGE__->config(namespace => '');
+
+=head1 NAME
+
+test_chained::Controller::Root - Root Controller for test_chained
+
+=head1 DESCRIPTION
+
+[enter your description here]
+
+=head1 METHODS
+
+=head2 setup
+
+This is the C<setup> method that initializes the request. Any matching action
+will go through this, so it is an application-wide automatically executed
+action. For more information, see L<Catalyst::DispatchType::Chained>
+
+=cut
+
+sub setup : Chained('/') PathPart('') CaptureArgs(0) {
+ my ( $self, $c ) = @_;
+ # Common things here are to check for ACL and setup global contexts
+}
+
+sub home : Chained('setup') PathPart('') Args(0) {
+ my($self,$c) = @_;
+ $c->response->body( "Application Home Page" );
+}
+
+=head2 home_base
+
+ Args:
+ project_id
+ project_title
+
+=cut
+
+sub home_base : Chained('setup') PathPart('') CaptureArgs(2) {
+ my($self,$c,$proj_id,$title) = @_;
+ $c->stash({project_id=>$proj_id, project_title=>$title});
+}
+
+sub hpages : Chained('home_base') PathPart('') Args(0) {
+ my($self,$c) = @_;
+ $c->response->body( "List project " . $c->stash->{project_title} . " pages");
+}
+
+sub hpage : Chained('home_base') PathPart('') Args(2) {
+ my($self,$c,$page_id, $pagetitle) = @_;
+ $c->response->body( "This is $pagetitle page of " . $c->stash->{project_title} . " project" );
+}
+
+sub no_account : Chained('setup') PathPart('account') Args(0) {
+ my($self,$c) = @_;
+ $c->response->body( "New account o login" );
+}
+
+sub account_base : Chained('setup') PathPart('account') CaptureArgs(1) {
+ my($self,$c,$acc_id) = @_;
+ $c->stash({account_id=>$acc_id});
+}
+
+sub account : Chained('account_base') PathPart('') Args(0) {
+ my($self,$c,$acc) = @_;
+ $c->response->body( "This is account " . $c->stash->{account_id} );
+}
+
+=head2 default
+
+Standard 404 error page
+
+=cut
+
+sub default : Chained('setup') PathPart('') Args() {
+ my ( $self, $c ) = @_;
+ $c->response->body( 'Page not found' );
+ $c->response->status(404);
+}
+
+=head2 end
+
+Attempt to render a view, if needed.
+
+=cut
+
+sub end : ActionClass('RenderView') {}
+
+=head1 AUTHOR
+
+Ferruccio Zamuner
+
+=head1 LICENSE
+
+This library is free software. You can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
+__PACKAGE__->meta->make_immutable;
+
+1;
use strict;
use warnings;
+use Catalyst::Utils; #< some of the scripts use Catalyst::Utils before MyApp.pm
+
BEGIN { $Catalyst::Exception::CATALYST_EXCEPTION_CLASS = 'TestAppClassExceptionSimpleTest::Exception'; }
use Catalyst;
--- /dev/null
+package TestAppShowInternalActions;
+use Moose;
+use namespace::autoclean;
+
+use Catalyst::Runtime 5.80;
+
+use Catalyst qw/ -Debug /; # Debug must remain on for
+ # t/live_show_internal_actions_warnings.t
+
+extends 'Catalyst';
+
+__PACKAGE__->config(
+ name => 'TestAppShowInternalActions',
+ disable_component_resolution_regex_fallback => 1,
+ show_internal_actions => 1,
+);
+
+__PACKAGE__->setup();
+
+1;
--- /dev/null
+package TestAppShowInternalActions::Controller::Root;
+use Moose;
+use namespace::autoclean;
+
+BEGIN { extends 'Catalyst::Controller' }
+
+__PACKAGE__->config(namespace => '');
+
+sub index :Path :Args(0) {
+ my ( $self, $c ) = @_;
+
+ $c->response->body( 'hello world' );
+}
+
+sub end : Action {}
+
+__PACKAGE__->meta->make_immutable;
+
+1;
--- /dev/null
+use strict;
+use warnings;
+use FindBin '$Bin';
+use lib "$Bin/lib";
+use Test::More;
+use File::Spec;
+BEGIN { # Shut up debug output, app needs debug on for the issue to
+ # appear, but we don't want the spraff to the screen
+
+ my $devnull = File::Spec->devnull;
+ open my $fh, '>', $devnull or die "Cannot write to $devnull: $!";
+
+ *STDERR = $fh;
+}
+
+use Catalyst::Test 'TestAppShowInternalActions';
+
+my $last_warning;
+{
+ local $SIG{__WARN__} = sub { $last_warning = shift };
+ my $res = get('/');
+}
+is( $last_warning, undef, 'there should be no warnings about uninitialized value' );
+
+done_testing;
sub test {}
}
-
+my $c = 0;
foreach my $class (qw/ CT RT /) {
my $class_name = 'NoAttributes::' . $class;
my $meta = $class_name->meta;
my $meth = $meta->find_method_by_name('test');
{
- local $TODO = "Known MX::MethodAttributes issue";
+ local $TODO = "Known MX::MethodAttributes issue" if $c++;
ok $meth->can('attributes'), 'method metaclass has ->attributes method for ' . $class;;
}
}