lib/TWiki/OopsException.pm
changeset 0 414e01d06fd5
equal deleted inserted replaced
-1:000000000000 0:414e01d06fd5
       
     1 # Module of TWiki Enterprise Collaboration Platform, http://TWiki.org/
       
     2 #
       
     3 # Copyright (C) 2005-2007 TWiki Contributors.
       
     4 # All Rights Reserved. TWiki Contributors
       
     5 # are listed in the AUTHORS file in the root of this distribution.
       
     6 # NOTE: Please extend that file, not this notice.
       
     7 #
       
     8 # This program is free software; you can redistribute it and/or
       
     9 # modify it under the terms of the GNU General Public License
       
    10 # as published by the Free Software Foundation; either version 2
       
    11 # of the License, or (at your option) any later version. For
       
    12 # more details read LICENSE in the root of this distribution.
       
    13 #
       
    14 # This program is distributed in the hope that it will be useful,
       
    15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
       
    17 #
       
    18 # As per the GPL, removal of this notice is prohibited.
       
    19 
       
    20 =pod twiki
       
    21 
       
    22 ---+ package TWiki::OopsException
       
    23 
       
    24 Exception used to raise a request to redirect to an Oops URL.
       
    25 
       
    26 An OopsException thrown anywhere in the code will redirect the
       
    27 browser to a url based on the =oops= script. =oops= requires
       
    28 the name of an oops template file from the =templates= directory.
       
    29 This file will be expanded and the
       
    30 parameter values passed to the exception instantiated. The
       
    31 result will be shown in the browser.
       
    32 
       
    33 Plugins may throw TWiki::OopsException. For example:
       
    34 
       
    35 <verbatim>
       
    36 use Error;
       
    37 
       
    38 ...
       
    39 
       
    40 throw TWiki::OopsException( 'bathplugin',
       
    41                             def => 'toestuck',
       
    42                             web => $web,
       
    43                             topic => $topic,
       
    44                             params => [ 'bigtoe', 'hot tap' ] );
       
    45 
       
    46 =cut
       
    47 
       
    48 package TWiki::OopsException;
       
    49 use base 'Error';
       
    50 
       
    51 use strict;
       
    52 use Error;
       
    53 use Assert;
       
    54 
       
    55 =pod
       
    56 
       
    57 ---++ ClassMethod new( $template, ...)
       
    58    * =template= is the name of an oops template. e.g. 'bathplugin' refers to =templates/oopsbathplugin.tmpl=
       
    59 The remaining parameters are interpreted as key-value pairs. The following keys are used:
       
    60    * =web= will be used as the web for the oops
       
    61    * =topic= will be used as the topic for the oops
       
    62    * =def= - is the (optional) name of a TMPL:DEF within the template
       
    63    * =keep= - if set, the exception handler should try its damnedest to retain parameter values from the query.
       
    64    * =params= is a reference to an array of parameters. These will be substituted for !%PARAM1%, !%PARAM2% ... !%PARAMn% in the template.
       
    65 
       
    66 For an example of how to use the =def= parameter, see the =oopsattention=
       
    67 template.
       
    68 
       
    69 NOTE: parameter values are automatically and unconditionally entity-encoded
       
    70 
       
    71 =cut
       
    72 
       
    73 sub new {
       
    74     my $class = shift;
       
    75     my $template = shift;
       
    76     my $this = bless( $class->SUPER::new(), $class );
       
    77     $this->{template} = $template;
       
    78     ASSERT( scalar( @_ ) % 2 == 0, join( ";", map { $_ || 'undef'} @_ ) )
       
    79       if DEBUG;
       
    80     while ( my $key = shift @_ ) {
       
    81         my $val = shift @_;
       
    82         if( $key eq 'params' ) {
       
    83             if( ref( $val ) ne 'ARRAY') {
       
    84                 $val = [ $val ];
       
    85             }
       
    86             $this->{params} = $val;
       
    87         } else {
       
    88             $this->{$key} = $val || '';
       
    89         }
       
    90     }
       
    91     return $this;
       
    92 }
       
    93 
       
    94 =pod
       
    95 
       
    96 ---++ ObjectMethod stringify( [$session] ) -> $string
       
    97 
       
    98 Generates a string representation for the object. if a session is passed in,
       
    99 and the exception specifies a def, then that def is expanded. This is to allow
       
   100 internal expansion of oops exceptions for example when performing bulk
       
   101 operations, and also for debugging.
       
   102 
       
   103 =cut
       
   104 
       
   105 sub stringify {
       
   106     my( $this, $session ) = @_;
       
   107 
       
   108     if ($this->{template} && $this->{def} && $session) {
       
   109         # load the defs
       
   110         $session->templates->readTemplate( 'oops'.$this->{template},
       
   111                                              $session->getSkin() );
       
   112         my $message = $session->templates->expandTemplate( $this->{def} );
       
   113         $message = $session->handleCommonTags(
       
   114             $message, $this->{web}, $this->{topic} );
       
   115         my $n = 1;
       
   116         foreach my $param ( @{$this->{params}} ) {
       
   117             $message =~ s/%PARAM$n%/$param/g;
       
   118             $n++;
       
   119         }
       
   120         return $message;
       
   121     } else {
       
   122         my $s = 'OopsException(';
       
   123         $s .= $this->{template};
       
   124         $s .= '/'.$this->{def} if $this->{def};
       
   125         $s .= ' web=>'.$this->{web} if $this->{web};
       
   126         $s .= ' topic=>'.$this->{topic} if $this->{topic};
       
   127         $s .= ' keep=>1' if $this->{keep};
       
   128         if( defined $this->{params} ) {
       
   129             $s .= ' params=>['.join( ',', @{$this->{params}} ).']';
       
   130         }
       
   131         return $s.')';
       
   132     }
       
   133 }
       
   134 
       
   135 =pod
       
   136 
       
   137 ---++ ObjectMethod redirect( $twiki )
       
   138 
       
   139 Generate a redirect to an 'oops' script for this exception.
       
   140 
       
   141 If the 'keep' parameter is set in the
       
   142 exception, it saves parameter values into the query as well. This is needed
       
   143 if the query string might get lost during a passthrough, due to a POST
       
   144 being redirected to a GET.
       
   145 
       
   146 =cut
       
   147 
       
   148 sub redirect {
       
   149     my( $this, $session ) = @_;
       
   150 
       
   151     my @p = ();
       
   152 
       
   153     $this->{template} = "oops$this->{template}" unless
       
   154       $this->{template} =~ /^oops/;
       
   155     push( @p, template => $this->{template} );
       
   156     push( @p, def => $this->{def}) if $this->{def};
       
   157     my $n = 1;
       
   158     push( @p, map { 'param'.($n++) => $_ } @{$this->{params}} );
       
   159     my $url = $session->getScriptUrl(
       
   160         1, 'oops', $this->{web}, $this->{topic}, @p);
       
   161     while( my $p = shift( @p )) {
       
   162         $session->{cgiQuery}->param(
       
   163             -name => $p, -value => shift( @p ));
       
   164     }
       
   165     $session->redirect( $url, 1 );
       
   166 }
       
   167 
       
   168 1;