use File::stat;
use NEXT;
use Text::SimpleTable;
-use Path::Class;
+use Path::Class::Dir;
+use Path::Class::File;
use Time::HiRes qw/gettimeofday tv_interval/;
use URI;
use Scalar::Util qw/weaken blessed/;
use Tree::Simple qw/use_weak_refs/;
use Tree::Simple::Visitor::FindByUID;
use attributes;
+use Carp qw/croak/;
__PACKAGE__->mk_accessors(
qw/counter request response state action stack namespace/
my $c = shift;
if ( $_[0] ) {
my $error = ref $_[0] eq 'ARRAY' ? $_[0] : [@_];
+ croak @$error unless ref $c;
push @{ $c->{error} }, @$error;
}
elsif ( defined $_[0] ) { $c->{error} = undef }
# search via regex
sub _comp_search {
- my ($c, @names) = @_;
+ my ( $c, @names ) = @_;
foreach my $name (@names) {
foreach my $component ( keys %{ $c->components } ) {
- my $comp = $c->components->{$component} if $component =~ /$name/i;
- if ($comp) {
- if ( eval { $comp->can('ACCEPT_CONTEXT'); } ) {
- return $comp->ACCEPT_CONTEXT($c);
- }
- else { return $comp }
- }
+ return $c->components->{$component} if $component =~ /$name/i;
}
}
# try explicit component names
sub _comp_explicit {
- my ($c, @names) = @_;
+ my ( $c, @names ) = @_;
foreach my $try (@names) {
- if ( exists $c->components->{$try} ) {
- my $comp = $c->components->{$try};
- if ( eval { $comp->can('ACCEPT_CONTEXT'); } ) {
- return $comp->ACCEPT_CONTEXT($c);
- }
- else { return $comp }
- }
+ return $c->components->{$try} if ( exists $c->components->{$try} );
}
return undef;
# like component, but try just these prefixes before regex searching,
# and do not try to return "sort keys %{ $c->components }"
sub _comp_prefixes {
- my ($c, $name, @prefixes) = @_;
+ my ( $c, $name, @prefixes ) = @_;
my $appclass = ref $c || $c;
return $comp;
}
+# Find possible names for a prefix
+
+sub _comp_names {
+ my ( $c, @prefixes ) = @_;
+
+ my $appclass = ref $c || $c;
+
+ my @pre = map { "${appclass}::${_}::" } @prefixes;
+
+ my @names;
+
+ COMPONENT: foreach my $comp ($c->component) {
+ foreach my $p (@pre) {
+ if ($comp =~ s/^$p//) {
+ push(@names, $comp);
+ next COMPONENT;
+ }
+ }
+ }
+
+ return @names;
+}
+
# Return a component if only one matches.
sub _comp_singular {
- my ($c, @prefixes) = @_;
+ my ( $c, @prefixes ) = @_;
my $appclass = ref $c || $c;
- my ($comp,$rest) = map { $c->_comp_search("^${appclass}::${_}::") }
- @prefixes;
+ my ( $comp, $rest ) =
+ map { $c->_comp_search("^${appclass}::${_}::") } @prefixes;
return $comp unless $rest;
}
+# Filter a component before returning by calling ACCEPT_CONTEXT if available
+sub _filter_component {
+ my ( $c, $comp, @args ) = @_;
+ if ( eval { $comp->can('ACCEPT_CONTEXT'); } ) {
+ return $comp->ACCEPT_CONTEXT( $c, @args );
+ }
+ else { return $comp }
+}
+
=head2 COMPONENT ACCESSORS
=head2 $c->comp($name)
);
my $comp = $c->_comp_explicit(@names);
- return $comp if defined($comp);
+ return $c->_filter_component( $comp, @_ ) if defined($comp);
$comp = $c->_comp_search($name);
- return $comp if defined($comp);
+ return $c->_filter_component( $comp, @_ ) if defined($comp);
}
return sort keys %{ $c->components };
=cut
sub controller {
- my ( $c, $name ) = @_;
- return $c->_comp_prefixes($name, qw/Controller C/)
- if ($name);
- return $c->component($c->action->class);
+ my ( $c, $name, @args ) = @_;
+ return $c->_filter_component( $c->_comp_prefixes( $name, qw/Controller C/ ),
+ @args )
+ if ($name);
+ return $c->component( $c->action->class );
+}
+
+=head2 $c->controllers
+
+Returns the available names which can be passed to $c->controller
+
+=cut
+
+sub controllers {
+ my ( $c ) = @_;
+ return $c->_comp_names(qw/Controller C/);
}
=head2 $c->model($name)
=cut
sub model {
- my ( $c, $name ) = @_;
- return $c->_comp_prefixes($name, qw/Model M/)
- if $name;
- return $c->comp($c->config->{default_model})
- if $c->config->{default_model};
- return $c->_comp_singular(qw/Model M/);
+ my ( $c, $name, @args ) = @_;
+ return $c->_filter_component( $c->_comp_prefixes( $name, qw/Model M/ ),
+ @args )
+ if $name;
+ return $c->component( $c->config->{default_model} )
+ if $c->config->{default_model};
+ return $c->_filter_component( $c->_comp_singular(qw/Model M/), @args );
}
+=head2 $c->models
+
+Returns the available names which can be passed to $c->model
+
+=cut
+
+sub models {
+ my ( $c ) = @_;
+ return $c->_comp_names(qw/Model M/);
+}
+
=head2 $c->view($name)
Gets a L<Catalyst::View> instance by name.
=cut
sub view {
- my ( $c, $name ) = @_;
- return $c->_comp_prefixes($name, qw/View V/)
- if $name;
- return $c->comp($c->config->{default_view})
- if $c->config->{default_view};
- return $c->_comp_singular(qw/View V/);
+ my ( $c, $name, @args ) = @_;
+ return $c->_filter_component( $c->_comp_prefixes( $name, qw/View V/ ),
+ @args )
+ if $name;
+ return $c->component( $c->config->{default_view} )
+ if $c->config->{default_view};
+ return $c->_filter_component( $c->_comp_singular(qw/View V/) );
+}
+
+=head2 $c->views
+
+Returns the available names which can be passed to $c->view
+
+=cut
+
+sub views {
+ my ( $c ) = @_;
+ return $c->_comp_names(qw/View V/);
}
=head2 Class data and helper classes
sub path_to {
my ( $c, @path ) = @_;
- my $path = dir( $c->config->{home}, @path );
+ my $path = Path::Class::Dir->new( $c->config->{home}, @path );
if ( -d $path ) { return $path }
- else { return file( $c->config->{home}, @path ) }
+ else { return Path::Class::File->new( $c->config->{home}, @path ) }
}
=head2 $c->plugin( $name, $class, @args )
$class->setup_finished(1);
}
-=head2 $c->uri_for( $path, [ @args ] )
+=head2 $c->uri_for( $path, @args?, \%query_values? )
Merges path with C<$c-E<gt>request-E<gt>base> for absolute uri's and
with C<$c-E<gt>namespace> for relative uri's, then returns a
<a href="http://lists.rawmode.org/mailman/listinfo/catalyst">Mailing-List</a>
</li>
<li>
- <a href="irc://irc.perl.org/catalyst">IRC channel #catalyst on irc.perl.org</a>
+ <a href="irc://irc.perl.org/catalyst">IRC channel #catalyst-talk on irc.perl.org</a>
</li>
</ul>
<h2>In conclusion</h2>
$class = $c->component($class) || $class;
$c->state(0);
- if ($c->depth >= $RECURSION) {
+ if ( $c->depth >= $RECURSION ) {
my $action = "$code";
$action = "/$action" unless $action =~ /\-\>/;
my $error = qq/Deep recursion detected calling "$action"/;
return $c->state;
}
-
if ( $c->debug ) {
my $action = "$code";
$action = "/$action" unless $action =~ /\-\>/;
$c->log->error($error);
}
- $c->finalize_uploads;
-
- # Error
- if ( $#{ $c->error } >= 0 ) {
- $c->finalize_error;
+ # Allow engine to handle finalize flow (for POE)
+ if ( $c->engine->can('finalize') ) {
+ $c->engine->finalize( $c );
}
+ else {
- $c->finalize_headers;
+ $c->finalize_uploads;
- # HEAD request
- if ( $c->request->method eq 'HEAD' ) {
- $c->response->body('');
- }
+ # Error
+ if ( $#{ $c->error } >= 0 ) {
+ $c->finalize_error;
+ }
+
+ $c->finalize_headers;
+
+ # HEAD request
+ if ( $c->request->method eq 'HEAD' ) {
+ $c->response->body('');
+ }
- $c->finalize_body;
+ $c->finalize_body;
+ }
return $c->response->status;
}
if ( $c->response->body && !$c->response->content_length ) {
# get the length from a filehandle
- if ( blessed($c->response->body) && $c->response->body->can('read') ) {
+ if ( blessed( $c->response->body ) && $c->response->body->can('read') )
+ {
if ( my $stat = stat $c->response->body ) {
$c->response->content_length( $stat->size );
}
$c->res->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
}
- $c->prepare_request(@arguments);
- $c->prepare_connection;
- $c->prepare_query_parameters;
- $c->prepare_headers;
- $c->prepare_cookies;
- $c->prepare_path;
-
- # On-demand parsing
- $c->prepare_body unless $c->config->{parse_on_demand};
+ # Allow engine to direct the prepare flow (for POE)
+ if ( $c->engine->can('prepare') ) {
+ $c->engine->prepare( $c, @arguments );
+ }
+ else {
+ $c->prepare_request(@arguments);
+ $c->prepare_connection;
+ $c->prepare_query_parameters;
+ $c->prepare_headers;
+ $c->prepare_cookies;
+ $c->prepare_path;
+
+ # On-demand parsing
+ $c->prepare_body unless $c->config->{parse_on_demand};
+ }
my $method = $c->req->method || '';
my $path = $c->req->path || '';
if ($home) {
$class->config->{home} ||= $home;
- $class->config->{root} ||= dir($home)->subdir('root');
+ $class->config->{root} ||= Path::Class::Dir->new($home)->subdir('root');
}
}
sub registered_plugins {
my $proto = shift;
- return sort keys %{$proto->_plugins} unless @_;
+ return sort keys %{ $proto->_plugins } unless @_;
my $plugin = shift;
return 1 if exists $proto->_plugins->{$plugin};
return exists $proto->_plugins->{"Catalyst::Plugin::$plugin"};
message => qq/Couldn't load ${type}plugin "$plugin", $error/ );
}
- $proto->_plugins->{$plugin} = 1;
+ $proto->_plugins->{$plugin} = 1;
unless ($instant) {
no strict 'refs';
unshift @{"$class\::ISA"}, $plugin;
IRC:
- Join #catalyst on irc.perl.org.
+ Join #catalyst-talk on irc.perl.org.
Mailing Lists: