[ Index ]
 

Code source de PHP PEAR 1.4.5

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/PEAR/ -> ErrorStack.php (source)

   1  <?php
   2  /**
   3   * Error Stack Implementation
   4   * 
   5   * This is an incredibly simple implementation of a very complex error handling
   6   * facility.  It contains the ability
   7   * to track multiple errors from multiple packages simultaneously.  In addition,
   8   * it can track errors of many levels, save data along with the error, context
   9   * information such as the exact file, line number, class and function that
  10   * generated the error, and if necessary, it can raise a traditional PEAR_Error.
  11   * It has built-in support for PEAR::Log, to log errors as they occur
  12   * 
  13   * Since version 0.2alpha, it is also possible to selectively ignore errors,
  14   * through the use of an error callback, see {@link pushCallback()}
  15   * 
  16   * Since version 0.3alpha, it is possible to specify the exception class
  17   * returned from {@link push()}
  18   *
  19   * Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class.  This can
  20   * still be done quite handily in an error callback or by manipulating the returned array
  21   * @category   Debugging
  22   * @package    PEAR_ErrorStack
  23   * @author     Greg Beaver <cellog@php.net>
  24   * @copyright  2004-2006 Greg Beaver
  25   * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  26   * @version    CVS: $Id: ErrorStack.php,v 1.26 2006/10/31 02:54:40 cellog Exp $
  27   * @link       http://pear.php.net/package/PEAR_ErrorStack
  28   */
  29  
  30  /**
  31   * Singleton storage
  32   * 
  33   * Format:
  34   * <pre>
  35   * array(
  36   *  'package1' => PEAR_ErrorStack object,
  37   *  'package2' => PEAR_ErrorStack object,
  38   *  ...
  39   * )
  40   * </pre>
  41   * @access private
  42   * @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON']
  43   */
  44  $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array();
  45  
  46  /**
  47   * Global error callback (default)
  48   * 
  49   * This is only used if set to non-false.  * is the default callback for
  50   * all packages, whereas specific packages may set a default callback
  51   * for all instances, regardless of whether they are a singleton or not.
  52   *
  53   * To exclude non-singletons, only set the local callback for the singleton
  54   * @see PEAR_ErrorStack::setDefaultCallback()
  55   * @access private
  56   * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']
  57   */
  58  $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array(
  59      '*' => false,
  60  );
  61  
  62  /**
  63   * Global Log object (default)
  64   * 
  65   * This is only used if set to non-false.  Use to set a default log object for
  66   * all stacks, regardless of instantiation order or location
  67   * @see PEAR_ErrorStack::setDefaultLogger()
  68   * @access private
  69   * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
  70   */
  71  $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false;
  72  
  73  /**
  74   * Global Overriding Callback
  75   * 
  76   * This callback will override any error callbacks that specific loggers have set.
  77   * Use with EXTREME caution
  78   * @see PEAR_ErrorStack::staticPushCallback()
  79   * @access private
  80   * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
  81   */
  82  $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
  83  
  84  /**#@+
  85   * One of four possible return values from the error Callback
  86   * @see PEAR_ErrorStack::_errorCallback()
  87   */
  88  /**
  89   * If this is returned, then the error will be both pushed onto the stack
  90   * and logged.
  91   */
  92  define('PEAR_ERRORSTACK_PUSHANDLOG', 1);
  93  /**
  94   * If this is returned, then the error will only be pushed onto the stack,
  95   * and not logged.
  96   */
  97  define('PEAR_ERRORSTACK_PUSH', 2);
  98  /**
  99   * If this is returned, then the error will only be logged, but not pushed
 100   * onto the error stack.
 101   */
 102  define('PEAR_ERRORSTACK_LOG', 3);
 103  /**
 104   * If this is returned, then the error is completely ignored.
 105   */
 106  define('PEAR_ERRORSTACK_IGNORE', 4);
 107  /**
 108   * If this is returned, then the error is logged and die() is called.
 109   */
 110  define('PEAR_ERRORSTACK_DIE', 5);
 111  /**#@-*/
 112  
 113  /**
 114   * Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in
 115   * the singleton method.
 116   */
 117  define('PEAR_ERRORSTACK_ERR_NONCLASS', 1);
 118  
 119  /**
 120   * Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()}
 121   * that has no __toString() method
 122   */
 123  define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2);
 124  /**
 125   * Error Stack Implementation
 126   *
 127   * Usage:
 128   * <code>
 129   * // global error stack
 130   * $global_stack = &PEAR_ErrorStack::singleton('MyPackage');
 131   * // local error stack
 132   * $local_stack = new PEAR_ErrorStack('MyPackage');
 133   * </code>
 134   * @author     Greg Beaver <cellog@php.net>
 135   * @version    1.5.0
 136   * @package    PEAR_ErrorStack
 137   * @category   Debugging
 138   * @copyright  2004-2006 Greg Beaver
 139   * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 140   * @version    CVS: $Id: ErrorStack.php,v 1.26 2006/10/31 02:54:40 cellog Exp $
 141   * @link       http://pear.php.net/package/PEAR_ErrorStack
 142   */
 143  class PEAR_ErrorStack {
 144      /**
 145       * Errors are stored in the order that they are pushed on the stack.
 146       * @since 0.4alpha Errors are no longer organized by error level.
 147       * This renders pop() nearly unusable, and levels could be more easily
 148       * handled in a callback anyway
 149       * @var array
 150       * @access private
 151       */
 152      var $_errors = array();
 153  
 154      /**
 155       * Storage of errors by level.
 156       *
 157       * Allows easy retrieval and deletion of only errors from a particular level
 158       * @since PEAR 1.4.0dev
 159       * @var array
 160       * @access private
 161       */
 162      var $_errorsByLevel = array();
 163  
 164      /**
 165       * Package name this error stack represents
 166       * @var string
 167       * @access protected
 168       */
 169      var $_package;
 170      
 171      /**
 172       * Determines whether a PEAR_Error is thrown upon every error addition
 173       * @var boolean
 174       * @access private
 175       */
 176      var $_compat = false;
 177      
 178      /**
 179       * If set to a valid callback, this will be used to generate the error
 180       * message from the error code, otherwise the message passed in will be
 181       * used
 182       * @var false|string|array
 183       * @access private
 184       */
 185      var $_msgCallback = false;
 186      
 187      /**
 188       * If set to a valid callback, this will be used to generate the error
 189       * context for an error.  For PHP-related errors, this will be a file
 190       * and line number as retrieved from debug_backtrace(), but can be
 191       * customized for other purposes.  The error might actually be in a separate
 192       * configuration file, or in a database query.
 193       * @var false|string|array
 194       * @access protected
 195       */
 196      var $_contextCallback = false;
 197      
 198      /**
 199       * If set to a valid callback, this will be called every time an error
 200       * is pushed onto the stack.  The return value will be used to determine
 201       * whether to allow an error to be pushed or logged.
 202       * 
 203       * The return value must be one an PEAR_ERRORSTACK_* constant
 204       * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
 205       * @var false|string|array
 206       * @access protected
 207       */
 208      var $_errorCallback = array();
 209      
 210      /**
 211       * PEAR::Log object for logging errors
 212       * @var false|Log
 213       * @access protected
 214       */
 215      var $_logger = false;
 216      
 217      /**
 218       * Error messages - designed to be overridden
 219       * @var array
 220       * @abstract
 221       */
 222      var $_errorMsgs = array();
 223      
 224      /**
 225       * Set up a new error stack
 226       * 
 227       * @param string   $package name of the package this error stack represents
 228       * @param callback $msgCallback callback used for error message generation
 229       * @param callback $contextCallback callback used for context generation,
 230       *                 defaults to {@link getFileLine()}
 231       * @param boolean  $throwPEAR_Error
 232       */
 233      function PEAR_ErrorStack($package, $msgCallback = false, $contextCallback = false,
 234                           $throwPEAR_Error = false)
 235      {
 236          $this->_package = $package;
 237          $this->setMessageCallback($msgCallback);
 238          $this->setContextCallback($contextCallback);
 239          $this->_compat = $throwPEAR_Error;
 240      }
 241      
 242      /**
 243       * Return a single error stack for this package.
 244       * 
 245       * Note that all parameters are ignored if the stack for package $package
 246       * has already been instantiated
 247       * @param string   $package name of the package this error stack represents
 248       * @param callback $msgCallback callback used for error message generation
 249       * @param callback $contextCallback callback used for context generation,
 250       *                 defaults to {@link getFileLine()}
 251       * @param boolean  $throwPEAR_Error
 252       * @param string   $stackClass class to instantiate
 253       * @static
 254       * @return PEAR_ErrorStack
 255       */
 256      function &singleton($package, $msgCallback = false, $contextCallback = false,
 257                           $throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack')
 258      {
 259          if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
 260              return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
 261          }
 262          if (!class_exists($stackClass)) {
 263              if (function_exists('debug_backtrace')) {
 264                  $trace = debug_backtrace();
 265              }
 266              PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS,
 267                  'exception', array('stackclass' => $stackClass),
 268                  'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)',
 269                  false, $trace);
 270          }
 271          $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] =
 272              new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error);
 273  
 274          return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
 275      }
 276  
 277      /**
 278       * Internal error handler for PEAR_ErrorStack class
 279       * 
 280       * Dies if the error is an exception (and would have died anyway)
 281       * @access private
 282       */
 283      function _handleError($err)
 284      {
 285          if ($err['level'] == 'exception') {
 286              $message = $err['message'];
 287              if (isset($_SERVER['REQUEST_URI'])) {
 288                  echo '<br />';
 289              } else {
 290                  echo "\n";
 291              }
 292              var_dump($err['context']);
 293              die($message);
 294          }
 295      }
 296      
 297      /**
 298       * Set up a PEAR::Log object for all error stacks that don't have one
 299       * @param Log $log 
 300       * @static
 301       */
 302      function setDefaultLogger(&$log)
 303      {
 304          if (is_object($log) && method_exists($log, 'log') ) {
 305              $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
 306          } elseif (is_callable($log)) {
 307              $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
 308      }
 309      }
 310      
 311      /**
 312       * Set up a PEAR::Log object for this error stack
 313       * @param Log $log 
 314       */
 315      function setLogger(&$log)
 316      {
 317          if (is_object($log) && method_exists($log, 'log') ) {
 318              $this->_logger = &$log;
 319          } elseif (is_callable($log)) {
 320              $this->_logger = &$log;
 321          }
 322      }
 323      
 324      /**
 325       * Set an error code => error message mapping callback
 326       * 
 327       * This method sets the callback that can be used to generate error
 328       * messages for any instance
 329       * @param array|string Callback function/method
 330       */
 331      function setMessageCallback($msgCallback)
 332      {
 333          if (!$msgCallback) {
 334              $this->_msgCallback = array(&$this, 'getErrorMessage');
 335          } else {
 336              if (is_callable($msgCallback)) {
 337                  $this->_msgCallback = $msgCallback;
 338              }
 339          }
 340      }
 341      
 342      /**
 343       * Get an error code => error message mapping callback
 344       * 
 345       * This method returns the current callback that can be used to generate error
 346       * messages
 347       * @return array|string|false Callback function/method or false if none
 348       */
 349      function getMessageCallback()
 350      {
 351          return $this->_msgCallback;
 352      }
 353      
 354      /**
 355       * Sets a default callback to be used by all error stacks
 356       * 
 357       * This method sets the callback that can be used to generate error
 358       * messages for a singleton
 359       * @param array|string Callback function/method
 360       * @param string Package name, or false for all packages
 361       * @static
 362       */
 363      function setDefaultCallback($callback = false, $package = false)
 364      {
 365          if (!is_callable($callback)) {
 366              $callback = false;
 367          }
 368          $package = $package ? $package : '*';
 369          $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback;
 370      }
 371      
 372      /**
 373       * Set a callback that generates context information (location of error) for an error stack
 374       * 
 375       * This method sets the callback that can be used to generate context
 376       * information for an error.  Passing in NULL will disable context generation
 377       * and remove the expensive call to debug_backtrace()
 378       * @param array|string|null Callback function/method
 379       */
 380      function setContextCallback($contextCallback)
 381      {
 382          if ($contextCallback === null) {
 383              return $this->_contextCallback = false;
 384          }
 385          if (!$contextCallback) {
 386              $this->_contextCallback = array(&$this, 'getFileLine');
 387          } else {
 388              if (is_callable($contextCallback)) {
 389                  $this->_contextCallback = $contextCallback;
 390              }
 391          }
 392      }
 393      
 394      /**
 395       * Set an error Callback
 396       * If set to a valid callback, this will be called every time an error
 397       * is pushed onto the stack.  The return value will be used to determine
 398       * whether to allow an error to be pushed or logged.
 399       * 
 400       * The return value must be one of the ERRORSTACK_* constants.
 401       * 
 402       * This functionality can be used to emulate PEAR's pushErrorHandling, and
 403       * the PEAR_ERROR_CALLBACK mode, without affecting the integrity of
 404       * the error stack or logging
 405       * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
 406       * @see popCallback()
 407       * @param string|array $cb
 408       */
 409      function pushCallback($cb)
 410      {
 411          array_push($this->_errorCallback, $cb);
 412      }
 413      
 414      /**
 415       * Remove a callback from the error callback stack
 416       * @see pushCallback()
 417       * @return array|string|false
 418       */
 419      function popCallback()
 420      {
 421          if (!count($this->_errorCallback)) {
 422              return false;
 423          }
 424          return array_pop($this->_errorCallback);
 425      }
 426      
 427      /**
 428       * Set a temporary overriding error callback for every package error stack
 429       *
 430       * Use this to temporarily disable all existing callbacks (can be used
 431       * to emulate the @ operator, for instance)
 432       * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
 433       * @see staticPopCallback(), pushCallback()
 434       * @param string|array $cb
 435       * @static
 436       */
 437      function staticPushCallback($cb)
 438      {
 439          array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb);
 440      }
 441      
 442      /**
 443       * Remove a temporary overriding error callback
 444       * @see staticPushCallback()
 445       * @return array|string|false
 446       * @static
 447       */
 448      function staticPopCallback()
 449      {
 450          $ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']);
 451          if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) {
 452              $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
 453          }
 454          return $ret;
 455      }
 456      
 457      /**
 458       * Add an error to the stack
 459       * 
 460       * If the message generator exists, it is called with 2 parameters.
 461       *  - the current Error Stack object
 462       *  - an array that is in the same format as an error.  Available indices
 463       *    are 'code', 'package', 'time', 'params', 'level', and 'context'
 464       * 
 465       * Next, if the error should contain context information, this is
 466       * handled by the context grabbing method.
 467       * Finally, the error is pushed onto the proper error stack
 468       * @param int    $code      Package-specific error code
 469       * @param string $level     Error level.  This is NOT spell-checked
 470       * @param array  $params    associative array of error parameters
 471       * @param string $msg       Error message, or a portion of it if the message
 472       *                          is to be generated
 473       * @param array  $repackage If this error re-packages an error pushed by
 474       *                          another package, place the array returned from
 475       *                          {@link pop()} in this parameter
 476       * @param array  $backtrace Protected parameter: use this to pass in the
 477       *                          {@link debug_backtrace()} that should be used
 478       *                          to find error context
 479       * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
 480       * thrown.  If a PEAR_Error is returned, the userinfo
 481       * property is set to the following array:
 482       * 
 483       * <code>
 484       * array(
 485       *    'code' => $code,
 486       *    'params' => $params,
 487       *    'package' => $this->_package,
 488       *    'level' => $level,
 489       *    'time' => time(),
 490       *    'context' => $context,
 491       *    'message' => $msg,
 492       * //['repackage' => $err] repackaged error array/Exception class
 493       * );
 494       * </code>
 495       * 
 496       * Normally, the previous array is returned.
 497       */
 498      function push($code, $level = 'error', $params = array(), $msg = false,
 499                    $repackage = false, $backtrace = false)
 500      {
 501          $context = false;
 502          // grab error context
 503          if ($this->_contextCallback) {
 504              if (!$backtrace) {
 505                  $backtrace = debug_backtrace();
 506              }
 507              $context = call_user_func($this->_contextCallback, $code, $params, $backtrace);
 508          }
 509          
 510          // save error
 511          $time = explode(' ', microtime());
 512          $time = $time[1] + $time[0];
 513          $err = array(
 514                  'code' => $code,
 515                  'params' => $params,
 516                  'package' => $this->_package,
 517                  'level' => $level,
 518                  'time' => $time,
 519                  'context' => $context,
 520                  'message' => $msg,
 521                 );
 522  
 523          if ($repackage) {
 524              $err['repackage'] = $repackage;
 525          }
 526  
 527          // set up the error message, if necessary
 528          if ($this->_msgCallback) {
 529              $msg = call_user_func_array($this->_msgCallback,
 530                                          array(&$this, $err));
 531              $err['message'] = $msg;
 532          }        
 533          $push = $log = true;
 534          $die = false;
 535          // try the overriding callback first
 536          $callback = $this->staticPopCallback();
 537          if ($callback) {
 538              $this->staticPushCallback($callback);
 539          }
 540          if (!is_callable($callback)) {
 541              // try the local callback next
 542              $callback = $this->popCallback();
 543              if (is_callable($callback)) {
 544                  $this->pushCallback($callback);
 545              } else {
 546                  // try the default callback
 547                  $callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ?
 548                      $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] :
 549                      $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*'];
 550              }
 551          }
 552          if (is_callable($callback)) {
 553              switch(call_user_func($callback, $err)){
 554                  case PEAR_ERRORSTACK_IGNORE: 
 555                      return $err;
 556                  break;
 557                  case PEAR_ERRORSTACK_PUSH: 
 558                      $log = false;
 559                  break;
 560                  case PEAR_ERRORSTACK_LOG: 
 561                      $push = false;
 562                  break;
 563                  case PEAR_ERRORSTACK_DIE: 
 564                      $die = true;
 565                  break;
 566                  // anything else returned has the same effect as pushandlog
 567              }
 568          }
 569          if ($push) {
 570              array_unshift($this->_errors, $err);
 571              if (!isset($this->_errorsByLevel[$err['level']])) {
 572                  $this->_errorsByLevel[$err['level']] = array();
 573              }
 574              $this->_errorsByLevel[$err['level']][] = &$this->_errors[0];
 575          }
 576          if ($log) {
 577              if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) {
 578                  $this->_log($err);
 579              }
 580          }
 581          if ($die) {
 582              die();
 583          }
 584          if ($this->_compat && $push) {
 585              return $this->raiseError($msg, $code, null, null, $err);
 586          }
 587          return $err;
 588      }
 589      
 590      /**
 591       * Static version of {@link push()}
 592       * 
 593       * @param string $package   Package name this error belongs to
 594       * @param int    $code      Package-specific error code
 595       * @param string $level     Error level.  This is NOT spell-checked
 596       * @param array  $params    associative array of error parameters
 597       * @param string $msg       Error message, or a portion of it if the message
 598       *                          is to be generated
 599       * @param array  $repackage If this error re-packages an error pushed by
 600       *                          another package, place the array returned from
 601       *                          {@link pop()} in this parameter
 602       * @param array  $backtrace Protected parameter: use this to pass in the
 603       *                          {@link debug_backtrace()} that should be used
 604       *                          to find error context
 605       * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
 606       *                          thrown.  see docs for {@link push()}
 607       * @static
 608       */
 609      function staticPush($package, $code, $level = 'error', $params = array(),
 610                          $msg = false, $repackage = false, $backtrace = false)
 611      {
 612          $s = &PEAR_ErrorStack::singleton($package);
 613          if ($s->_contextCallback) {
 614              if (!$backtrace) {
 615                  if (function_exists('debug_backtrace')) {
 616                      $backtrace = debug_backtrace();
 617                  }
 618              }
 619          }
 620          return $s->push($code, $level, $params, $msg, $repackage, $backtrace);
 621      }
 622      
 623      /**
 624       * Log an error using PEAR::Log
 625       * @param array $err Error array
 626       * @param array $levels Error level => Log constant map
 627       * @access protected
 628       */
 629      function _log($err)
 630      {
 631          if ($this->_logger) {
 632              $logger = &$this->_logger;
 633          } else {
 634              $logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'];
 635          }
 636          if (is_a($logger, 'Log')) {
 637              $levels = array(
 638                  'exception' => PEAR_LOG_CRIT,
 639                  'alert' => PEAR_LOG_ALERT,
 640                  'critical' => PEAR_LOG_CRIT,
 641                  'error' => PEAR_LOG_ERR,
 642                  'warning' => PEAR_LOG_WARNING,
 643                  'notice' => PEAR_LOG_NOTICE,
 644                  'info' => PEAR_LOG_INFO,
 645                  'debug' => PEAR_LOG_DEBUG);
 646              if (isset($levels[$err['level']])) {
 647                  $level = $levels[$err['level']];
 648              } else {
 649                  $level = PEAR_LOG_INFO;
 650              }
 651              $logger->log($err['message'], $level, $err);
 652          } else { // support non-standard logs
 653              call_user_func($logger, $err);
 654          }
 655      }
 656  
 657      
 658      /**
 659       * Pop an error off of the error stack
 660       * 
 661       * @return false|array
 662       * @since 0.4alpha it is no longer possible to specify a specific error
 663       * level to return - the last error pushed will be returned, instead
 664       */
 665      function pop()
 666      {
 667          $err = @array_shift($this->_errors);
 668          if (!is_null($err)) {
 669              @array_pop($this->_errorsByLevel[$err['level']]);
 670              if (!count($this->_errorsByLevel[$err['level']])) {
 671                  unset($this->_errorsByLevel[$err['level']]);
 672              }
 673          }
 674          return $err;
 675      }
 676  
 677      /**
 678       * Pop an error off of the error stack, static method
 679       *
 680       * @param string package name
 681       * @return boolean
 682       * @since PEAR1.5.0a1
 683       */
 684      function staticPop($package)
 685      {
 686          if ($package) {
 687              if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
 688                  return false;
 689              }
 690              return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop();
 691          }
 692      }
 693  
 694      /**
 695       * Determine whether there are any errors on the stack
 696       * @param string|array Level name.  Use to determine if any errors
 697       * of level (string), or levels (array) have been pushed
 698       * @return boolean
 699       */
 700      function hasErrors($level = false)
 701      {
 702          if ($level) {
 703              return isset($this->_errorsByLevel[$level]);
 704          }
 705          return count($this->_errors);
 706      }
 707      
 708      /**
 709       * Retrieve all errors since last purge
 710       * 
 711       * @param boolean set in order to empty the error stack
 712       * @param string level name, to return only errors of a particular severity
 713       * @return array
 714       */
 715      function getErrors($purge = false, $level = false)
 716      {
 717          if (!$purge) {
 718              if ($level) {
 719                  if (!isset($this->_errorsByLevel[$level])) {
 720                      return array();
 721                  } else {
 722                      return $this->_errorsByLevel[$level];
 723                  }
 724              } else {
 725                  return $this->_errors;
 726              }
 727          }
 728          if ($level) {
 729              $ret = $this->_errorsByLevel[$level];
 730              foreach ($this->_errorsByLevel[$level] as $i => $unused) {
 731                  // entries are references to the $_errors array
 732                  $this->_errorsByLevel[$level][$i] = false;
 733              }
 734              // array_filter removes all entries === false
 735              $this->_errors = array_filter($this->_errors);
 736              unset($this->_errorsByLevel[$level]);
 737              return $ret;
 738          }
 739          $ret = $this->_errors;
 740          $this->_errors = array();
 741          $this->_errorsByLevel = array();
 742          return $ret;
 743      }
 744      
 745      /**
 746       * Determine whether there are any errors on a single error stack, or on any error stack
 747       *
 748       * The optional parameter can be used to test the existence of any errors without the need of
 749       * singleton instantiation
 750       * @param string|false Package name to check for errors
 751       * @param string Level name to check for a particular severity
 752       * @return boolean
 753       * @static
 754       */
 755      function staticHasErrors($package = false, $level = false)
 756      {
 757          if ($package) {
 758              if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
 759                  return false;
 760              }
 761              return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level);
 762          }
 763          foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
 764              if ($obj->hasErrors($level)) {
 765                  return true;
 766              }
 767          }
 768          return false;
 769      }
 770      
 771      /**
 772       * Get a list of all errors since last purge, organized by package
 773       * @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be
 774       * @param boolean $purge Set to purge the error stack of existing errors
 775       * @param string  $level Set to a level name in order to retrieve only errors of a particular level
 776       * @param boolean $merge Set to return a flat array, not organized by package
 777       * @param array   $sortfunc Function used to sort a merged array - default
 778       *        sorts by time, and should be good for most cases
 779       * @static
 780       * @return array 
 781       */
 782      function staticGetErrors($purge = false, $level = false, $merge = false,
 783                               $sortfunc = array('PEAR_ErrorStack', '_sortErrors'))
 784      {
 785          $ret = array();
 786          if (!is_callable($sortfunc)) {
 787              $sortfunc = array('PEAR_ErrorStack', '_sortErrors');
 788          }
 789          foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
 790              $test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level);
 791              if ($test) {
 792                  if ($merge) {
 793                      $ret = array_merge($ret, $test);
 794                  } else {
 795                      $ret[$package] = $test;
 796                  }
 797              }
 798          }
 799          if ($merge) {
 800              usort($ret, $sortfunc);
 801          }
 802          return $ret;
 803      }
 804      
 805      /**
 806       * Error sorting function, sorts by time
 807       * @access private
 808       */
 809      function _sortErrors($a, $b)
 810      {
 811          if ($a['time'] == $b['time']) {
 812              return 0;
 813          }
 814          if ($a['time'] < $b['time']) {
 815              return 1;
 816          }
 817          return -1;
 818      }
 819  
 820      /**
 821       * Standard file/line number/function/class context callback
 822       *
 823       * This function uses a backtrace generated from {@link debug_backtrace()}
 824       * and so will not work at all in PHP < 4.3.0.  The frame should
 825       * reference the frame that contains the source of the error.
 826       * @return array|false either array('file' => file, 'line' => line,
 827       *         'function' => function name, 'class' => class name) or
 828       *         if this doesn't work, then false
 829       * @param unused
 830       * @param integer backtrace frame.
 831       * @param array Results of debug_backtrace()
 832       * @static
 833       */
 834      function getFileLine($code, $params, $backtrace = null)
 835      {
 836          if ($backtrace === null) {
 837              return false;
 838          }
 839          $frame = 0;
 840          $functionframe = 1;
 841          if (!isset($backtrace[1])) {
 842              $functionframe = 0;
 843          } else {
 844              while (isset($backtrace[$functionframe]['function']) &&
 845                    $backtrace[$functionframe]['function'] == 'eval' &&
 846                    isset($backtrace[$functionframe + 1])) {
 847                  $functionframe++;
 848              }
 849          }
 850          if (isset($backtrace[$frame])) {
 851              if (!isset($backtrace[$frame]['file'])) {
 852                  $frame++;
 853              }
 854              $funcbacktrace = $backtrace[$functionframe];
 855              $filebacktrace = $backtrace[$frame];
 856              $ret = array('file' => $filebacktrace['file'],
 857                           'line' => $filebacktrace['line']);
 858              // rearrange for eval'd code or create function errors
 859              if (strpos($filebacktrace['file'], '(') && 
 860                    preg_match(';^(.*?)\((\d+)\) : (.*?)$;', $filebacktrace['file'],
 861                    $matches)) {
 862                  $ret['file'] = $matches[1];
 863                  $ret['line'] = $matches[2] + 0;
 864              }
 865              if (isset($funcbacktrace['function']) && isset($backtrace[1])) {
 866                  if ($funcbacktrace['function'] != 'eval') {
 867                      if ($funcbacktrace['function'] == '__lambda_func') {
 868                          $ret['function'] = 'create_function() code';
 869                      } else {
 870                          $ret['function'] = $funcbacktrace['function'];
 871                      }
 872                  }
 873              }
 874              if (isset($funcbacktrace['class']) && isset($backtrace[1])) {
 875                  $ret['class'] = $funcbacktrace['class'];
 876              }
 877              return $ret;
 878          }
 879          return false;
 880      }
 881      
 882      /**
 883       * Standard error message generation callback
 884       * 
 885       * This method may also be called by a custom error message generator
 886       * to fill in template values from the params array, simply
 887       * set the third parameter to the error message template string to use
 888       * 
 889       * The special variable %__msg% is reserved: use it only to specify
 890       * where a message passed in by the user should be placed in the template,
 891       * like so:
 892       * 
 893       * Error message: %msg% - internal error
 894       * 
 895       * If the message passed like so:
 896       * 
 897       * <code>
 898       * $stack->push(ERROR_CODE, 'error', array(), 'server error 500');
 899       * </code>
 900       * 
 901       * The returned error message will be "Error message: server error 500 -
 902       * internal error"
 903       * @param PEAR_ErrorStack
 904       * @param array
 905       * @param string|false Pre-generated error message template
 906       * @static
 907       * @return string
 908       */
 909      function getErrorMessage(&$stack, $err, $template = false)
 910      {
 911          if ($template) {
 912              $mainmsg = $template;
 913          } else {
 914              $mainmsg = $stack->getErrorMessageTemplate($err['code']);
 915          }
 916          $mainmsg = str_replace('%__msg%', $err['message'], $mainmsg);
 917          if (is_array($err['params']) && count($err['params'])) {
 918              foreach ($err['params'] as $name => $val) {
 919                  if (is_array($val)) {
 920                      // @ is needed in case $val is a multi-dimensional array
 921                      $val = @implode(', ', $val);
 922                  }
 923                  if (is_object($val)) {
 924                      if (method_exists($val, '__toString')) {
 925                          $val = $val->__toString();
 926                      } else {
 927                          PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING,
 928                              'warning', array('obj' => get_class($val)),
 929                              'object %obj% passed into getErrorMessage, but has no __toString() method');
 930                          $val = 'Object';
 931                      }
 932                  }
 933                  $mainmsg = str_replace('%' . $name . '%', $val, $mainmsg);
 934              }
 935          }
 936          return $mainmsg;
 937      }
 938      
 939      /**
 940       * Standard Error Message Template generator from code
 941       * @return string
 942       */
 943      function getErrorMessageTemplate($code)
 944      {
 945          if (!isset($this->_errorMsgs[$code])) {
 946              return '%__msg%';
 947          }
 948          return $this->_errorMsgs[$code];
 949      }
 950      
 951      /**
 952       * Set the Error Message Template array
 953       * 
 954       * The array format must be:
 955       * <pre>
 956       * array(error code => 'message template',...)
 957       * </pre>
 958       * 
 959       * Error message parameters passed into {@link push()} will be used as input
 960       * for the error message.  If the template is 'message %foo% was %bar%', and the
 961       * parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will
 962       * be 'message one was six'
 963       * @return string
 964       */
 965      function setErrorMessageTemplate($template)
 966      {
 967          $this->_errorMsgs = $template;
 968      }
 969      
 970      
 971      /**
 972       * emulate PEAR::raiseError()
 973       * 
 974       * @return PEAR_Error
 975       */
 976      function raiseError()
 977      {
 978          require_once  'PEAR.php';
 979          $args = func_get_args();
 980          return call_user_func_array(array('PEAR', 'raiseError'), $args);
 981      }
 982  }
 983  $stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack');
 984  $stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
 985  ?>


Généré le : Sun Feb 25 14:08:00 2007 par Balluche grâce à PHPXref 0.7