<?php
/**
* @package simpleMVC
* @class smvcShutdownManager
* @since 2010-12-20
* @licence dual licence LGPL / MIT
* @author jonathan gotti <jgotti at jgotti dot net>
*/
class smvcShutdownManager{
static private $_registeredCallbacks = array();
static private $_byPassCallBacks = false;
static private $_registered = false;
static private $_id = 0;
/**
* Check that given callable is registered by shutdown manager. It also allow to check that smvcShutdownManager is registered itself
* @param callback $callBack check that the given callback (or id of registered callback return by register method) is registered (if null then check that smvcShutdownManager itself is registered)
* @param bool $returnPriority if true the actual priority level of the callback will be return instead of bool (be aware it may return 0 in such case that doesn't mean false)
* @return bool or integer if $returnPriority is passed to true
*/
static public function isRegistered($callBack=null,$returnPriority=false){
if( null === $callBack ){
return self::$_registered;
}
if( is_int($callBack) ){
return isset(self::$_registeredCallbacks[$callBack])?($returnPriority?self::$_registeredCallbacks[$callBack][1]:true):false;
}
foreach(self::$_registeredCallbacks as $cb){
if( $cb[0]===$callBack)
return $returnPriority?$cb[1]:true;
}
return false;
}
/**
* register a callback function to be executed as a shutdown fucntion
* @param callback $callBack the callback to register, if already registered then it
* @param int $priority the priority level of the callback (higher level means later call)
* @param mixed $param you can add as many optionnal parameter as you want to the callback
* @return int internal callback id
*/
static public function register($callBack,$priority=0){
if(! self::$_registered ){
register_shutdown_function(array(__class__,'_registered_shutdown'));
self::$_registered = true;
}
$params = func_get_args();
self::$_registeredCallbacks[++self::$_id] = array($callBack,(int) $priority,self::$_id,array_slice($params,2));
return self::$_id;
}
/**
* unregister previously registered callback
* @param callback $callBack the callback to unregister (or the callback id returned by register method )
* /!\ if null is given then will unregister all previously registered callback.
* @return bool return true if successfully removed else return false
*/
static public function unregister($callBack){
if( is_null($callBack) ){
self::$_registeredCallbacks = array();
return true;
}
if( is_int($callBack) ){
if( !isset(self::$_registered[$callBack]))
return false;
unset(self::$_registered[$callBack]);
return true;
}
foreach(self::$_registeredCallbacks as $k=>$cb){
if( $cb[0]===$callBack){
unset(self::$_registeredCallbacks[$k]);
return true;
}
}
return false;
}
/**
* shutdown the script by calling exit.
* @param mixed $status may be a string as in die or a status code (@see exit)
* @param bool $byPassCallBacks if true then will do a normal exit without calling any of the registered callbacks
*/
static public function shutdown($status=0,$byPassCallBacks=false){
self::$_byPassCallBacks = $byPassCallBacks;
exit($status?$status:0);
}
/**
* THIS IS NOT INTENTED TO BE CALLED OTHER THAN INTERNALLY
* the only reason for this to be public is that it's a necessity for register_shutdown_function to see it
* there's no reason at all for you to call this
* @internal
*/
static public function _registered_shutdown(){
if( self::$_byPassCallBacks )
return;
#- first sort the stack
uasort(self::$_registeredCallbacks,array(__class__,'_compare'));
foreach( self::$_registeredCallbacks as $cb){
call_user_func_array($cb[0],$cb[3]);
}
}
/**
* used to sort callbacks by priority respecting their registering order
* @internal
* @private
*/
static private function _compare($a,$b){
if( $a[1] === $b[1] ){
return $a[2] > $b[2]?1:-1;
}
return $a[1] > $b[1]?1:-1;
}
}
|