PEAR
[ class tree: PEAR ] [ index: PEAR ] [ all elements ]

Source for file Exception.php

Documentation is available at Exception.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
  3. /**
  4.  * PEAR_Exception
  5.  *
  6.  * PHP versions 4 and 5
  7.  *
  8.  * @category   pear
  9.  * @package    PEAR
  10.  * @author     Tomas V. V. Cox <cox@idecnet.com>
  11.  * @author     Hans Lellelid <hans@velum.net>
  12.  * @author     Bertrand Mansion <bmansion@mamasam.com>
  13.  * @author     Greg Beaver <cellog@php.net>
  14.  * @copyright  1997-2009 The Authors
  15.  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
  16.  * @version    CVS: $Id: Exception.php 313023 2011-07-06 19:17:11Z dufuz $
  17.  * @link       http://pear.php.net/package/PEAR
  18.  * @since      File available since Release 1.3.3
  19.  */
  20.  
  21.  
  22. /**
  23.  * Base PEAR_Exception Class
  24.  *
  25.  * 1) Features:
  26.  *
  27.  * - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception))
  28.  * - Definable triggers, shot when exceptions occur
  29.  * - Pretty and informative error messages
  30.  * - Added more context info available (like class, method or cause)
  31.  * - cause can be a PEAR_Exception or an array of mixed
  32.  *   PEAR_Exceptions/PEAR_ErrorStack warnings
  33.  * - callbacks for specific exception classes and their children
  34.  *
  35.  * 2) Ideas:
  36.  *
  37.  * - Maybe a way to define a 'template' for the output
  38.  *
  39.  * 3) Inherited properties from PHP Exception Class:
  40.  *
  41.  * protected $message
  42.  * protected $code
  43.  * protected $line
  44.  * protected $file
  45.  * private   $trace
  46.  *
  47.  * 4) Inherited methods from PHP Exception Class:
  48.  *
  49.  * __clone
  50.  * __construct
  51.  * getMessage
  52.  * getCode
  53.  * getFile
  54.  * getLine
  55.  * getTraceSafe
  56.  * getTraceSafeAsString
  57.  * __toString
  58.  *
  59.  * 5) Usage example
  60.  *
  61.  * <code>
  62.  *  require_once 'PEAR/Exception.php';
  63.  *
  64.  *  class Test {
  65.  *     function foo() {
  66.  *         throw new PEAR_Exception('Error Message', ERROR_CODE);
  67.  *     }
  68.  *  }
  69.  *
  70.  *  function myLogger($pear_exception) {
  71.  *     echo $pear_exception->getMessage();
  72.  *  }
  73.  *  // each time a exception is thrown the 'myLogger' will be called
  74.  *  // (its use is completely optional)
  75.  *  PEAR_Exception::addObserver('myLogger');
  76.  *  $test = new Test;
  77.  *  try {
  78.  *     $test->foo();
  79.  *  } catch (PEAR_Exception $e) {
  80.  *     print $e;
  81.  *  }
  82.  * </code>
  83.  *
  84.  * @category   pear
  85.  * @package    PEAR
  86.  * @author     Tomas V.V.Cox <cox@idecnet.com>
  87.  * @author     Hans Lellelid <hans@velum.net>
  88.  * @author     Bertrand Mansion <bmansion@mamasam.com>
  89.  * @author     Greg Beaver <cellog@php.net>
  90.  * @copyright  1997-2009 The Authors
  91.  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
  92.  * @version    Release: 1.9.4
  93.  * @link       http://pear.php.net/package/PEAR
  94.  * @since      Class available since Release 1.3.3
  95.  *
  96.  */
  97. class PEAR_Exception extends Exception
  98. {
  99.     const OBSERVER_PRINT = -2;
  100.     const OBSERVER_TRIGGER = -4;
  101.     const OBSERVER_DIE = -8;
  102.     protected $cause;
  103.     private static $_observers = array();
  104.     private static $_uniqueid = 0;
  105.     private $_trace;
  106.  
  107.     /**
  108.      * Supported signatures:
  109.      *  - PEAR_Exception(string $message);
  110.      *  - PEAR_Exception(string $message, int $code);
  111.      *  - PEAR_Exception(string $message, Exception $cause);
  112.      *  - PEAR_Exception(string $message, Exception $cause, int $code);
  113.      *  - PEAR_Exception(string $message, PEAR_Error $cause);
  114.      *  - PEAR_Exception(string $message, PEAR_Error $cause, int $code);
  115.      *  - PEAR_Exception(string $message, array $causes);
  116.      *  - PEAR_Exception(string $message, array $causes, int $code);
  117.      * @param string exception message
  118.      * @param int|Exception|PEAR_Error|array|nullexception cause
  119.      * @param int|nullexception code or null
  120.      */
  121.     public function __construct($message$p2 = null$p3 = null)
  122.     {
  123.         if (is_int($p2)) {
  124.             $code $p2;
  125.             $this->cause = null;
  126.         elseif (is_object($p2|| is_array($p2)) {
  127.             // using is_object allows both Exception and PEAR_Error
  128.             if (is_object($p2&& !($p2 instanceof Exception)) {
  129.                 if (!class_exists('PEAR_Error'|| !($p2 instanceof PEAR_Error)) {
  130.                     throw new PEAR_Exception('exception cause must be Exception, ' .
  131.                         'array, or PEAR_Error');
  132.                 }
  133.             }
  134.             $code $p3;
  135.             if (is_array($p2&& isset($p2['message'])) {
  136.                 // fix potential problem of passing in a single warning
  137.                 $p2 = array($p2);
  138.             }
  139.             $this->cause = $p2;
  140.         else {
  141.             $code = null;
  142.             $this->cause = null;
  143.         }
  144.         parent::__construct($message$code);
  145.         $this->signal();
  146.     }
  147.  
  148.     /**
  149.      * @param mixed $callback  - A valid php callback, see php func is_callable()
  150.      *                          - A PEAR_Exception::OBSERVER_* constant
  151.      *                          - An array(const PEAR_Exception::OBSERVER_*,
  152.      *                            mixed $options)
  153.      * @param string $label    The name of the observer. Use this if you want
  154.      *                          to remove it later with removeObserver()
  155.      */
  156.     public static function addObserver($callback$label 'default')
  157.     {
  158.         self::$_observers[$label$callback;
  159.     }
  160.  
  161.     public static function removeObserver($label 'default')
  162.     {
  163.         unset(self::$_observers[$label]);
  164.     }
  165.  
  166.     /**
  167.      * @return int unique identifier for an observer
  168.      */
  169.     public static function getUniqueId()
  170.     {
  171.         return self::$_uniqueid++;
  172.     }
  173.  
  174.     private function signal()
  175.     {
  176.         foreach (self::$_observers as $func{
  177.             if (is_callable($func)) {
  178.                 call_user_func($func$this);
  179.                 continue;
  180.             }
  181.             settype($func'array');
  182.             switch ($func[0]{
  183.                 case self::OBSERVER_PRINT :
  184.                     $f (isset($func[1])) $func[1'%s';
  185.                     printf($f$this->getMessage());
  186.                     break;
  187.                 case self::OBSERVER_TRIGGER :
  188.                     $f (isset($func[1])) $func[1: E_USER_NOTICE;
  189.                     trigger_error($this->getMessage()$f);
  190.                     break;
  191.                 case self::OBSERVER_DIE :
  192.                     $f (isset($func[1])) $func[1'%s';
  193.                     die(printf($f$this->getMessage()));
  194.                     break;
  195.                 default:
  196.                     trigger_error('invalid observer type'E_USER_WARNING);
  197.             }
  198.         }
  199.     }
  200.  
  201.     /**
  202.      * Return specific error information that can be used for more detailed
  203.      * error messages or translation.
  204.      *
  205.      * This method may be overridden in child exception classes in order
  206.      * to add functionality not present in PEAR_Exception and is a placeholder
  207.      * to define API
  208.      *
  209.      * The returned array must be an associative array of parameter => value like so:
  210.      * <pre>
  211.      * array('name' => $name, 'context' => array(...))
  212.      * </pre>
  213.      * @return array 
  214.      */
  215.     public function getErrorData()
  216.     {
  217.         return array();
  218.     }
  219.  
  220.     /**
  221.      * Returns the exception that caused this exception to be thrown
  222.      * @access public
  223.      * @return Exception|arrayThe context of the exception
  224.      */
  225.     public function getCause()
  226.     {
  227.         return $this->cause;
  228.     }
  229.  
  230.     /**
  231.      * Function must be public to call on caused exceptions
  232.      * @param array 
  233.      */
  234.     public function getCauseMessage(&$causes)
  235.     {
  236.         $trace $this->getTraceSafe();
  237.         $cause = array('class'   => get_class($this),
  238.                        'message' => $this->message,
  239.                        'file' => 'unknown',
  240.                        'line' => 'unknown');
  241.         if (isset($trace[0])) {
  242.             if (isset($trace[0]['file'])) {
  243.                 $cause['file'$trace[0]['file'];
  244.                 $cause['line'$trace[0]['line'];
  245.             }
  246.         }
  247.         $causes[$cause;
  248.         if ($this->cause instanceof PEAR_Exception{
  249.             $this->cause->getCauseMessage($causes);
  250.         elseif ($this->cause instanceof Exception{
  251.             $causes[= array('class'   => get_class($this->cause),
  252.                               'message' => $this->cause->getMessage(),
  253.                               'file' => $this->cause->getFile(),
  254.                               'line' => $this->cause->getLine());
  255.         elseif (class_exists('PEAR_Error'&& $this->cause instanceof PEAR_Error{
  256.             $causes[= array('class' => get_class($this->cause),
  257.                               'message' => $this->cause->getMessage(),
  258.                               'file' => 'unknown',
  259.                               'line' => 'unknown');
  260.         elseif (is_array($this->cause)) {
  261.             foreach ($this->cause as $cause{
  262.                 if ($cause instanceof PEAR_Exception{
  263.                     $cause->getCauseMessage($causes);
  264.                 elseif ($cause instanceof Exception{
  265.                     $causes[= array('class'   => get_class($cause),
  266.                                    'message' => $cause->getMessage(),
  267.                                    'file' => $cause->getFile(),
  268.                                    'line' => $cause->getLine());
  269.                 elseif (class_exists('PEAR_Error'&& $cause instanceof PEAR_Error{
  270.                     $causes[= array('class' => get_class($cause),
  271.                                       'message' => $cause->getMessage(),
  272.                                       'file' => 'unknown',
  273.                                       'line' => 'unknown');
  274.                 elseif (is_array($cause&& isset($cause['message'])) {
  275.                     // PEAR_ErrorStack warning
  276.                     $causes[= array(
  277.                         'class' => $cause['package'],
  278.                         'message' => $cause['message'],
  279.                         'file' => isset($cause['context']['file']?
  280.                                             $cause['context']['file':
  281.                                             'unknown',
  282.                         'line' => isset($cause['context']['line']?
  283.                                             $cause['context']['line':
  284.                                             'unknown',
  285.                     );
  286.                 }
  287.             }
  288.         }
  289.     }
  290.  
  291.     public function getTraceSafe()
  292.     {
  293.         if (!isset($this->_trace)) {
  294.             $this->_trace $this->getTrace();
  295.             if (empty($this->_trace)) {
  296.                 $backtrace debug_backtrace();
  297.                 $this->_trace = array($backtrace[count($backtrace)-1]);
  298.             }
  299.         }
  300.         return $this->_trace;
  301.     }
  302.  
  303.     public function getErrorClass()
  304.     {
  305.         $trace $this->getTraceSafe();
  306.         return $trace[0]['class'];
  307.     }
  308.  
  309.     public function getErrorMethod()
  310.     {
  311.         $trace $this->getTraceSafe();
  312.         return $trace[0]['function'];
  313.     }
  314.  
  315.     public function __toString()
  316.     {
  317.         if (isset($_SERVER['REQUEST_URI'])) {
  318.             return $this->toHtml();
  319.         }
  320.         return $this->toText();
  321.     }
  322.  
  323.     public function toHtml()
  324.     {
  325.         $trace $this->getTraceSafe();
  326.         $causes = array();
  327.         $this->getCauseMessage($causes);
  328.         $html =  '<table style="border: 1px" cellspacing="0">' "\n";
  329.         foreach ($causes as $i => $cause{
  330.             $html .= '<tr><td colspan="3" style="background: #ff9999">'
  331.                . str_repeat('-'$i' <b>' $cause['class''</b>: '
  332.                . htmlspecialchars($cause['message']' in <b>' $cause['file''</b> '
  333.                . 'on line <b>' $cause['line''</b>'
  334.                . "</td></tr>\n";
  335.         }
  336.         $html .= '<tr><td colspan="3" style="background-color: #aaaaaa; text-align: center; font-weight: bold;">Exception trace</td></tr>' "\n"
  337.                . '<tr><td style="text-align: center; background: #cccccc; width:20px; font-weight: bold;">#</td>'
  338.                . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Function</td>'
  339.                . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Location</td></tr>' "\n";
  340.  
  341.         foreach ($trace as $k => $v{
  342.             $html .= '<tr><td style="text-align: center;">' $k '</td>'
  343.                    . '<td>';
  344.             if (!empty($v['class'])) {
  345.                 $html .= $v['class'$v['type'];
  346.             }
  347.             $html .= $v['function'];
  348.             $args = array();
  349.             if (!empty($v['args'])) {
  350.                 foreach ($v['args'as $arg{
  351.                     if (is_null($arg)) $args['null';
  352.                     elseif (is_array($arg)) $args['Array';
  353.                     elseif (is_object($arg)) $args['Object('.get_class($arg).')';
  354.                     elseif (is_bool($arg)) $args[$arg 'true' 'false';
  355.                     elseif (is_int($arg|| is_double($arg)) $args[$arg;
  356.                     else {
  357.                         $arg = (string)$arg;
  358.                         $str htmlspecialchars(substr($arg016));
  359.                         if (strlen($arg> 16$str .= '&hellip;';
  360.                         $args["'" $str "'";
  361.                     }
  362.                 }
  363.             }
  364.             $html .= '(' implode(', ',$args')'
  365.                    . '</td>'
  366.                    . '<td>' (isset($v['file']$v['file''unknown')
  367.                    . ':' (isset($v['line']$v['line''unknown')
  368.                    . '</td></tr>' "\n";
  369.         }
  370.         $html .= '<tr><td style="text-align: center;">' ($k+1'</td>'
  371.                . '<td>{main}</td>'
  372.                . '<td>&nbsp;</td></tr>' "\n"
  373.                . '</table>';
  374.         return $html;
  375.     }
  376.  
  377.     public function toText()
  378.     {
  379.         $causes = array();
  380.         $this->getCauseMessage($causes);
  381.         $causeMsg '';
  382.         foreach ($causes as $i => $cause{
  383.             $causeMsg .= str_repeat(' '$i$cause['class'': '
  384.                    . $cause['message'' in ' $cause['file']
  385.                    . ' on line ' $cause['line'"\n";
  386.         }
  387.         return $causeMsg $this->getTraceAsString();
  388.     }
  389. }

Documentation generated on Wed, 06 Jul 2011 23:30:49 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.