|
eZ Publish
[trunk]
|
00001 <?php 00002 /** 00003 * File containing the eZExecution class. 00004 * 00005 * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved. 00006 * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2 00007 * @version //autogentag// 00008 * @package lib 00009 */ 00010 00011 /*! 00012 \class eZExecution ezexecution.php 00013 \brief Handles proper script execution, fatal error detection and handling. 00014 00015 By registering a fatal error handler it's possible for the PHP script to 00016 catch fatal errors, such as "Call to a member function on a non-object". 00017 00018 By registering a cleanup handler it's possible to make sure the script can 00019 end properly. 00020 */ 00021 00022 class eZExecution 00023 { 00024 /*! 00025 Sets the clean exit flag to on, 00026 this notifies the exit handler that everything finished properly. 00027 */ 00028 static function setCleanExit() 00029 { 00030 self::$hasCleanExit = true; 00031 } 00032 00033 /*! 00034 Calls the cleanup handlers to make sure that the script is ready to exit. 00035 */ 00036 static function cleanup() 00037 { 00038 $handlers = eZExecution::cleanupHandlers(); 00039 foreach ( $handlers as $handler ) 00040 { 00041 if ( is_callable( $handler ) ) 00042 call_user_func( $handler ); 00043 else 00044 eZDebug::writeError('Could not call cleanup handler, is it a static public function?', __METHOD__ ); 00045 } 00046 } 00047 00048 /*! 00049 Adds a cleanup handler to the end of the list, 00050 \a $handler must contain the name of the function to call. 00051 The function is called at the end of the script execution to 00052 do some cleanups. 00053 */ 00054 static function addCleanupHandler( $handler ) 00055 { 00056 self::registerShutdownHandler(); 00057 self::$cleanupHandlers[] = $handler; 00058 } 00059 00060 /*! 00061 \return An array with cleanup handlers. 00062 */ 00063 static function cleanupHandlers() 00064 { 00065 return self::$cleanupHandlers; 00066 } 00067 00068 /*! 00069 Adds a fatal error handler to the end of the list, 00070 \a $handler must contain the name of the function to call. 00071 The handler will be called whenever a fatal error occurs, 00072 which usually happens when the script did not finish. 00073 */ 00074 static function addFatalErrorHandler( $handler ) 00075 { 00076 self::registerShutdownHandler(); 00077 self::$fatalErrorHandlers[] = $handler; 00078 } 00079 00080 /*! 00081 \return An array with fatal error handlers. 00082 */ 00083 static function fatalErrorHandlers() 00084 { 00085 return self::$fatalErrorHandlers; 00086 } 00087 00088 /*! 00089 \return true if the request finished properly. 00090 */ 00091 static function isCleanExit() 00092 { 00093 return self::$hasCleanExit; 00094 } 00095 00096 /*! 00097 Sets the clean exit flag and exits the page. 00098 Use this if you want premature exits instead of the \c exit function. 00099 */ 00100 static function cleanExit() 00101 { 00102 eZExecution::cleanup(); 00103 eZExecution::setCleanExit(); 00104 exit; 00105 } 00106 00107 /*! 00108 Exit handler which called after the script is done, if it detects 00109 that eZ Publish did not exit cleanly it will issue an error message 00110 and display the debug. 00111 */ 00112 static function uncleanShutdownHandler() 00113 { 00114 // Need to change the current directory, since this information is lost 00115 // when the callbackfunction is called. eZDocumentRoot is set in ::registerShutdownHandler 00116 if ( self::$eZDocumentRoot !== null ) 00117 { 00118 chdir( self::$eZDocumentRoot ); 00119 } 00120 00121 if ( eZExecution::isCleanExit() ) 00122 return; 00123 eZExecution::cleanup(); 00124 $handlers = eZExecution::fatalErrorHandlers(); 00125 foreach ( $handlers as $handler ) 00126 { 00127 if ( is_callable( $handler ) ) 00128 call_user_func( $handler ); 00129 else 00130 00131 eZDebug::writeError('Could not call fatal error handler, is it a static public function?', __METHOD__ ); 00132 } 00133 } 00134 00135 /*! 00136 Register ::uncleanShutdownHandler as shutdown function 00137 */ 00138 static public function registerShutdownHandler( $documentRoot = false ) 00139 { 00140 if ( !self::$shutdownHandle ) 00141 { 00142 register_shutdown_function( array('eZExecution', 'uncleanShutdownHandler') ); 00143 /* 00144 see: 00145 - http://www.php.net/manual/en/function.session-set-save-handler.php 00146 - http://bugs.php.net/bug.php?id=33635 00147 - http://bugs.php.net/bug.php?id=33772 00148 */ 00149 register_shutdown_function( array('eZSession', 'stop') ); 00150 set_exception_handler( array('eZExecution', 'defaultExceptionHandler') ); 00151 self::$shutdownHandle = true; 00152 } 00153 00154 // Needed by the error handler, since the current directory is lost when 00155 // the callback function eZExecution::uncleanShutdownHandler is called. 00156 if ( $documentRoot ) 00157 { 00158 self::$eZDocumentRoot = $documentRoot; 00159 } 00160 else if ( self::$eZDocumentRoot === null ) 00161 { 00162 self::$eZDocumentRoot = getcwd(); 00163 } 00164 } 00165 00166 /** 00167 * Installs the default Exception handler 00168 * 00169 * @params Exception the exception 00170 * @return void 00171 */ 00172 static public function defaultExceptionHandler( Exception $e ) 00173 { 00174 if( PHP_SAPI != 'cli' ) 00175 { 00176 header( 'HTTP/1.x 500 Internal Server Error' ); 00177 header( 'Content-Type: text/html' ); 00178 00179 echo "An unexpected error has occurred. Please contact the webmaster.<br />"; 00180 00181 if( eZDebug::isDebugEnabled() ) 00182 { 00183 echo $e->getMessage() . ' in ' . $e->getFile() . ' on line ' . $e->getLine(); 00184 } 00185 } 00186 else 00187 { 00188 $cli = eZCLI::instance(); 00189 $cli->error( "An unexpected error has occurred. Please contact the webmaster."); 00190 00191 if( eZDebug::isDebugEnabled() ) 00192 { 00193 $cli->error( $e->getMessage() . ' in ' . $e->getFile() . ' on line ' . $e->getLine() ); 00194 } 00195 } 00196 00197 eZLog::write( 'Unexpected error, the message was : ' . $e->getMessage() . ' in ' . $e->getFile() . ' on line ' . $e->getLine(), 'error.log' ); 00198 00199 eZExecution::cleanup(); 00200 eZExecution::setCleanExit(); 00201 exit( 1 ); 00202 } 00203 00204 static private $eZDocumentRoot = null; 00205 static private $hasCleanExit = false; 00206 static private $shutdownHandle = false; 00207 static private $fatalErrorHandlers = array(); 00208 static private $cleanupHandlers = array(); 00209 } 00210 00211 00212 ?>