← Index
NYTProf Performance Profile   « block view • line view • sub view »
For /usr/local/src/github.com/foswiki/core/bin/view
  Run on Sun Dec 4 17:17:59 2011
Reported on Sun Dec 4 17:27:07 2011

Filename/usr/local/src/github.com/foswiki/core/lib/Foswiki/OopsException.pm
StatementsExecuted 11 statements in 1.24ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
11124µs31µsFoswiki::OopsException::::BEGIN@93Foswiki::OopsException::BEGIN@93
11117µs58µsFoswiki::OopsException::::BEGIN@99Foswiki::OopsException::BEGIN@99
11116µs34µsFoswiki::OopsException::::BEGIN@94Foswiki::OopsException::BEGIN@94
1119µs9µsFoswiki::OopsException::::BEGIN@96Foswiki::OopsException::BEGIN@96
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
68API version $Date$ (revision $Rev$)
69
70*Since* _date_ indicates where functions or parameters have been added since
71the baseline of the API (TWiki release 4.2.3). The _date_ indicates the
72earliest date of a Foswiki release that will support that function or
73parameter.
74
75*Deprecated* _date_ indicates where a function or parameters has been
76[[http://en.wikipedia.org/wiki/Deprecation][deprecated]]. Deprecated
77functions will still work, though they should
78_not_ be called in new plugins and should be replaced in older plugins
79as soon as possible. Deprecated parameters are simply ignored in Foswiki
80releases after _date_.
81
82*Until* _date_ indicates where a function or parameter has been removed.
83The _date_ indicates the latest date at which Foswiki releases still supported
84the function or parameter.
85
86=cut
87
88# THIS PACKAGE IS PART OF THE PUBLISHED API USED BY EXTENSION AUTHORS.
89# DO NOT CHANGE THE EXISTING APIS (well thought out extensions are OK)
90# AND ENSURE ALL POD DOCUMENTATION IS COMPLETE AND ACCURATE.
91
92package Foswiki::OopsException;
93244µs238µs
# spent 31µs (24+7) within Foswiki::OopsException::BEGIN@93 which was called: # once (24µs+7µs) by Foswiki::Plugin::BEGIN@15 at line 93
use strict;
# spent 31µs making 1 call to Foswiki::OopsException::BEGIN@93 # spent 7µs making 1 call to strict::import
94242µs251µs
# spent 34µs (16+18) within Foswiki::OopsException::BEGIN@94 which was called: # once (16µs+18µs) by Foswiki::Plugin::BEGIN@15 at line 94
use warnings;
# spent 34µs making 1 call to Foswiki::OopsException::BEGIN@94 # spent 18µs making 1 call to warnings::import
95
96257µs19µs
# spent 9µs within Foswiki::OopsException::BEGIN@96 which was called: # once (9µs+0s) by Foswiki::Plugin::BEGIN@15 at line 96
use Error ();
# spent 9µs making 1 call to Foswiki::OopsException::BEGIN@96
9719µsour @ISA = ('Error');
98
9921.08ms299µs
# spent 58µs (17+41) within Foswiki::OopsException::BEGIN@99 which was called: # once (17µs+41µs) by Foswiki::Plugin::BEGIN@15 at line 99
use Assert;
# spent 58µs making 1 call to Foswiki::OopsException::BEGIN@99 # spent 41µs making 1 call to Assert::import
100
10112µsour $VERSION = '$Rev';
102
103=begin TML
104
105---++ ClassMethod new( $template, ...)
106 * =template= is the name of an oops template. e.g. 'bathplugin' refers to =templates/oopsbathplugin.tmpl=
107The remaining parameters are interpreted as key-value pairs. The following keys are used:
108 * =web= will be used as the web for the oops
109 * =topic= will be used as the topic for the oops
110 * =def= - is the (optional) name of a TMPL:DEF within the template
111 * =keep= - if set, the exception handler should try its damnedest to retain parameter values from the query.
112 * =params= is a reference to an array of parameters. These will be substituted for !%PARAM1%, !%PARAM2% ... !%PARAMn% in the template.
113
114For an example of how to use the =def= parameter, see the =oopsattention=
115template.
116
117NOTE: parameter values are automatically and unconditionally entity-encoded
118
119=cut
120
121sub new {
122 my $class = shift;
123 my $template = shift;
124 my $this = $class->SUPER::new();
125 $this->{template} = $template || 'generic';
126 $this->{status} = 500; # default server error
127 ASSERT( scalar(@_) % 2 == 0, join( ";", map { $_ || 'undef' } @_ ) )
128 if DEBUG;
129 while ( my $key = shift @_ ) {
130 my $val = shift @_;
131 if ( $key eq 'params' ) {
132 if ( ref($val) ne 'ARRAY' ) {
133 $val = [$val];
134 }
135 $this->{params} = $val;
136 }
137 else {
138 $this->{$key} = $val || '';
139 }
140 }
141 return $this;
142}
143
144=begin TML
145
146---++ ObjectMethod stringify( [$session] ) -> $string
147
148Generates a string representation for the object. if a session is passed in,
149and the exception specifies a def, then that def is expanded. This is to allow
150internal expansion of oops exceptions for example when performing bulk
151operations, and also for debugging.
152
153=cut
154
155sub stringify {
156 my ( $this, $session ) = @_;
157
158 if ( $this->{template} && $this->{def} && $session ) {
159
160 # load the defs
161 $session->templates->readTemplate( 'oops' . $this->{template},
162 no_oops => 1 );
163 my $message = $session->templates->expandTemplate( $this->{def} )
164 || "Failed to find '$this->{def}' in 'oops$this->{template}'";
165 my $topicObject =
166 Foswiki::Meta->new( $session, $this->{web}, $this->{topic} );
167 $message = $topicObject->expandMacros($message);
168 my $n = 1;
169 foreach my $param ( @{ $this->{params} } ) {
170 $message =~ s/%PARAM$n%/$param/g;
171 $n++;
172 }
173 return $message;
174 }
175 else {
176 my $s = 'OopsException(';
177 $s .= $this->{template};
178 $s .= '/' . $this->{def} if $this->{def};
179 $s .= ' web=>' . $this->{web} if $this->{web};
180 $s .= ' topic=>' . $this->{topic} if $this->{topic};
181 $s .= ' keep=>1' if $this->{keep};
182 if ( defined $this->{params} ) {
183 $s .= ' params=>[' . join( ',', @{ $this->{params} } ) . ']';
184 }
185 return $s . ')' . ( (DEBUG) ? $this->stacktrace : '' );
186 }
187}
188
189# Generate a redirect to an 'oops' script for this exception.
190#
191# If the 'keep' parameter is set in the
192# exception, it saves parameter values into the query as well. This is needed
193# if the query string might get lost during a passthrough, due to a POST
194# being redirected to a GET.
195# This redirect has been replaced by the generate function below and should
196# not be called in new code.
197sub redirect {
198 my ( $this, $session ) = @_;
199
200 my @p = $this->_prepareResponse($session);
201 my $url =
202 $session->getScriptUrl( 1, 'oops', $this->{web}, $this->{topic}, @p );
203 $session->redirect( $url, 1 );
204}
205
206=begin TML
207
208---++ ObjectMethod generate( $session )
209
210Generate an error page for the exception. This will output the error page
211to the browser. The default HTTP Status for an Oops page is 500. This
212can be overridden using the 'status => ' parameter to the constructor.
213
214=cut
215
216sub generate {
217 my ( $this, $session ) = @_;
218
219 my @p = $this->_prepareResponse($session);
220 $session->{response}->status( $this->{status} );
221 require Foswiki::UI::Oops;
222 Foswiki::UI::Oops::oops( $session, $this->{web}, $this->{topic},
223 $session->{request}, 0 );
224}
225
226sub _prepareResponse {
227 my ( $this, $session ) = @_;
228 my @p = ();
229
230 $this->{template} = "oops$this->{template}"
231 unless $this->{template} =~ /^oops/;
232 push( @p, template => $this->{template} );
233 push( @p, def => $this->{def} ) if $this->{def};
234 my $n = 1;
235 push( @p, map { 'param' . ( $n++ ) => $_ } @{ $this->{params} } );
236 while ( my $p = shift(@p) ) {
237 $session->{request}->param( -name => $p, -value => shift(@p) );
238 }
239 return @p;
240}
241
24216µs1;
243__END__