root/trunk/lib/SGL/ErrorHandler.php

Revision 4398, 11.7 kB (checked in by demian, 3 years ago)

updating constructor calls

Line 
1 <?php
2 /* Reminder: always indent with 4 spaces (no tabs). */
3 // +---------------------------------------------------------------------------+
4 // | Copyright (c) 2010, Demian Turner                                         |
5 // | All rights reserved.                                                      |
6 // |                                                                           |
7 // | Redistribution and use in source and binary forms, with or without        |
8 // | modification, are permitted provided that the following conditions        |
9 // | are met:                                                                  |
10 // |                                                                           |
11 // | o Redistributions of source code must retain the above copyright          |
12 // |   notice, this list of conditions and the following disclaimer.           |
13 // | o Redistributions in binary form must reproduce the above copyright       |
14 // |   notice, this list of conditions and the following disclaimer in the     |
15 // |   documentation and/or other materials provided with the distribution.    |
16 // | o The names of the authors may not be used to endorse or promote          |
17 // |   products derived from this software without specific prior written      |
18 // |   permission.                                                             |
19 // |                                                                           |
20 // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       |
21 // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT         |
22 // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR     |
23 // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT      |
24 // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,     |
25 // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT          |
26 // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     |
27 // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     |
28 // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       |
29 // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE     |
30 // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.      |
31 // |                                                                           |
32 // +---------------------------------------------------------------------------+
33 // | Seagull 1.0                                                               |
34 // +---------------------------------------------------------------------------+
35 // | ErrorHandler.php                                                          |
36 // +---------------------------------------------------------------------------+
37 // | Authors:   Peter James <petej@shaman.ca>                                  |
38 // |            Demian Turner <demian@phpkitchen.com>                          |
39 // +---------------------------------------------------------------------------+
40 // $Id: ErrorHandler.php,v 1.8 2005/05/28 19:32:12 demian Exp $
41
42 //  This class is based on Peter James' class of the same name, for more info
43 //  see http://php.shaman.ca/
44
45 /**
46  * Global error handler class, modifies behaviour for PHP errors, not PEAR.
47  *
48  * @package SGL
49  * @author  Demian Turner <demian@phpkitchen.com>
50  * @author  Peter James
51  * @version $Revision: 1.8 $
52  */
53 class SGL_ErrorHandler
54 {
55     var $errorType = array();
56     var $sourceContextOptions = array();
57
58     /**
59      * Constructor.
60      *
61      * @access  public
62      * @return  void
63      */
64     function __construct()
65     {
66         //  first dimension elements are PHP error types
67         //  2nd dimension elements are roughly PEAR Log's equivalents
68
69         //  nb: comment out Notice for equivalent of
70         //  error_reporting(E_ALL ^ E_NOTICE);
71         $this->errorType = array (
72            1   =>  array('Error', 3),
73            2   =>  array('Warning', 4),
74            4   =>  array('Parsing Error', 3),
75            8   =>  array('Notice', 5),
76            16  =>  array('Core Error', 3),
77            32  =>  array('Core Warning', 4),
78            64  =>  array('Compile Error', 3),
79            128 =>  array('Compile Warning', 4),
80            256 =>  array('User Error', 3),
81            512 =>  array('User Warning', 4),
82            1024=>  array('User Notice', 5),
83            2047=>  array('All', 7)
84             );
85         $this->sourceContextOptions = array('lines' => 5);
86     }
87
88     /**
89      * BC hack to assign custom error handler in a method.
90      *
91      * @access  public
92      * @return  void
93      */
94     function startHandler()
95     {
96         $GLOBALS['_SGL']['ERROR_HANDLER_OBJECT'] =  & $this;
97         $GLOBALS['_SGL']['ERROR_HANDLER_METHOD'] =  'errHandler';
98
99         //  inner function to handle redirection to a class method
100         function eh($errNo, $errStr, $file, $line, $context)
101         {
102             call_user_func(array(
103                &$GLOBALS['_SGL']['ERROR_HANDLER_OBJECT'],
104                 $GLOBALS['_SGL']['ERROR_HANDLER_METHOD']),
105                 $errNo, $errStr, $file, $line, $context
106             );
107         }
108         //  start handling errors
109         set_error_handler('eh');
110     }
111
112     /**
113      * Enhances PHP's default error handling.
114      *
115      *  o overrides notices in certain cases
116      *  o obeys @muffled errors,
117      *  o error logged to selected target
118      *  o context info presented for developer
119      *  o error data emailed to admin if threshold passed
120      *
121      * @access  public
122      * @param   int     $errNo      PHP's error number
123      * @param   string  $errStr     PHP's error message
124      * @param   string  $file       filename where error occurred
125      * @param   int     $line       line number where error occurred
126      * @param   string  $context    contextual info
127      * @return  void
128      */
129     function errHandler($errNo, $errStr, $file, $line, $context)
130     {
131         //  if an @ error suppression operator has been detected (0) return null
132         if (error_reporting() == 0) {
133             return null;
134         }
135         //  or if notices are temporarily being suppressed, return null
136         if ($GLOBALS['_SGL']['ERROR_OVERRIDE'] == true) {
137             if (error_reporting() == E_ALL ^ E_NOTICE) {
138                 return null;
139             }
140         }
141         if (in_array($errNo, array_keys($this->errorType))) {
142             $c = SGL_Config::singleton();
143             $conf = $c->getAll();
144             //  final param is 2nd dimension element from errorType array,
145             //  representing PEAR error codes mapped to PHP's
146
147             //  also, error obj is stored in $GLOBALS['_SGL']['ERRORS']
148             //  in the logMessage method
149             SGL::logMessage($errStr, $file, $line, $this->errorType[$errNo][1]);
150
151             //  if a debug sesssion has been started, or the site in in
152             //  development mode, send error info to screen
153             if (!$conf['debug']['production'] || SGL_Session::get('adminMode')) {
154                 $source = $this->_getSourceContext($file, $line);
155                 //  generate screen debug html
156                 //  type is 1st dimension element from $errorType array, ie,
157                 //  PHP error code
158                 $output = <<<EOF
159 <hr />
160 <div id="errorWrapper" class="errorContent">
161         <strong>MESSAGE</strong>: $errStr<br />
162         <strong>TYPE:</strong> {$this->errorType[$errNo][0]}<br />
163         <strong>FILE:</strong> $file<br />
164         <strong>LINE:</strong> $line<br />
165         <strong>DEBUG INFO:</strong>
166         <p>$source</p>
167 </div>
168 <hr />
169 EOF;
170                 if (SGL::runningFromCLI()) {
171                     $output = <<<EOL
172 MESSAGE: $errStr
173 TYPE: {$this->errorType[$errNo][0]}
174 FILE: $file
175 LINE: $line
176
177  --
178 EOL;
179                 }
180                 if (!empty($conf['log']['showErrors']) && $conf['log']['showErrors'] == true) {
181                     echo $output;
182                 }
183
184             } else {
185                 //  we're in production mode, suppress any errors from being displayed
186                 @ini_set('display_errors', 0);
187             }
188             //  email the error to admin if threshold reached
189             if ($this->errorType[$errNo][1] <= SGL_EMAIL_ADMIN_THRESHOLD) {
190
191                 //  get extra info
192                 $dbh SGL_DB::singleton();
193
194                 $aExtraInfo['callingURL'] = $_SERVER['SCRIPT_NAME'];
195                 $aExtraInfo['lastSQL'] = isset($dbh->last_query) ?
196                     $dbh->last_query : null;
197                 $aExtraInfo['userID'] = SGL_Session::get('uid');
198                 $aExtraInfo['clientData']['HTTP_REFERER'] = isset($_SERVER['HTTP_REFERER'])
199                     ? $_SERVER['HTTP_REFERER']
200                     : null;
201                 $aExtraInfo['clientData']['HTTP_USER_AGENT'] = isset($_SERVER['HTTP_USER_AGENT'])
202                     ? $_SERVER['HTTP_USER_AGENT']
203                     : null;
204                 $aExtraInfo['clientData']['REMOTE_ADDR'] = isset($_SERVER['REMOTE_ADDR'])
205                     ? $_SERVER['REMOTE_ADDR']
206                     : null;
207                 $aExtraInfo['clientData']['SERVER_PORT'] = isset($_SERVER['SERVER_PORT'])
208                     ? $_SERVER['SERVER_PORT']
209                     : null;
210
211                 //  store formatted output
212                 $info = print_r($aExtraInfo, true);
213
214                 //  rebuild error output w/out html
215                 $crlf = SGL_String::getCrlf();
216                 $output = $errStr . $crlf .
217                     'type: ' . $this->errorType[$errNo][0] . $crlf .
218                     'file: ' . $file . $crlf .
219                     'line: ' . $line . $crlf . $crlf;
220                 $message = $output . $info;
221                 @mail($conf['email']['admin'], 'ERROR OUTPUT FROM ' .
222                     $conf['site']['name'], $message);
223             }
224         }
225     }
226
227     /**
228      * Provides enhanced error info for developer.
229      *
230      * Gives 10 lines before and after error occurred, hightlight erroroneous
231      * line in red.
232      *
233      * @access  private
234      * @param   string  $file       filename where error occurred
235      * @param   int     $line       line number where error occurred
236      * @param   string  $context    contextual info
237      * @return  string  contextual error info
238      */
239     function _getSourceContext($file, $line)
240     {
241         $sourceContext = null;
242
243         //  check that file exists
244         if (!is_file($file)) {
245             $sourceContext = "Context cannot be shown - ($file) does not exist";
246
247         //  check if line number is valid
248         } elseif ((!is_int($line)) || ($line <= 0)) {
249             $sourceContext = "Context cannot be shown - ($line) is an invalid line number";
250         } else {
251             $lines = file($file);
252
253             //  get the source ## core dump in windows, scrap colour highlighting :-(
254             //  $source = highlight_file($file, true);
255             //  $lines = split("<br />", $source);
256             //  get line numbers
257             $start = $line - $this->sourceContextOptions['lines'] - 1;
258             $finish = $line + $this->sourceContextOptions['lines'];
259
260             //  get lines
261             if ($start < 0) {
262                 $start = 0;
263             }
264
265             if ($start >= count($lines)) {
266                 $start = count($lines) -1;
267             }
268
269             for ($i = $start; $i < $finish; $i++) {
270                 //  highlight line in question
271                 if ($i == ($line - 1)) {
272                     $context_lines[] = '<div class="error"><strong>' . ($i + 1) .
273                         "\t" . strip_tags($lines[$line -1]) . '</strong></div>';
274                 } else {
275                     $context_lines[] = '<strong>' . ($i + 1) .
276                         "</strong>\t" . @$lines[$i];
277                 }
278             }
279             $sourceContext = trim(join("<br />\n", $context_lines)) . "<br />\n";
280         }
281         return $sourceContext;
282     }
283 }
284 ?>
285
Note: See TracBrowser for help on using the browser.