[ Index ]
 

Code source de SPIP Agora 1.4

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

title

Body

[fermer]

/Pear/PEAR/ -> ErrorStack.php (source)

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


Généré le : Sat Feb 24 14:40:03 2007 par Balluche grâce à PHPXref 0.7