<?php
/**
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
 * @version //autogentag//
 * @filesource
 * @package Execution
 */

/**
 * Class for handling fatal errors
 *
 * This class allows you to invoke a handler whenever a fatal error occurs, or
 * when an uncatched exception happens.  You can specify which callback
 * function to use and signal whether your application cleanly exited.
 *
 * Example:
 * <code>
 * <?php
 * class myExecutionHandler extends ezcExecutionBasicErrorHandler
 * {
 *     public static function onError( Exception $exception = null )
 *     {
 *         echo "Error!\n";
 *         // If you want, you can use the parent's onError method, but that
 *         // will only show a standard message.
 *         parent::onError( $exception );
 *     }
 * }
 * 
 * ezcExecution::init( 'myExecutionHandler' );
 * 
 * // ....
 * 
 * ezcExecution::cleanExit();
 * ?>
 * </code>
 *
 * @package Execution
 * @version //autogentag//
 * @mainclass
 */
class ezcExecution
{
    /**
     * Used for keeping a record whether the ezcExecution mechanism was
     * initialized through the init() method.
     * @var bool
     */
    static private $isInitialized = false;

    /**
     * Contains the name of the class that is going to be used to call the
     * onError() static method on when an fatal error situation occurs.
     * @var string
     */
    static private $callbackClassName = null;

    /**
     * Records whether we had a clean exit from the application or not. If it's
     * false then the shutdownCallbackHandler() method will not call the
     * Execution Handler's onError() method.
     * @var bool
     */
    static private $cleanExit = false;

    /**
     * A shutdown handler can not be removed, and that's why this static
     * property records if it was set or not. This ensures that the class will
     * only set the shutdown handler once over the lifetime of a request.
     * @var bool
     */
    static private $shutdownHandlerRegistered = false;

    /**
     * Initializes the ezcExecution environment.
     *
     * With this method you initialize the ezcExecution environment. You need
     * to specify a class name $callBackClassName that will be used to call the
     * onError() method on in case of an error. The class name that you
     * pass should implement the ezcExecutionErrorHandler interface. This
     * method takes care of registering the uncaught exception and shutdown
     * handlers. 
     *
     * @throws ezcExecutionInvalidCallbackException if an unknown callback
     *         class was passed.
     * @throws ezcExecutionWrongClassException if an invalid callback class was
     *         passed.
     * @throws ezcExecutionAlreadyInitializedException if the environment was
     *         already initialized.
     *
     * @param string $callbackClassName 
     * @return void
     */
    static public function init( $callbackClassName )
    {
        // Check if the passed classname actually exists
        if ( !ezcBaseFeatures::classExists( $callbackClassName, true ) )
        {
            throw new ezcExecutionInvalidCallbackException( $callbackClassName );
        }

        // Check if the passed classname actually implements the interface.
        if ( !in_array( 'ezcExecutionErrorHandler', class_implements( $callbackClassName ) ) )
        {
            throw new ezcExecutionWrongClassException( $callbackClassName );
        }

        // Check if it was already initialized once
        if ( self::$isInitialized == true )
        {
            throw new ezcExecutionAlreadyInitializedException();
        }

        // Install shutdown handler and exception handler
        set_exception_handler( array( 'ezcExecution', 'exceptionCallbackHandler' ) );
        if ( !self::$shutdownHandlerRegistered )
        {
            register_shutdown_function( array( 'ezcExecution', 'shutdownCallbackHandler' ) );
        }
        self::$callbackClassName = $callbackClassName;
        self::$isInitialized = true;
        self::$cleanExit = false;
        self::$shutdownHandlerRegistered = true;
    }

    /**
     * Resets the ezcExecution environment.
     *
     * With this function you reset the environment. Usually this method should
     * not be used, but in the cases when you want to restart the environment
     * this is the method to use. It also takes care of restoring the user
     * defined uncaught exception handler, but it can not undo the registered
     * shutdown handler as PHP doesn't provide that functionality.
     *
     * @return void
     */
    static public function reset()
    {
        if ( self::$isInitialized )
        {
            restore_exception_handler();
        }
        self::$callbackClassName = null;
        self::$isInitialized = false;
        self::$cleanExit = false;
    }

    /**
     * Marks the current application as cleanly-exited.
     *
     * With this method you signal the ezcExecution environment that your
     * application ended without errors. This is usually done just before you
     * reach the end of your script, or just before you call 
     * {@link http://www.php.net/exit exit()} or 
     * {@link http://www.php.net/die die()}.
     *
     * @throws ezcExecutionNotInitializedException if the environment was not
     *         yet initialized.
     * @return void
     */
    static public function cleanExit()
    {
        self::$cleanExit = true;        
    }

    /**
     * Handler for uncaught exceptions.
     *
     * The ezcExecution environment installs this method as handler for
     * uncaught exceptions and will be called when one is found.  This method's
     * only function is to call the ::onError() static method of the error
     * handler set with the init() method. It passes along the uncaught
     * exception to this method.
     *
     * This method has to be public otherwise PHP can not call it, but you
     * should never call this method yourself.
     *
     * @param Exception $e
     * @return void
     */
    static public function exceptionCallbackHandler( Exception $e )
    {
        self::$cleanExit = true;        
        call_user_func( array( self::$callbackClassName, 'onError' ), $e );
    }

    /**
     * Shutdown handler
     *
     * The ezcExecution environment installs this method as general shutdown handler.
     * This method's only function is to call the ::onError() static method of
     * the error handler set with the init() method.
     *
     * @return void
     */
    static public function shutdownCallbackHandler()
    {
        if ( !self::$cleanExit )
        {
            self::$cleanExit = true;        
            call_user_func( array( self::$callbackClassName, 'onError' ) );
        }
    }
}
?>
