File indexing completed on 2024-04-21 16:36:33

0001 <?php
0002 
0003 /**
0004  * Flooer Framework
0005  *
0006  * LICENSE: BSD License (2 Clause)
0007  *
0008  * @category    Flooer
0009  * @package     Flooer_Exception
0010  * @author      Akira Ohgaki <akiraohgaki@gmail.com>
0011  * @copyright   Akira Ohgaki
0012  * @license     https://opensource.org/licenses/BSD-2-Clause  BSD License (2 Clause)
0013  * @link        https://github.com/akiraohgaki/flooer
0014  */
0015 
0016 /**
0017  * Usage
0018  *
0019  * try {
0020  *     throw new Flooer_Exception('Message');
0021  * }
0022  * catch (Flooer_Exception $exception) {
0023  *     echo $exception->getMessage();
0024  * }
0025  */
0026 
0027 /**
0028  * Exception class
0029  *
0030  * @category    Flooer
0031  * @package     Flooer_Exception
0032  * @author      Akira Ohgaki <akiraohgaki@gmail.com>
0033  */
0034 class Flooer_Exception extends Exception
0035 {
0036 
0037     /**
0038      * Previous exception object
0039      *
0040      * @var     Flooer_Exception|Exception
0041      */
0042     protected $_previousException = null;
0043 
0044     /**
0045      * Constructor
0046      *
0047      * @param   string $message
0048      * @param   int $code
0049      * @param   string $file
0050      * @param   int $line
0051      * @param   Flooer_Exception|Exception $previous
0052      * @return  void
0053      */
0054     public function __construct($message = null, $code = 0, $file = null, $line = null, Exception $previous = null)
0055     {
0056         if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
0057             parent::__construct($message, $code, $previous);
0058         }
0059         else {
0060             parent::__construct($message, $code);
0061         }
0062         if ($file !== null) {
0063             $this->file = $file;
0064         }
0065         if ($line !== null) {
0066             $this->line = $line;
0067         }
0068         if ($previous !== null) {
0069             $this->_previousException = $previous;
0070         }
0071     }
0072 
0073     /**
0074      * Magic method to get a string representation
0075      *
0076      * @return  string
0077      */
0078     public function __toString()
0079     {
0080         return __CLASS__ . " [{$this->code}]: {$this->message}; {$this->file}({$this->line})\n";
0081     }
0082 
0083     /**
0084      * Exception handler
0085      *
0086      * @param   Flooer_Exception|Exception $exception
0087      * @return  void
0088      */
0089     public static function exceptionHandler($exception)
0090     {
0091         $displayErrors = ini_get("display_errors");
0092         $displayErrors = strtolower($displayErrors);
0093 
0094         $logErrors = boolval(ini_get("log_errors"));
0095 
0096         if ($logErrors) {
0097             $errorMsg = __CLASS__ . " [{$exception->getCode()}]: {$exception->getMessage()} in {$exception->getFile()}({$exception->getLine()})\n{$exception->getTraceAsString()}\n";
0098             error_log($errorMsg);
0099         }
0100 
0101         if (error_reporting() === 0 || empty($displayErrors) || $displayErrors === "off") {
0102             return;
0103         }
0104 
0105         echo $exception;
0106     }
0107 
0108     /**
0109      * Set the exception handler
0110      *
0111      * @return  callback|null
0112      */
0113     public static function setExceptionHandler()
0114     {
0115         return set_exception_handler(array(__CLASS__, 'exceptionHandler'));
0116     }
0117 
0118     /**
0119      * Restore the exception handler
0120      *
0121      * @return  bool Always true
0122      */
0123     public static function restoreExceptionHandler()
0124     {
0125         return restore_exception_handler();
0126     }
0127 
0128     /**
0129      * Error handler
0130      *
0131      * @param   int $errno
0132      * @param   string $errstr
0133      * @param   string $errfile
0134      * @param   int $errline
0135      * @return  void
0136      * @throws  Flooer_Exception
0137      */
0138     public static function errorHandler($errno, $errstr, $errfile = null, $errline = null)
0139     {
0140         throw new self($errstr, self::convertErrorCode($errno), $errfile, $errline);
0141     }
0142 
0143     /**
0144      * Set the error handler
0145      *
0146      * @return  mixed
0147      */
0148     public static function setErrorHandler()
0149     {
0150         return set_error_handler(array(__CLASS__, 'errorHandler'), error_reporting());
0151     }
0152 
0153     /**
0154      * Restore the error handler
0155      *
0156      * @return  bool Always true
0157      */
0158     public static function restoreErrorHandler()
0159     {
0160         return restore_error_handler();
0161     }
0162 
0163     /**
0164      * Convert an error code to a log code
0165      *
0166      * @param   int $errno E_* code
0167      * @return  int LOG_* code
0168      */
0169     public static function convertErrorCode($errno)
0170     {
0171         $types = array(
0172             E_ERROR => LOG_EMERG,
0173             E_WARNING => LOG_WARNING,
0174             E_PARSE => LOG_ERR,
0175             E_NOTICE => LOG_NOTICE,
0176             E_CORE_ERROR => LOG_EMERG,
0177             E_CORE_WARNING => LOG_WARNING,
0178             E_COMPILE_ERROR => LOG_EMERG,
0179             E_COMPILE_WARNING => LOG_WARNING,
0180             E_USER_ERROR => LOG_ERR,
0181             E_USER_WARNING => LOG_WARNING,
0182             E_USER_NOTICE => LOG_NOTICE,
0183             E_STRICT => LOG_NOTICE,
0184             E_RECOVERABLE_ERROR => LOG_ERR
0185         );
0186         if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
0187             $types += array(
0188                 E_DEPRECATED => LOG_WARNING,
0189                 E_USER_DEPRECATED => LOG_WARNING
0190             );
0191         }
0192         if (isset($types[$errno])) {
0193             return $types[$errno];
0194         }
0195         return LOG_NOTICE;
0196     }
0197 
0198     /**
0199      * Get a previous exception object
0200      *
0201      * @return  Flooer_Exception|Exception
0202      */
0203     public function getPreviousException()
0204     {
0205         return $this->_previousException;
0206     }
0207 
0208 }