array( 'mode' => 'echo' ), E_WARNING => array( 'mode' => 'echo' ), E_ERROR => array( 'mode' => 'die' ) ); /** * available error levels * Stored in a variable to keep them flexible */ $GLOBALS['_pat_errorLevels'] = array( E_NOTICE => 'Notice', E_WARNING => 'Warning', E_ERROR => 'Error' ); /** * error class names * Stored in a variable allows to change during runtime */ $GLOBALS['_pat_errorClass'] = 'patError'; /** * ignore errors * Store error-codes that will be ignored forever */ $GLOBALS['_pat_errorIgnores'] = array(); /** * expects errors * Store error-codes that will be ignored once */ $GLOBALS['_pat_errorExpects'] = array(); /** * patErrorManager main error management class used by pat tools for the * application-internal error management. Creates patError objects for * any errors for precise error management. * * @static * @package patError * @version 0.3 * @author gERD Schaufelberger * @author Stephan Schmidt * @license LGPL * @link http://www.php-tools.net * @todo implement ignoreError() to ignore errrors with a certain code * @todo implement expectError() to ignore an error with a certain code only once. */ class patErrorManager { /** * method for checking whether the return value of a pat application method is a pat * error object. * * @static * @access public * @param mixed &$object * @return boolean $result True if argument is a patError-object, false otherwise. */ function isError( &$object ) { if( !is_object( $object ) ) { return false; } if( strtolower( get_class( $object ) ) != strtolower( $GLOBALS['_pat_errorClass'] ) && !is_subclass_of( $object, $GLOBALS['_pat_errorClass'] ) ) { return false; } return true; } /** * wrapper for the {@link raise()} method where you do not have to specify the * error level - a {@link patError} object with error level E_ERROR will be returned. * * @static * @access public * @param string $code The application-internal error code for this error * @param string $msg The error message, which may also be shown the user if need be. * @param mixed $info Optional: Additional error information (usually only developer-relevant information that the user should never see, like a database DSN). * @return object $error The configured patError object * @see raise() * @see patError */ function &raiseError( $code, $msg, $info = null ) { return patErrorManager::raise( E_ERROR, $code, $msg, $info ); } /** * wrapper for the {@link raise()} method where you do not have to specify the * error level - a {@link patError} object with error level E_WARNING will be returned. * * @static * @access public * @param string $code The application-internal error code for this error * @param string $msg The error message, which may also be shown the user if need be. * @param mixed $info Optional: Additional error information (usually only developer-relevant information that the user should never see, like a database DSN). * @return object $error The configured patError object * @see raise() * @see patError */ function &raiseWarning( $code, $msg, $info = null ) { return patErrorManager::raise( E_WARNING, $code, $msg, $info ); } /** * wrapper for the {@link raise()} method where you do not have to specify the * error level - a {@link patError} object with error level E_NOTICE will be returned. * * @static * @access public * @param string $code The application-internal error code for this error * @param string $msg The error message, which may also be shown the user if need be. * @param mixed $info Optional: Additional error information (usually only developer-relevant information that the user should never see, like a database DSN). * @return object $error The configured patError object * @see raise() * @see patError */ function &raiseNotice( $code, $msg, $info = null ) { return patErrorManager::raise( E_NOTICE, $code, $msg, $info ); } /** * creates a new patError object given the specified information. * * @access public * @param int $level The error level - use any of PHP's own error levels for this: E_ERROR, E_WARNING, E_NOTICE, E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE. * @param string $code The application-internal error code for this error * @param string $msg The error message, which may also be shown the user if need be. * @param mixed $info Optional: Additional error information (usually only developer-relevant information that the user should never see, like a database DSN). * @return mixed $error The configured patError object or false if this error should be ignored * @see patError * @todo implement 'simple' mode that returns just false (BC for patConfiguration) * @todo either remove HTML tags and entities from output or test for enviroment!!! in shell is ugly! */ function &raise( $level, $code, $msg, $info = null ) { // ignore this error? if( in_array( $code, $GLOBALS['_pat_errorIgnores'] ) ) { return false; } // need patError $class = $GLOBALS['_pat_errorClass']; if( !class_exists( $class ) ) { include_once dirname( __FILE__ ) . '/'. $class .'.php'; } // build error object $error =& new $class( $level, $code, $msg, $info ); // this error was expected if( !empty( $GLOBALS['_pat_errorExpects'] ) ) { $expected = array_pop( $GLOBALS['_pat_errorExpects'] ); array_push( $GLOBALS['_pat_errorExpects'], $expected ); if( in_array( $code, $expected ) ) { return $error; } } // see what to do with this kind of error $handling = patErrorManager::getErrorHandling( $level ); $function = 'handleError' . ucfirst( $handling['mode'] ); return patErrorManager::$function( $error, $handling ); } /** * register a new error level * * This allows you to add custom error levels to the built-in * - E_NOTICE * - E_WARNING * - E_NOTICE * * You may use this level in subsequent calls to raise(). * Error handling will be set to 'ignore' for the new level, you * may change it by using setErrorHandling(). * * You could be using PHP's predefined constants for error levels * or any other integer value. * * @access public * @param integer error level * @param string human-readable name * @return boolean true on success; false if the level already has been registered * @see raise(), setErrorHandling() * @link http://www.php.net/manual/en/function.error-reporting.php */ function registerErrorLevel( $level, $name ) { if( isset( $GLOBALS['_pat_errorLevels'][$level] ) ) { return false; } $GLOBALS['_pat_errorLevels'][$level] = $name; patErrorManager::setErrorHandling( $level, 'ignore' ); return true; } /** * sets the way the patErrorManager will handle teh different error levels. Use this * if you want to override the default settings. * * Error handling modes: * - ignore * - trigger * - verbose * - echo * - callback * - die * * You may also set the error handling for several modes at once using PHP's bit operations. * Examples: * - E_ALL = Set the handling for all levels * - E_ERROR | E_WARNING = Set the handling for errors and warnings * - E_ALL ^ E_ERROR = Set the handling for all levels except errors * * @static * @access public * @param int $level The error level for which to set the error handling * @param string $mode The mode to use for the error handling. * @param mixed $options Optional: Any options needed for the given mode. * @return mixed $result True on success, or a patError object if failed. * @see getErrorHandling() */ function setErrorHandling( $level, $mode, $options = null ) { $levels = $GLOBALS['_pat_errorLevels']; $function = 'handleError' . ucfirst( $mode ); if( !is_callable( array( 'patErrorManager', $function ) ) ) { return patErrorManager::raiseError( E_ERROR, 'patErrorManager:' . PATERRORMANAGER_ERROR_ILLEGAL_MODE, 'Error Handling mode is not knwon', 'Mode: ' . $mode . ' is not implemented.' ); } foreach( $levels as $eLevel => $eTitle ) { if( ( $level & $eLevel ) != $eLevel ) { continue; } // set callback options if( $mode == 'callback' ) { if( !is_array( $options ) ) { return patErrorManager::raiseError( E_ERROR, 'patErrorManager:' . PATERRORMANAGER_ERROR_ILLEGAL_OPTIONS, 'Options for callback not valid' ); } if( !is_callable( $options ) ) { $tmp = array( 'GLOBAL' ); if( is_array( $options ) ) { $tmp[0] = $options[0]; $tmp[1] = $options[1]; } else { $tmp[1] = $options; } return patErrorManager::raiseError( E_ERROR, 'patErrorManager:' . PATERRORMANAGER_ERROR_CALLBACK_NOT_CALLABLE, 'Function is not callable', 'Function:' . $tmp[1] . ' scope ' . $tmp[0] . '.' ); } } // save settings $GLOBALS['_pat_errorHandling'][$eLevel] = array( 'mode' => $mode ); if( $options != null ) { $GLOBALS['_pat_errorHandling'][$eLevel]['options'] = $options; } } return true; } /** * retrieves the current error handling settings for the specified error level. * * @access public * @param int $level The error level to retrieve. This can be any of PHP's own error levels, e.g. E_ALL, E_NOTICE... * @return array $handling All error handling details */ function getErrorHandling( $level ) { return $GLOBALS['_pat_errorHandling'][$level]; } /** * translate an error level * * returns the human-readable name for an error level, * e.g. E_ERROR will be translated to 'Error'. * * @access public * @param integer error level * @return string human-readable representation */ function translateErrorLevel( $level ) { if( isset( $GLOBALS['_pat_errorLevels'][$level] ) ) { return $GLOBALS['_pat_errorLevels'][$level]; } return 'Unknown error level'; } /** * setErrorClass * * In order to autoload this class, the filename containing that class must be * named like the class itself; with an appending ".php". Although the file must be stored * in the same directory as patErrorManager.php (this file) * * @access public * @param string $name classname * @return boolean $result true on success */ function setErrorClass( $name ) { // include old error-class if( $name !== $GLOBALS['_pat_errorClass'] && !class_exists( $GLOBALS['_pat_errorClass'] ) ) { include_once dirname( __FILE__ ) . '/' . $GLOBALS['_pat_errorClass'] . '.php'; } $GLOBALS['_pat_errorClass'] = $name; return true; } /** * add error codes to be ingored * * @static * @access public * @param mixed $codes either an array of error code or a single code that will be ignored in future * @return boolean $result true on success */ function addIgnore( $codes ) { if( !is_array( $codes ) ) { $codes = array( $codes ); } $codes = array_merge( $GLOBALS['_pat_errorIgnores'], $codes ); $GLOBALS['_pat_errorIgnores'] = array_unique( $codes ); return true; } /** * removeIgnore * * * @static * @access public * @return boolean $result true on success */ function removeIgnore( $codes ) { if( !is_array( $codes ) ) { $codes = array( $codes ); } foreach( $codes as $code ) { $index = array_search( $code, $GLOBALS['_pat_errorIgnores'] ); if( $index === false ) { continue; } unset( $GLOBALS['_pat_errorIgnores'][$index] ); } // reorder the codes $GLOBALS['_pat_errorIgnores'] = array_values( $GLOBALS['_pat_errorIgnores'] ); return true; } /** * recieve all registerd error codes that will be ignored * * @static * @access public * @return array $codes list of error codes */ function getIgnore() { return $GLOBALS['_pat_errorIgnores']; } /** * empty list of errors to be ignored * * @static * @access public * @return boolean $result true on success */ function clearIgnore() { $GLOBALS['_pat_errorIgnores'] = array(); return true; } /** * add expected errors to stack * * @static * @access public * @param mixed $codes either an array of error code or a single code that will be ignored in future * @return boolean $result true on success */ function pushExpect( $codes ) { if( !is_array( $codes ) ) { $codes = array( $codes ); } array_push( $GLOBALS['_pat_errorExpects'], $codes ); return true; } /** * remove top of error-codes from stack * * @static * @access public * @return boolean $result true on success */ function popExpect() { if( empty( $GLOBALS['_pat_errorExpects'] ) ) { return false; } array_pop( $GLOBALS['_pat_errorExpects'] ); return true; } /** * recieve all registerd error codes that will be ignored * * @static * @access public * @return array $codes list of error codes */ function getExpect() { return $GLOBALS['_pat_errorExpects']; } /** * empty list of errors to be ignored * * @static * @access public * @return boolean $result true on success */ function clearExpect() { $GLOBALS['_pat_errorExpects'] = array(); return true; } /** * handleError: Ignore * Does nothing * * @access private * @param object $error patError-Object * @param array $options options for handler * @return object $error error-object * @see raise() */ function &handleErrorIgnore( &$error, $options ) { return $error; } /** * handleError: Echo * display error message * * @access private * @param object $error patError-Object * @param array $options options for handler * @return object $error error-object * @see raise() */ function &handleErrorEcho( &$error, $options ) { $level_human = patErrorManager::translateErrorLevel( $error->getLevel() ); if( isset( $_SERVER['HTTP_HOST'] ) ) { // output as html echo "
pat-$level_human: " . $error->getMessage() . "
\n"; } else { // output as simple text if( defined( 'STDERR' ) ) { fwrite( STDERR, "pat-$level_human: " . $error->getMessage() . "\n" ); } else { echo "pat-$level_human: " . $error->getMessage() . "\n"; } } return $error; } /** * handleError: Verbose * display verbose output for developing purpose * * @access private * @param object $error patError-Object * @param array $options options for handler * @return object $error error-object * @see raise() */ function &handleErrorVerbose( &$error, $options ) { $level_human = patErrorManager::translateErrorLevel( $error->getLevel() ); $info = $error->getInfo(); if( isset( $_SERVER['HTTP_HOST'] ) ) { // output as html echo "
pat-$level_human: " . $error->getMessage() . "
\n"; if( $info != null ) { echo "   " . $error->getInfo() . "
\n"; } } else { // output as simple text echo "pat-$level_human: " . $error->getMessage() . "\n"; if( $info != null ) { echo " " . $error->getInfo() . "\n"; } } return $error; } /** * handleError: die * display error-message and die * * @access private * @param object $error patError-Object * @param array $options options for handler * @return object $error error-object * @see raise() */ function &handleErrorDie( &$error, $options ) { $level_human = patErrorManager::translateErrorLevel( $error->getLevel() ); if( isset( $_SERVER['HTTP_HOST'] ) ) { // output as html die( "
pat-$level_human " . $error->getMessage() . "
\n" ); } else { // output as simple text if( defined( 'STDERR' ) ) { fwrite( STDERR, "pat-$level_human " . $error->getMessage() . "\n" ); } else { die( "pat-$level_human " . $error->getMessage() . "\n" ); } } return $error; } /** * handleError: trigger * trigger php-error * * @access private * @param object $error patError-Object * @param array $options options for handler * @return object $error error-object * @see raise() */ function &handleErrorTrigger( &$error, $options ) { switch( $error->getLevel() ) { case E_NOTICE: $level = E_USER_NOTICE; break; case E_WARNING: $level = E_USER_WARNING; break; case E_NOTICE: $level = E_NOTICE; break; default: $level = E_USER_ERROR; break; } trigger_error( $error->getMessage(), $level ); return $error; } /** * handleError: callback * forward error to custom handler * * @access private * @param object $error patError-Object * @param array $options options for handler * @return object $error error-object * @see raise() */ function &handleErrorCallback( &$error, $options ) { $opt = $options['options']; return call_user_func( $opt, $error ); } /** * handleError: throw an exception * * @access private * @param object $error patError-Object * @param array $options options for handler * @return null * @throws Exception * @see raise() */ function &handleErrorException(&$error, $options) { if (isset($options['options'])) { $exception = $options['options']; } else { $exception = 'Exception'; } $code = 'throw new '.$exception.'("'.$error->getMessage().'");'; eval($code); } } ?>