File Coverage

blib/lib/Catalyst/Plugin/Digress.pm
Criterion Covered Total %
statement 28 35 80.0
branch 6 14 42.8
condition 1 6 16.6
subroutine 6 6 100.0
pod 1 1 100.0
total 42 62 67.7


line stmt bran cond sub pod time code
1 1     1   3153 use strict; use warnings;
  1     1   2  
  1         30  
  1         6  
  1         2  
  1         42  
2              
3              
4             use Scalar::Util ();
5 1     1   6 use Carp ();
  1         2  
  1         12  
6 1     1   3  
  1         2  
  1         416  
7             our $VERSION = '1.100';
8              
9             my $c = shift;
10              
11 3     3 1 310115 my ( $action, $path );
12             if ( Scalar::Util::blessed( $_[0] ) && $_[0]->isa( 'Catalyst::Action' ) ) {
13 3         8 $action = shift;
14 3 50 33     13 }
15 0         0 else {
16             $path = shift;
17             $path = $c->stack->[-1]->namespace . '/' . $path if $path !~ m!/!;
18 3         5 $action = $c->dispatcher->get_action_by_path( $path )
19 3 100       25 or Carp::croak "Cannot digress to nonexistant action '$path'";
20 3 50       42 }
21              
22             my $scope_guard = bless [ $c ], 'Catalyst::Plugin::Digress::_ScopeGuard';
23             if ( $c->use_stats ) { # basically Catalyst::_stats_start_execute with less nonsense
24 3         215 my $action_name = $action->reverse;
25 3 50       8 my $uid = $action_name . ++$c->counter->{ $action_name };
26 0         0 my $stats_info = '-> ' . ( $action_name =~ /->/ ? '' : '/' ) . $action_name;
27 0         0 my ( $parent ) = grep exists $c->counter->{ $_ }, $c->stack->[-1] || ();
28 0 0       0 $c->stats->profile(
29 0   0     0 begin => $stats_info,
30             uid => $uid,
31             $parent ? ( parent => $parent . $c->counter->{ $parent } ) : (),
32             );
33 0 0       0 push @$scope_guard, $stats_info;
34             }
35 0         0 push @{ $c->stack }, $action;
36              
37 3         12 # using a scope guard to unwind the Catalyst stack allows this call to
  3         64  
38             # happen as the last thing in the function, which avoids the need to
39             # explicitly recreate caller context with wantarray
40             $action->execute( $c->components->{ $action->class }, $c, @_ );
41             }
42 3         33  
43             my ( $c, $stats_info ) = @{ $_[0] };
44             $c->stats->profile( end => $stats_info ) if $stats_info;
45             pop @{ $c->stack };
46 3     3   498 }
  3         10  
47 3 50       8  
48 3         3 1;
  3         55  
49              
50              
51             =pod
52              
53             =encoding UTF-8
54              
55             =head1 NAME
56              
57             Catalyst::Plugin::Digress - A cleaner, simpler, action-only $c->forward
58              
59             =head1 SYNOPSIS
60              
61             $c->digress( 'some/other/action' );
62             $c->digress( 'action_in_same_controller' );
63             $c->digress( $self->action_for( 'action_in_same_controller' ) );
64            
65             my %form = $c->digress( 'validate_params', {
66             name => { required => 1 },
67             email => { type => 'Str' },
68             } );
69              
70             $c->digress( $c->view ); # FAIL: cannot digress to components
71              
72             =head1 DESCRIPTION
73              
74             This plugin gives you the useful part of the Catalyst C<forward> method without
75             the weirdness (or the madness).
76              
77             =head1 METHODS
78              
79             =head2 C<digress>
80              
81             This is akin to C<forward>, with the following differences:
82              
83             =over 2
84              
85             =item * It does not catch exceptions (the most important benefit).
86              
87             =item * It passes parameters like in a normal Perl method call.
88              
89             =item * It does not mess with C<< $c->request->arguments >>.
90              
91             =item * It preserves list vs scalar context for the call.
92              
93             =item *
94              
95             It does not walk the Perl call stack every time (or ever, even once)
96             to figure out what its own name was (or for any other purpose).
97              
98             =item *
99              
100             It cannot forward to components, only actions
101             (because don’t ask how forwarding to components works).
102              
103             =back
104              
105             In other words, is almost identical to a straight method call:
106              
107             package MyApp::Controller::Some;
108             sub other_action : Private { ... }
109              
110             package MyApp::Controller::Root;
111             sub index : Path {
112             my ( $c, @some_args ) = ( shift, @_ );
113             # ...
114             my @some_return = $c->digress( '/some/other_action', @any_old_args );
115             # this is nearly identical to the following line:
116             my @some_return = $c->controller( 'Some' )->other_action( $c, @any_old_args );
117             # ...
118             }
119              
120             Except, of course, that it takes an action path instead of a plain method name,
121             and it maintains the Catalyst action stack for you just like C<forward> would,
122             which keeps various Catalyst mechanisms working, such as calling C<forward> and
123             friends from C<other_action> with a local action name.
124              
125             =head1 AUTHOR
126              
127             Aristotle Pagaltzis <pagaltzis@gmx.de>
128              
129             =head1 COPYRIGHT AND LICENSE
130              
131             This software is copyright (c) 2021 by Aristotle Pagaltzis.
132              
133             This is free software; you can redistribute it and/or modify it under
134             the same terms as the Perl 5 programming language system itself.
135              
136             =cut