File Coverage

blib/lib/HTML/MasonX/Free/Request.pm
Criterion Covered Total %
statement 59 81 72.8
branch 16 36 44.4
condition 1 3 33.3
subroutine 6 6 100.0
pod 1 1 100.0
total 83 127 65.3


line stmt bran cond sub pod time code
1 3     3   1416 use strict;
  3         6  
  3         87  
2 3     3   17 use warnings;
  3         4  
  3         122  
3             package HTML::MasonX::Free::Request 0.007;
4              
5             # ABSTRACT: a request class that eliminates the wrapping chain
6 3     3   17 use parent 'HTML::Mason::Request';
  3         6  
  3         16  
7              
8             #pod =head1 OVERVIEW
9             #pod
10             #pod You don't want to know about this class. The basic thing is: if you're using
11             #pod L<HTML::MasonX::Free::Resolver>, you should use this.
12             #pod
13             #pod If you want a little more information: this gets rid of the notion of
14             #pod automatically execing the whole wrapping chain (like autohandlers) for
15             #pod components. It's gross, but it can make things a fair bit simpler.
16             #pod
17             #pod =cut
18              
19 3     3   220 use Log::Any qw($log);
  3         22  
  3         67  
20 3         30 use HTML::Mason::Exceptions( abbr => [qw(error param_error syntax_error
21 3     3   1455 top_level_not_found_error error)] );
  3         6  
22              
23             # BEGIN DIRECT THEFT FROM HTML-Mason 1.50
24             sub exec {
25 23     23 1 10688 my ($self) = @_;
26              
27             # If the request failed to initialize, the error has already been handled
28             # at the bottom of _initialize(); just return.
29 23 50       78 return unless $self->initialized();
30              
31 23 50       126 local $SIG{'__DIE__'} = $self->component_error_handler
32             if $self->component_error_handler;
33              
34             # Cheap way to prevent users from executing the same request twice.
35             #
36 23 50       658 if ($self->{execd}++) {
37 0         0 error "Can only call exec() once for a given request object. Did you want to use a subrequest?";
38             }
39              
40             # Check for infinite subrequest loop.
41             #
42 23 50       63 error "subrequest depth > " . $self->max_recurse . " (infinite subrequest loop?)"
43             if $self->request_depth > $self->max_recurse;
44              
45             #
46             # $m is a dynamically scoped global containing this
47             # request. This needs to be defined in the HTML::Mason::Commands
48             # package, as well as the component package if that is different.
49             #
50 23         187 local $HTML::Mason::Commands::m = $self;
51              
52             # Dynamically scoped global pointing at the top of the request stack.
53             #
54 23         38 $self->{top_stack} = undef;
55              
56             # Save context of subroutine for use inside eval.
57 23         41 my $wantarray = wantarray;
58 23         36 my @result;
59              
60             # Initialize output buffer to interpreter's preallocated buffer
61             # before clearing, to reduce memory reallocations.
62             #
63 23         46 $self->{request_buffer} = $self->interp->preallocated_output_buffer;
64 23         145 $self->{request_buffer} = '';
65              
66 23 50       108 $log->debugf("starting request for '%s'", $self->request_comp->title)
67             if $log->is_debug;
68              
69 23         349 eval {
70             # Build wrapper chain and index.
71 23         60 my $request_comp = $self->request_comp;
72 23         113 my $first_comp;
73             {
74 23         33 my @wrapper_chain = ($request_comp);
  23         47  
75              
76             ## XXX: eliminated for(;;) loop here -- rjbs, 2012-09-24
77 23         35 $first_comp = $wrapper_chain[0];
78 23         50 $self->{wrapper_chain} = [@wrapper_chain];
79             $self->{wrapper_index} = { map
80 23         61 { $wrapper_chain[$_]->comp_id => $_ }
  23         59  
81             (0..$#wrapper_chain)
82             };
83             }
84              
85             # Get original request_args array reference to avoid copying.
86 23         147 my $request_args = $self->{request_args};
87             {
88 23         36 local *SELECTED;
  23         74  
89 23         211 tie *SELECTED, 'Tie::Handle::Mason';
90              
91 23         195 my $old = select SELECTED;
92 23         94 my $mods = {base_comp => $request_comp, store => \($self->{request_buffer}), flushable => 1};
93              
94 23 50       65 if ($self->{has_plugins}) {
95 0         0 my $context = bless
96             [$self, $request_args],
97             'HTML::Mason::Plugin::Context::StartRequest';
98 0         0 eval {
99 0         0 foreach my $plugin_instance (@{$self->plugin_instances}) {
  0         0  
100 0         0 $plugin_instance->start_request_hook( $context );
101             }
102             };
103 0 0       0 if ($@) {
104 0         0 select $old;
105 0         0 rethrow_exception $@;
106             }
107             }
108              
109 23 50       75 if ($wantarray) {
    50          
110 0         0 @result = eval {$self->comp($mods, $first_comp, @$request_args)};
  0         0  
111             } elsif (defined($wantarray)) {
112 0         0 $result[0] = eval {$self->comp($mods, $first_comp, @$request_args)};
  0         0  
113             } else {
114 23         35 eval {$self->comp($mods, $first_comp, @$request_args)};
  23         84  
115             }
116            
117 23         648 my $error = $@;
118              
119 23 50       129 if ($self->{has_plugins}) {
120             # plugins called in reverse order when exiting.
121             my $context = bless
122 0         0 [$self, $request_args, \$self->{request_buffer}, $wantarray, \@result, \$error],
123             'HTML::Mason::Plugin::Context::EndRequest';
124 0         0 eval {
125 0         0 foreach my $plugin_instance (@{$self->{plugin_instances_reverse}}) {
  0         0  
126 0         0 $plugin_instance->end_request_hook( $context );
127             }
128             };
129 0 0       0 if ($@) {
130             # plugin errors take precedence over component errors
131 0         0 $error = $@;
132             }
133             }
134            
135 23         95 select $old;
136 23         76 rethrow_exception $error;
137             }
138             };
139              
140 23 50       255 $log->debugf("finishing request for '%s'", $self->request_comp->title)
141             if $log->is_debug;
142              
143             # Purge code cache if necessary.
144 23         218 $self->interp->purge_code_cache;
145              
146             # Handle errors.
147 23         192 my $err = $@;
148 23 50 33     60 if ($err and !$self->_aborted_or_declined($err)) {
149 0         0 $self->_handle_error($err);
150 0         0 return;
151             }
152              
153             # If there's anything in the output buffer, send it to out_method.
154             # Otherwise skip out_method call to avoid triggering side effects
155             # (e.g. HTTP header sending).
156 23 50       59 if (length($self->{request_buffer}) > 0) {
157 23         74 $self->out_method->($self->{request_buffer});
158             }
159              
160             # Return aborted value or result.
161 23 50       266 @result = ($err->aborted_value) if $self->aborted($err);
162 23 50       544 @result = ($err->declined_value) if $self->declined($err);
163 23 50       492 return $wantarray ? @result : defined($wantarray) ? $result[0] : undef;
    50          
164             }
165             # BEGIN DIRECT THEFT FROM HTML-Mason 1.50
166              
167             1;
168              
169             __END__
170              
171             =pod
172              
173             =encoding UTF-8
174              
175             =head1 NAME
176              
177             HTML::MasonX::Free::Request - a request class that eliminates the wrapping chain
178              
179             =head1 VERSION
180              
181             version 0.007
182              
183             =head1 OVERVIEW
184              
185             You don't want to know about this class. The basic thing is: if you're using
186             L<HTML::MasonX::Free::Resolver>, you should use this.
187              
188             If you want a little more information: this gets rid of the notion of
189             automatically execing the whole wrapping chain (like autohandlers) for
190             components. It's gross, but it can make things a fair bit simpler.
191              
192             =head1 PERL VERSION
193              
194             This library should run on perls released even a long time ago. It should work
195             on any version of perl released in the last five years.
196              
197             Although it may work on older versions of perl, no guarantee is made that the
198             minimum required version will not be increased. The version may be increased
199             for any reason, and there is no promise that patches will be accepted to lower
200             the minimum required perl.
201              
202             =head1 AUTHOR
203              
204             Ricardo Signes <cpan@semiotic.systems>
205              
206             =head1 COPYRIGHT AND LICENSE
207              
208             This software is copyright (c) 2022 by Ricardo Signes.
209              
210             This is free software; you can redistribute it and/or modify it under
211             the same terms as the Perl 5 programming language system itself.
212              
213             =cut