← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 19:05:14 2015
Reported on Fri Jul 31 19:08:09 2015

Filename/var/www/foswiki11/lib/Foswiki/OopsException.pm
StatementsExecuted 10 statements in 696µs
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
11119µs32µsFoswiki::OopsException::::BEGIN@91Foswiki::OopsException::BEGIN@91
1119µs24µsFoswiki::OopsException::::BEGIN@97Foswiki::OopsException::BEGIN@97
1118µs14µsFoswiki::OopsException::::BEGIN@92Foswiki::OopsException::BEGIN@92
1113µs3µsFoswiki::OopsException::::BEGIN@94Foswiki::OopsException::BEGIN@94
0000s0sFoswiki::OopsException::::_prepareResponseFoswiki::OopsException::_prepareResponse
0000s0sFoswiki::OopsException::::generateFoswiki::OopsException::generate
0000s0sFoswiki::OopsException::::newFoswiki::OopsException::new
0000s0sFoswiki::OopsException::::redirectFoswiki::OopsException::redirect
0000s0sFoswiki::OopsException::::stringifyFoswiki::OopsException::stringify
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# See bottom of file for license and copyright information
2
3=begin TML
4
5---+ package Foswiki::OopsException
6
7Exception used to raise a request to output a preformatted page.
8
9Despite the name, =oops= is not used just for errors; it is also used
10for one-time redirection, for example during the registration process.
11
12The =Foswiki::UI::run= function, which is in the call stack for almost
13all cases where an =OopsException= will be thrown, traps the exception
14and outputs an =oops= page to the browser. This requires
15the name of a template file from the =templates= directory, which it
16expands. Parameter values passed to the exception are instantiated in
17the expanded template. The =oops= page is output with an HTTP status
18appropriate to the event that caused the exception (default 500).
19
20Extensions may throw =Foswiki::OopsException=. For example:
21
22<verbatim>
23use Error qw(:try);
24
25...
26
27throw Foswiki::OopsException( 'bathplugin',
28 status => 418,
29 web => $web,
30 topic => $topic,
31 params => [ 'big toe', 'stuck in', 'hot tap' ] );
32</verbatim>
33This will raise an exception that uses the =bathplugin.tmpl= template. If
34=UI::run= handles the exception it will generate a redirect to:
35<verbatim>
36oops?template=bathplugin;param1=bigtoe;param2=hot%20tap
37</verbatim>
38The =bathplugin.tmpl= might contain:
39(&lt;nop> inserted to prevent translation interface from extracting these examples)
40<verbatim>
41%TMPL:INCLUDE{"oops"}%
42%TMPL:DEF{"titleaction"}% %<nop>MAKETEXT{"Bathing problem"}% %TMPL:END%
43%TMPL:DEF{"heading"}%%<nop>MAKETEXT{"Problem filling bath"}%%TMPL:END%
44%TMPL:DEF{"topicactionbuttons"}%%TMPL:P{"oktopicaction"}%%TMPL:END%
45%TMPL:DEF{"script"}%<meta http-equiv="refresh" content="0;url=%SCRIPTURL{view}%/%WEB%/%TOPIC%" />%TMPL:END%
46%TMPL:DEF{"pagetitle"}%%TMPL:P{"heading"}%%TMPL:END%
47%TMPL:DEF{"webaction"}% *%<nop>MAKETEXT{"Warning"}%* %TMPL:END%
48%TMPL:DEF{"message"}%
49%<nop>MAKETEXT{"Your bath cannot be filled because your [_1] is [_2] the [_3]" args="drain,flooding,basement"}%%TMPL:END%
50</verbatim>
51In this case the =oops= page will be rendered with a 418 ("I'm a teapot")
52status in the HTTP header.
53
54A more practical example for plugins authors that does not require them to
55provide their own template file involves use of the generic message template
56available from =oopsattention.tmpl=:
57<verbatim>
58throw Foswiki::OopsException( 'oopsattention', def => 'generic',
59 params => [ Operation is not allowed ] );
60</verbatim>
61
62Note that to protect against cross site scripting all parameter values are
63automatically and unconditionally entity-encoded so you cannot pass macros
64if you need messages to be automatically translated you either need to handle
65it in the perl code before throwing Foswiki::OopsException or put the %MAKETEXT
66in the template. You cannot pass macros through the parameters.
67
68*Since* _date_ indicates where functions or parameters have been added since
69the baseline of the API (TWiki release 4.2.3). The _date_ indicates the
70earliest date of a Foswiki release that will support that function or
71parameter.
72
73*Deprecated* _date_ indicates where a function or parameters has been
74[[http://en.wikipedia.org/wiki/Deprecation][deprecated]]. Deprecated
75functions will still work, though they should
76_not_ be called in new plugins and should be replaced in older plugins
77as soon as possible. Deprecated parameters are simply ignored in Foswiki
78releases after _date_.
79
80*Until* _date_ indicates where a function or parameter has been removed.
81The _date_ indicates the latest date at which Foswiki releases still supported
82the function or parameter.
83
84=cut
85
86# THIS PACKAGE IS PART OF THE PUBLISHED API USED BY EXTENSION AUTHORS.
87# DO NOT CHANGE THE EXISTING APIS (well thought out extensions are OK)
88# AND ENSURE ALL POD DOCUMENTATION IS COMPLETE AND ACCURATE.
89
90package Foswiki::OopsException;
91226µs246µs
# spent 32µs (19+13) within Foswiki::OopsException::BEGIN@91 which was called: # once (19µs+13µs) by Foswiki::Plugin::BEGIN@15 at line 91
use strict;
# spent 32µs making 1 call to Foswiki::OopsException::BEGIN@91 # spent 13µs making 1 call to strict::import
92222µs219µs
# spent 14µs (8+5) within Foswiki::OopsException::BEGIN@92 which was called: # once (8µs+5µs) by Foswiki::Plugin::BEGIN@15 at line 92
use warnings;
# spent 14µs making 1 call to Foswiki::OopsException::BEGIN@92 # spent 5µs making 1 call to warnings::import
93
94240µs13µs
# spent 3µs within Foswiki::OopsException::BEGIN@94 which was called: # once (3µs+0s) by Foswiki::Plugin::BEGIN@15 at line 94
use Error ();
# spent 3µs making 1 call to Foswiki::OopsException::BEGIN@94
9516µsour @ISA = ('Error');
96
972599µs240µs
# spent 24µs (9+15) within Foswiki::OopsException::BEGIN@97 which was called: # once (9µs+15µs) by Foswiki::Plugin::BEGIN@15 at line 97
use Assert;
# spent 24µs making 1 call to Foswiki::OopsException::BEGIN@97 # spent 15µs making 1 call to Assert::import
98
99=begin TML
100
101---++ ClassMethod new( $template, ...)
102 * =template= is the name of an oops template. e.g. 'bathplugin' refers to =templates/oopsbathplugin.tmpl=
103The remaining parameters are interpreted as key-value pairs. The following keys are used:
104 * =web= will be used as the web for the oops
105 * =topic= will be used as the topic for the oops
106 * =def= - is the (optional) name of a TMPL:DEF within the template
107 * =keep= - if set, the exception handler should try its damnedest to retain parameter values from the query.
108 * =params= is a reference to an array of parameters. These will be substituted for !%PARAM1%, !%PARAM2% ... !%PARAMn% in the template.
109
110For an example of how to use the =def= parameter, see the =oopsattention=
111template.
112
113NOTE: parameter values are automatically and unconditionally entity-encoded
114
115=cut
116
117sub new {
118 my $class = shift;
119 my $template = shift;
120 my $this = $class->SUPER::new();
121 $this->{template} = $template || 'generic';
122 $this->{status} = 500; # default server error
123 ASSERT( scalar(@_) % 2 == 0, join( ";", map { $_ || 'undef' } @_ ) )
124 if DEBUG;
125 while ( my $key = shift @_ ) {
126 my $val = shift @_;
127 if ( $key eq 'params' ) {
128 if ( ref($val) ne 'ARRAY' ) {
129 $val = [$val];
130 }
131 $this->{params} = $val;
132 }
133 else {
134 $this->{$key} = $val || '';
135 }
136 }
137 return $this;
138}
139
140=begin TML
141
142---++ ObjectMethod stringify( [$session] ) -> $string
143
144Generates a string representation for the object. if a session is passed in,
145and the exception specifies a def, then that def is expanded. This is to allow
146internal expansion of oops exceptions for example when performing bulk
147operations, and also for debugging.
148
149=cut
150
151sub stringify {
152 my ( $this, $session ) = @_;
153
154 if ( $this->{template} && $this->{def} && $session ) {
155
156 # load the defs
157 $session->templates->readTemplate( 'oops' . $this->{template},
158 no_oops => 1 );
159 my $message = $session->templates->expandTemplate( $this->{def} )
160 || "Failed to find '$this->{def}' in 'oops$this->{template}'";
161 my $topicObject =
162 Foswiki::Meta->new( $session, $this->{web}, $this->{topic} );
163 $message = $topicObject->expandMacros($message);
164 my $n = 1;
165 foreach my $param ( @{ $this->{params} } ) {
166 $message =~ s/%PARAM$n%/$param/g;
167 $n++;
168 }
169 return $message;
170 }
171 else {
172 my $s = 'OopsException(';
173 $s .= $this->{template};
174 $s .= '/' . $this->{def} if $this->{def};
175 $s .= ' web=>' . $this->{web} if $this->{web};
176 $s .= ' topic=>' . $this->{topic} if $this->{topic};
177 $s .= ' keep=>1' if $this->{keep};
178 if ( defined $this->{params} ) {
179 $s .= ' params=>[' . join( ',', @{ $this->{params} } ) . ']';
180 }
181 return $s . ')' . ( (DEBUG) ? $this->stacktrace : '' );
182 }
183}
184
185# Generate a redirect to an 'oops' script for this exception.
186#
187# If the 'keep' parameter is set in the
188# exception, it saves parameter values into the query as well. This is needed
189# if the query string might get lost during a passthrough, due to a POST
190# being redirected to a GET.
191# This redirect has been replaced by the generate function below and should
192# not be called in new code.
193sub redirect {
194 my ( $this, $session ) = @_;
195
196 my @p = $this->_prepareResponse($session);
197 my $url =
198 $session->getScriptUrl( 1, 'oops', $this->{web}, $this->{topic}, @p );
199 $session->redirect( $url, 1 );
200}
201
202=begin TML
203
204---++ ObjectMethod generate( $session )
205
206Generate an error page for the exception. This will output the error page
207to the browser. The default HTTP Status for an Oops page is 500. This
208can be overridden using the 'status => ' parameter to the constructor.
209
210=cut
211
212sub generate {
213 my ( $this, $session ) = @_;
214
215 my @p = $this->_prepareResponse($session);
216 $session->{response}->status( $this->{status} );
217 require Foswiki::UI::Oops;
218 Foswiki::UI::Oops::oops( $session, $this->{web}, $this->{topic},
219 $session->{request}, 0 );
220}
221
222sub _prepareResponse {
223 my ( $this, $session ) = @_;
224 my @p = ();
225
226 $this->{template} = "oops$this->{template}"
227 unless $this->{template} =~ /^oops/;
228 push( @p, template => $this->{template} );
229 push( @p, def => $this->{def} ) if $this->{def};
230 my $n = 1;
231 push( @p, map { 'param' . ( $n++ ) => $_ } @{ $this->{params} } );
232 while ( my $p = shift(@p) ) {
233 $session->{request}->param( -name => $p, -value => shift(@p) );
234 }
235 return @p;
236}
237
23813µs1;
239__END__