|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */ 00097 class PEAR_Exception extends Exception 00098 { 00099 const OBSERVER_PRINT = -2; 00100 const OBSERVER_TRIGGER = -4; 00101 const OBSERVER_DIE = -8; 00102 protected $cause; 00103 private static $_observers = array(); 00104 private static $_uniqueid = 0; 00105 private $_trace; 00106 00121 public function __construct($message, $p2 = null, $p3 = null) 00122 { 00123 if (is_int($p2)) { 00124 $code = $p2; 00125 $this->cause = null; 00126 } elseif (is_object($p2) || is_array($p2)) { 00127 // using is_object allows both Exception and PEAR_Error 00128 if (is_object($p2) && !($p2 instanceof Exception)) { 00129 if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) { 00130 throw new PEAR_Exception('exception cause must be Exception, ' . 00131 'array, or PEAR_Error'); 00132 } 00133 } 00134 $code = $p3; 00135 if (is_array($p2) && isset($p2['message'])) { 00136 // fix potential problem of passing in a single warning 00137 $p2 = array($p2); 00138 } 00139 $this->cause = $p2; 00140 } else { 00141 $code = null; 00142 $this->cause = null; 00143 } 00144 parent::__construct($message, $code); 00145 $this->signal(); 00146 } 00147 00156 public static function addObserver($callback, $label = 'default') 00157 { 00158 self::$_observers[$label] = $callback; 00159 } 00160 00161 public static function removeObserver($label = 'default') 00162 { 00163 unset(self::$_observers[$label]); 00164 } 00165 00169 public static function getUniqueId() 00170 { 00171 return self::$_uniqueid++; 00172 } 00173 00174 private function signal() 00175 { 00176 foreach (self::$_observers as $func) { 00177 if (is_callable($func)) { 00178 call_user_func($func, $this); 00179 continue; 00180 } 00181 settype($func, 'array'); 00182 switch ($func[0]) { 00183 case self::OBSERVER_PRINT : 00184 $f = (isset($func[1])) ? $func[1] : '%s'; 00185 printf($f, $this->getMessage()); 00186 break; 00187 case self::OBSERVER_TRIGGER : 00188 $f = (isset($func[1])) ? $func[1] : E_USER_NOTICE; 00189 trigger_error($this->getMessage(), $f); 00190 break; 00191 case self::OBSERVER_DIE : 00192 $f = (isset($func[1])) ? $func[1] : '%s'; 00193 die(printf($f, $this->getMessage())); 00194 break; 00195 default: 00196 trigger_error('invalid observer type', E_USER_WARNING); 00197 } 00198 } 00199 } 00200 00215 public function getErrorData() 00216 { 00217 return array(); 00218 } 00219 00225 public function getCause() 00226 { 00227 return $this->cause; 00228 } 00229 00234 public function getCauseMessage(&$causes) 00235 { 00236 $trace = $this->getTraceSafe(); 00237 $cause = array('class' => get_class($this), 00238 'message' => $this->message, 00239 'file' => 'unknown', 00240 'line' => 'unknown'); 00241 if (isset($trace[0])) { 00242 if (isset($trace[0]['file'])) { 00243 $cause['file'] = $trace[0]['file']; 00244 $cause['line'] = $trace[0]['line']; 00245 } 00246 } 00247 $causes[] = $cause; 00248 if ($this->cause instanceof PEAR_Exception) { 00249 $this->cause->getCauseMessage($causes); 00250 } elseif ($this->cause instanceof Exception) { 00251 $causes[] = array('class' => get_class($this->cause), 00252 'message' => $this->cause->getMessage(), 00253 'file' => $this->cause->getFile(), 00254 'line' => $this->cause->getLine()); 00255 } elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) { 00256 $causes[] = array('class' => get_class($this->cause), 00257 'message' => $this->cause->getMessage(), 00258 'file' => 'unknown', 00259 'line' => 'unknown'); 00260 } elseif (is_array($this->cause)) { 00261 foreach ($this->cause as $cause) { 00262 if ($cause instanceof PEAR_Exception) { 00263 $cause->getCauseMessage($causes); 00264 } elseif ($cause instanceof Exception) { 00265 $causes[] = array('class' => get_class($cause), 00266 'message' => $cause->getMessage(), 00267 'file' => $cause->getFile(), 00268 'line' => $cause->getLine()); 00269 } elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) { 00270 $causes[] = array('class' => get_class($cause), 00271 'message' => $cause->getMessage(), 00272 'file' => 'unknown', 00273 'line' => 'unknown'); 00274 } elseif (is_array($cause) && isset($cause['message'])) { 00275 // PEAR_ErrorStack warning 00276 $causes[] = array( 00277 'class' => $cause['package'], 00278 'message' => $cause['message'], 00279 'file' => isset($cause['context']['file']) ? 00280 $cause['context']['file'] : 00281 'unknown', 00282 'line' => isset($cause['context']['line']) ? 00283 $cause['context']['line'] : 00284 'unknown', 00285 ); 00286 } 00287 } 00288 } 00289 } 00290 00291 public function getTraceSafe() 00292 { 00293 if (!isset($this->_trace)) { 00294 $this->_trace = $this->getTrace(); 00295 if (empty($this->_trace)) { 00296 $backtrace = debug_backtrace(); 00297 $this->_trace = array($backtrace[count($backtrace)-1]); 00298 } 00299 } 00300 return $this->_trace; 00301 } 00302 00303 public function getErrorClass() 00304 { 00305 $trace = $this->getTraceSafe(); 00306 return $trace[0]['class']; 00307 } 00308 00309 public function getErrorMethod() 00310 { 00311 $trace = $this->getTraceSafe(); 00312 return $trace[0]['function']; 00313 } 00314 00315 public function __toString() 00316 { 00317 if (isset($_SERVER['REQUEST_URI'])) { 00318 return $this->toHtml(); 00319 } 00320 return $this->toText(); 00321 } 00322 00323 public function toHtml() 00324 { 00325 $trace = $this->getTraceSafe(); 00326 $causes = array(); 00327 $this->getCauseMessage($causes); 00328 $html = '<table style="border: 1px" cellspacing="0">' . "\n"; 00329 foreach ($causes as $i => $cause) { 00330 $html .= '<tr><td colspan="3" style="background: #ff9999">' 00331 . str_repeat('-', $i) . ' <b>' . $cause['class'] . '</b>: ' 00332 . htmlspecialchars($cause['message']) . ' in <b>' . $cause['file'] . '</b> ' 00333 . 'on line <b>' . $cause['line'] . '</b>' 00334 . "</td></tr>\n"; 00335 } 00336 $html .= '<tr><td colspan="3" style="background-color: #aaaaaa; text-align: center; font-weight: bold;">Exception trace</td></tr>' . "\n" 00337 . '<tr><td style="text-align: center; background: #cccccc; width:20px; font-weight: bold;">#</td>' 00338 . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Function</td>' 00339 . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Location</td></tr>' . "\n"; 00340 00341 foreach ($trace as $k => $v) { 00342 $html .= '<tr><td style="text-align: center;">' . $k . '</td>' 00343 . '<td>'; 00344 if (!empty($v['class'])) { 00345 $html .= $v['class'] . $v['type']; 00346 } 00347 $html .= $v['function']; 00348 $args = array(); 00349 if (!empty($v['args'])) { 00350 foreach ($v['args'] as $arg) { 00351 if (is_null($arg)) $args[] = 'null'; 00352 elseif (is_array($arg)) $args[] = 'Array'; 00353 elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')'; 00354 elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false'; 00355 elseif (is_int($arg) || is_double($arg)) $args[] = $arg; 00356 else { 00357 $arg = (string)$arg; 00358 $str = htmlspecialchars(substr($arg, 0, 16)); 00359 if (strlen($arg) > 16) $str .= '…'; 00360 $args[] = "'" . $str . "'"; 00361 } 00362 } 00363 } 00364 $html .= '(' . implode(', ',$args) . ')' 00365 . '</td>' 00366 . '<td>' . (isset($v['file']) ? $v['file'] : 'unknown') 00367 . ':' . (isset($v['line']) ? $v['line'] : 'unknown') 00368 . '</td></tr>' . "\n"; 00369 } 00370 $html .= '<tr><td style="text-align: center;">' . ($k+1) . '</td>' 00371 . '<td>{main}</td>' 00372 . '<td> </td></tr>' . "\n" 00373 . '</table>'; 00374 return $html; 00375 } 00376 00377 public function toText() 00378 { 00379 $causes = array(); 00380 $this->getCauseMessage($causes); 00381 $causeMsg = ''; 00382 foreach ($causes as $i => $cause) { 00383 $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': ' 00384 . $cause['message'] . ' in ' . $cause['file'] 00385 . ' on line ' . $cause['line'] . "\n"; 00386 } 00387 return $causeMsg . $this->getTraceAsString(); 00388 } 00389 }