use Tree::Simple;
use Tree::Simple::Visitor::FindByPath;
use Catalyst::Request;
+use Catalyst::Request::Upload;
use Catalyst::Response;
require Module::Pluggable::Fast;
}
}
+=item $c->dispatch
+
+Dispatch request to actions.
+
+=cut
+
+sub dispatch {
+ my $c = shift;
+ my $action = $c->req->action;
+ my $namespace = '';
+ $namespace = ( join( '/', @{ $c->req->args } ) || '/' )
+ if $action eq 'default';
+ unless ($namespace) {
+ if ( my $result = $c->get_action($action) ) {
+ $namespace = _class2prefix( $result->[0]->[0]->[0] );
+ }
+ }
+ my $default = $action eq 'default' ? $namespace : undef;
+ my $results = $c->get_action( $action, $default );
+ $namespace ||= '/';
+ if ( @{$results} ) {
+
+ # Execute last begin
+ $c->state(1);
+ if ( my $begin = @{ $c->get_action( 'begin', $namespace ) }[-1] ) {
+ $c->execute( @{ $begin->[0] } );
+ return if scalar @{ $c->error };
+ }
+
+ # Execute the auto chain
+ for my $auto ( @{ $c->get_action( 'auto', $namespace ) } ) {
+ $c->execute( @{ $auto->[0] } );
+ return if scalar @{ $c->error };
+ last unless $c->state;
+ }
+
+ # Execute the action or last default
+ if ( ( my $action = $c->req->action ) && $c->state ) {
+ if ( my $result = @{ $c->get_action( $action, $default ) }[-1] ) {
+ $c->execute( @{ $result->[0] } );
+ }
+ }
+
+ # Execute last end
+ if ( my $end = @{ $c->get_action( 'end', $namespace ) }[-1] ) {
+ $c->execute( @{ $end->[0] } );
+ return if scalar @{ $c->error };
+ }
+ }
+ else {
+ my $path = $c->req->path;
+ my $error = $path
+ ? qq/Unknown resource "$path"/
+ : "No default action defined";
+ $c->log->error($error) if $c->debug;
+ $c->error($error);
+ }
+}
+
=item $c->error
=item $c->error($error, ...)
else { $c->state( &$code( $class, $c, @{ $c->req->args } ) ) }
};
if ( my $error = $@ ) {
- chomp $error;
- $error = qq/Caught exception "$error"/;
+
+ unless ( ref $error ) {
+ chomp $error;
+ $error = qq/Caught exception "$error"/;
+ }
+
$c->log->error($error);
- $c->error($error) if $c->debug;
+ $c->error($error);
$c->state(0);
}
return $c->state;
if ( my $location = $c->response->redirect ) {
$c->log->debug(qq/Redirecting to "$location"/) if $c->debug;
$c->response->header( Location => $location );
- $c->response->status(302) if $c->response->status !~ /3\d\d$/;
+ $c->response->status(302) if $c->response->status !~ /^3\d\d$/;
}
if ( $#{ $c->error } >= 0 ) {
}
}
for my $result ( @{$results} ) {
- $c->state( $c->execute( @{ $result->[0] } ) );
+ $c->execute( @{ $result->[0] } );
+ return if scalar @{ $c->error };
+ last unless $c->state;
}
return $c->state;
}
$namespace = '' if $namespace eq '/';
my $parent = $c->tree;
my @results;
- my $result = $c->actions->{private}->{ $parent->getUID }->{$action};
- push @results, [$result] if $result;
- my $visitor = Tree::Simple::Visitor::FindByPath->new;
- for my $part ( split '/', $namespace ) {
- $visitor->setSearchPath($part);
- $parent->accept($visitor);
- my $child = $visitor->getResult;
- my $uid = $child->getUID if $child;
- my $match = $c->actions->{private}->{$uid}->{$action} if $uid;
- push @results, [$match] if $match;
- $parent = $child if $child;
+ my %allowed = ( begin => 1, auto => 1, default => 1, end => 1 );
+ if ( $allowed{$action} ) {
+ my $result = $c->actions->{private}->{ $parent->getUID }->{$action};
+ push @results, [$result] if $result;
+ my $visitor = Tree::Simple::Visitor::FindByPath->new;
+ for my $part ( split '/', $namespace ) {
+ $visitor->setSearchPath($part);
+ $parent->accept($visitor);
+ my $child = $visitor->getResult;
+ my $uid = $child->getUID if $child;
+ my $match = $c->actions->{private}->{$uid}->{$action} if $uid;
+ push @results, [$match] if $match;
+ $parent = $child if $child;
+ }
+ }
+ else {
+ if ($namespace) {
+ my $visitor = Tree::Simple::Visitor::FindByPath->new;
+ $visitor->setSearchPath( split '/', $namespace );
+ $parent->accept($visitor);
+ my $child = $visitor->getResult;
+ my $uid = $child->getUID if $child;
+ my $match = $c->actions->{private}->{$uid}->{$action}
+ if $uid;
+ push @results, [$match] if $match;
+ }
+ else {
+ my $result =
+ $c->actions->{private}->{ $parent->getUID }->{$action};
+ push @results, [$result] if $result;
+ }
}
return \@results;
}
my $handler = sub {
my $c = $class->prepare($engine);
$c->{stats} = \@stats;
- my $action = $c->req->action;
- my $namespace = '';
- $namespace = ( join( '/', @{ $c->req->args } ) || '/' )
- if $action eq 'default';
- unless ($namespace) {
- if ( my $result = $c->get_action($action) ) {
- $namespace = _class2prefix( $result->[0]->[0]->[0] );
- }
- }
- my $default = $action eq 'default' ? $namespace : undef;
- my $results = $c->get_action( $action, $default );
- $namespace ||= '/';
- if ( @{$results} ) {
- for my $begin ( @{ $c->get_action( 'begin', $namespace ) } ) {
- $c->state( $c->execute( @{ $begin->[0] } ) );
- }
- if ( my $action = $c->req->action ) {
- for my $result (
- @{ $c->get_action( $action, $default ) }[-1] )
- {
- $c->state( $c->execute( @{ $result->[0] } ) );
- last unless $default;
- }
- }
- for my $end ( reverse @{ $c->get_action( 'end', $namespace ) } )
- {
- $c->state( $c->execute( @{ $end->[0] } ) );
- }
- }
- else {
- my $path = $c->req->path;
- my $error = $path
- ? qq/Unknown resource "$path"/
- : "No default action defined";
- $c->log->error($error) if $c->debug;
- $c->error($error);
- }
+ $c->dispatch;
return $c->finalize;
};
if ( $class->debug ) {
$absolute = 1;
}
$absolute = 1 if $flags{global};
- my $name = $absolute ? $path : "$prefix/$path";
+ my $name = $absolute ? $path : $prefix ? "$prefix/$path" : $path;
$c->actions->{plain}->{$name} = [ $namespace, $code ];
}
if ( my $regex = $flags{regex} ) {
$self->components->{ ref $comp } = $comp;
$self->setup_actions($comp);
}
- my $t = Text::ASCIITable->new;
+ my $t = Text::ASCIITable->new( { hide_HeadRow => 1, hide_HeadLine => 1 } );
$t->setCols('Class');
$t->setColWidth( 'Class', 75, 1 );
$t->addRow( wrap( $_, 75 ) ) for keys %{ $self->components };
if ( @{ $t->{tbl_rows} } && $self->debug );
my $actions = $self->actions;
my $privates = Text::ASCIITable->new;
- $privates->setCols( 'Action', 'Class', 'Code' );
- $privates->setColWidth( 'Action', 28, 1 );
- $privates->setColWidth( 'Class', 28, 1 );
- $privates->setColWidth( 'Code', 14, 1 );
+ $privates->setCols( 'Private', 'Class', 'Code' );
+ $privates->setColWidth( 'Private', 28, 1 );
+ $privates->setColWidth( 'Class', 28, 1 );
+ $privates->setColWidth( 'Code', 14, 1 );
my $walker = sub {
my ( $walker, $parent, $prefix ) = @_;
$prefix .= $parent->getNodeValue || '';
$self->log->debug( 'Loaded private actions', $privates->draw )
if ( @{ $privates->{tbl_rows} } && $self->debug );
my $publics = Text::ASCIITable->new;
- $publics->setCols( 'Action', 'Class', 'Code' );
- $publics->setColWidth( 'Action', 28, 1 );
- $publics->setColWidth( 'Class', 28, 1 );
- $publics->setColWidth( 'Code', 14, 1 );
+ $publics->setCols( 'Public', 'Private' );
+ $publics->setColWidth( 'Public', 37, 1 );
+ $publics->setColWidth( 'Private', 36, 1 );
for my $plain ( sort keys %{ $actions->{plain} } ) {
my ( $class, $code ) = @{ $actions->{plain}->{$plain} };
- $publics->addRow(
- wrap( "/$plain", 28 ),
- wrap( $class, 28 ),
- wrap( $code, 14 )
- );
+ $publics->addRow( wrap( "/$plain", 37 ),
+ wrap( $self->actions->{reverse}->{$code} || $code, 36 ) );
}
$self->log->debug( 'Loaded public actions', $publics->draw )
if ( @{ $publics->{tbl_rows} } && $self->debug );
my $regexes = Text::ASCIITable->new;
- $regexes->setCols( 'Action', 'Class', 'Code' );
- $regexes->setColWidth( 'Action', 28, 1 );
- $regexes->setColWidth( 'Class', 28, 1 );
- $regexes->setColWidth( 'Code', 14, 1 );
+ $regexes->setCols( 'Regex', 'Private' );
+ $regexes->setColWidth( 'Regex', 37, 1 );
+ $regexes->setColWidth( 'Private', 36, 1 );
for my $regex ( sort keys %{ $actions->{regex} } ) {
my ( $class, $code ) = @{ $actions->{regex}->{$regex} };
- $regexes->addRow(
- wrap( $regex, 28 ),
- wrap( $class, 28 ),
- wrap( $code, 14 )
- );
+ $regexes->addRow( wrap( $regex, 37 ),
+ wrap( $self->actions->{reverse}->{$class} || $class, 36 ) );
}
$self->log->debug( 'Loaded regex actions', $regexes->draw )
if ( @{ $regexes->{tbl_rows} } && $self->debug );
}
+=item $c->state
+
+Contains the return value of the last executed action.
+
=item $c->stash
Returns a hashref containing all your data.