File Coverage

blib/lib/HTML/MasonX/Free/Request.pm
Criterion Covered Total %
statement 15 81 18.5
branch 0 36 0.0
condition 0 3 0.0
subroutine 5 6 83.3
pod 1 1 100.0
total 21 127 16.5


line stmt bran cond sub pod time code
1 2     2   1288 use strict;
  2         5  
  2         66  
2 2     2   10 use warnings;
  2         19  
  2         107  
3             package HTML::MasonX::Free::Request;
4             {
5             $HTML::MasonX::Free::Request::VERSION = '0.005';
6             }
7 2     2   10 use parent 'HTML::Mason::Request';
  2         4  
  2         13  
8             # ABSTRACT: a request class that eliminates the wrapping chain
9              
10 2     2   155 use Log::Any qw($log);
  2         6  
  2         36  
11 2         15 use HTML::Mason::Exceptions( abbr => [qw(error param_error syntax_error
12 2     2   223 top_level_not_found_error error)] );
  2         4  
13              
14             # BEGIN DIRECT THEFT FROM HTML-Mason 1.50
15             sub exec {
16 0     0 1   my ($self) = @_;
17              
18             # If the request failed to initialize, the error has already been handled
19             # at the bottom of _initialize(); just return.
20 0 0         return unless $self->initialized();
21              
22 0 0         local $SIG{'__DIE__'} = $self->component_error_handler
23             if $self->component_error_handler;
24              
25             # Cheap way to prevent users from executing the same request twice.
26             #
27 0 0         if ($self->{execd}++) {
28 0           error "Can only call exec() once for a given request object. Did you want to use a subrequest?";
29             }
30              
31             # Check for infinite subrequest loop.
32             #
33 0 0         error "subrequest depth > " . $self->max_recurse . " (infinite subrequest loop?)"
34             if $self->request_depth > $self->max_recurse;
35              
36             #
37             # $m is a dynamically scoped global containing this
38             # request. This needs to be defined in the HTML::Mason::Commands
39             # package, as well as the component package if that is different.
40             #
41 0           local $HTML::Mason::Commands::m = $self;
42              
43             # Dynamically scoped global pointing at the top of the request stack.
44             #
45 0           $self->{top_stack} = undef;
46              
47             # Save context of subroutine for use inside eval.
48 0           my $wantarray = wantarray;
49 0           my @result;
50              
51             # Initialize output buffer to interpreter's preallocated buffer
52             # before clearing, to reduce memory reallocations.
53             #
54 0           $self->{request_buffer} = $self->interp->preallocated_output_buffer;
55 0           $self->{request_buffer} = '';
56              
57 0 0         $log->debugf("starting request for '%s'", $self->request_comp->title)
58             if $log->is_debug;
59              
60 0           eval {
61             # Build wrapper chain and index.
62 0           my $request_comp = $self->request_comp;
63 0           my $first_comp;
64             {
65 0           my @wrapper_chain = ($request_comp);
  0            
66              
67             ## XXX: eliminated for(;;) loop here -- rjbs, 2012-09-24
68 0           $first_comp = $wrapper_chain[0];
69 0           $self->{wrapper_chain} = [@wrapper_chain];
70 0           $self->{wrapper_index} = { map
71 0           { $wrapper_chain[$_]->comp_id => $_ }
72             (0..$#wrapper_chain)
73             };
74             }
75              
76             # Get original request_args array reference to avoid copying.
77 0           my $request_args = $self->{request_args};
78             {
79 0           local *SELECTED;
  0            
80 0           tie *SELECTED, 'Tie::Handle::Mason';
81              
82 0           my $old = select SELECTED;
83 0           my $mods = {base_comp => $request_comp, store => \($self->{request_buffer}), flushable => 1};
84              
85 0 0         if ($self->{has_plugins}) {
86 0           my $context = bless
87             [$self, $request_args],
88             'HTML::Mason::Plugin::Context::StartRequest';
89 0           eval {
90 0           foreach my $plugin_instance (@{$self->plugin_instances}) {
  0            
91 0           $plugin_instance->start_request_hook( $context );
92             }
93             };
94 0 0         if ($@) {
95 0           select $old;
96 0           rethrow_exception $@;
97             }
98             }
99              
100 0 0         if ($wantarray) {
    0          
101 0           @result = eval {$self->comp($mods, $first_comp, @$request_args)};
  0            
102             } elsif (defined($wantarray)) {
103 0           $result[0] = eval {$self->comp($mods, $first_comp, @$request_args)};
  0            
104             } else {
105 0           eval {$self->comp($mods, $first_comp, @$request_args)};
  0            
106             }
107            
108 0           my $error = $@;
109              
110 0 0         if ($self->{has_plugins}) {
111             # plugins called in reverse order when exiting.
112 0           my $context = bless
113             [$self, $request_args, \$self->{request_buffer}, $wantarray, \@result, \$error],
114             'HTML::Mason::Plugin::Context::EndRequest';
115 0           eval {
116 0           foreach my $plugin_instance (@{$self->{plugin_instances_reverse}}) {
  0            
117 0           $plugin_instance->end_request_hook( $context );
118             }
119             };
120 0 0         if ($@) {
121             # plugin errors take precedence over component errors
122 0           $error = $@;
123             }
124             }
125            
126 0           select $old;
127 0           rethrow_exception $error;
128             }
129             };
130              
131 0 0         $log->debugf("finishing request for '%s'", $self->request_comp->title)
132             if $log->is_debug;
133              
134             # Purge code cache if necessary.
135 0           $self->interp->purge_code_cache;
136              
137             # Handle errors.
138 0           my $err = $@;
139 0 0 0       if ($err and !$self->_aborted_or_declined($err)) {
140 0           $self->_handle_error($err);
141 0           return;
142             }
143              
144             # If there's anything in the output buffer, send it to out_method.
145             # Otherwise skip out_method call to avoid triggering side effects
146             # (e.g. HTTP header sending).
147 0 0         if (length($self->{request_buffer}) > 0) {
148 0           $self->out_method->($self->{request_buffer});
149             }
150              
151             # Return aborted value or result.
152 0 0         @result = ($err->aborted_value) if $self->aborted($err);
153 0 0         @result = ($err->declined_value) if $self->declined($err);
154 0 0         return $wantarray ? @result : defined($wantarray) ? $result[0] : undef;
    0          
155             }
156             # BEGIN DIRECT THEFT FROM HTML-Mason 1.50
157              
158             1;
159              
160             __END__
161              
162             =pod
163              
164             =head1 NAME
165              
166             HTML::MasonX::Free::Request - a request class that eliminates the wrapping chain
167              
168             =head1 VERSION
169              
170             version 0.005
171              
172             =head1 AUTHOR
173              
174             Ricardo Signes <rjbs@cpan.org>
175              
176             =head1 COPYRIGHT AND LICENSE
177              
178             This software is copyright (c) 2013 by Ricardo Signes.
179              
180             This is free software; you can redistribute it and/or modify it under
181             the same terms as the Perl 5 programming language system itself.
182              
183             =cut