mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-01-03 04:29:28 +01:00
new egw::on_shutdown($callback, $args) method to register shutdonw handlers to run after output send back to user, thought only really working with fastCGI, Apache mod_php waits ...
This commit is contained in:
parent
68849834f9
commit
a786894c27
@ -171,8 +171,6 @@ class egw extends egw_minimal
|
|||||||
$this->preferences = new preferences();
|
$this->preferences = new preferences();
|
||||||
$this->applications = new applications();
|
$this->applications = new applications();
|
||||||
|
|
||||||
register_shutdown_function(array($this, 'shutdown'));
|
|
||||||
|
|
||||||
if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login' && $GLOBALS['egw_info']['flags']['currentapp'] != 'logout')
|
if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login' && $GLOBALS['egw_info']['flags']['currentapp'] != 'logout')
|
||||||
{
|
{
|
||||||
$this->verify_session();
|
$this->verify_session();
|
||||||
@ -211,8 +209,6 @@ class egw extends egw_minimal
|
|||||||
date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
|
date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
|
||||||
}
|
}
|
||||||
|
|
||||||
register_shutdown_function(array($this, 'shutdown'));
|
|
||||||
|
|
||||||
$this->define_egw_constants();
|
$this->define_egw_constants();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,20 +534,70 @@ class egw extends egw_minimal
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* eGW's shutdown handler
|
* registered shutdown callbacks and optional arguments
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
*/
|
*/
|
||||||
function shutdown()
|
private static $shutdown_callbacks = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a callback to run on shutdown AFTER output send to user
|
||||||
|
*
|
||||||
|
* Allows eg. static classes (no destructor) to run on shutdown AND
|
||||||
|
* garanties to run AFTER output send to user.
|
||||||
|
*
|
||||||
|
* @param callable $callback use array($classname, $method) for static methods
|
||||||
|
* @param array $args=array()
|
||||||
|
*/
|
||||||
|
public static function on_shutdown($callback, array $args=array())
|
||||||
|
{
|
||||||
|
array_unshift($args, $callback);
|
||||||
|
|
||||||
|
// prepend new callback, to run them in oposite order they are registered
|
||||||
|
array_unshift(self::$shutdown_callbacks, $args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown handler running all registered on_shutdown callbacks and then disconnecting from db
|
||||||
|
*/
|
||||||
|
function __destruct()
|
||||||
{
|
{
|
||||||
if (!defined('EGW_SHUTDOWN'))
|
if (!defined('EGW_SHUTDOWN'))
|
||||||
{
|
{
|
||||||
define('EGW_SHUTDOWN',True);
|
define('EGW_SHUTDOWN',True);
|
||||||
|
|
||||||
if (class_exists('egw_link',false)) // false = no autoload!
|
// send json response BEFORE flushing output
|
||||||
|
if (egw_json_request::isJSONRequest())
|
||||||
{
|
{
|
||||||
egw_link::save_session_cache();
|
egw_json_response::sendResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
// flush all output to user
|
||||||
|
/* does NOT work on Apache :-(
|
||||||
|
for($i = 0; ob_get_level() && $i < 10; ++$i)
|
||||||
|
{
|
||||||
|
ob_end_flush();
|
||||||
|
}
|
||||||
|
flush();*/
|
||||||
|
// working for fastCGI :-)
|
||||||
|
if (function_exists('fastcgi_finish_request'))
|
||||||
|
{
|
||||||
|
fastcgi_finish_request();
|
||||||
|
}
|
||||||
|
|
||||||
|
// run all on_shutdown, do NOT stop on exceptions
|
||||||
|
foreach(self::$shutdown_callbacks as $data)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
//error_log(__METHOD__."() running ".array2string($data));
|
||||||
|
$callback = array_shift($data);
|
||||||
|
call_user_func_array($callback, $data);
|
||||||
|
}
|
||||||
|
catch (Exception $ex) {
|
||||||
|
_egw_log_exception($ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// call the asyncservice check_run function if it is not explicitly set to cron-only
|
// call the asyncservice check_run function if it is not explicitly set to cron-only
|
||||||
//
|
|
||||||
if (!$GLOBALS['egw_info']['server']['asyncservice']) // is default
|
if (!$GLOBALS['egw_info']['server']['asyncservice']) // is default
|
||||||
{
|
{
|
||||||
ExecMethod('phpgwapi.asyncservice.check_run','fallback');
|
ExecMethod('phpgwapi.asyncservice.check_run','fallback');
|
||||||
|
@ -122,7 +122,6 @@ class egw_json_request
|
|||||||
error_log($_SERVER['PHP_SELF']. ' stopped for security reason. '.$menuaction.' is not valid. class- or function-name must start with ajax!!!');
|
error_log($_SERVER['PHP_SELF']. ' stopped for security reason. '.$menuaction.' is not valid. class- or function-name must start with ajax!!!');
|
||||||
// send message also to the user
|
// send message also to the user
|
||||||
throw new Exception($_SERVER['PHP_SELF']. ' stopped for security reason. '.$menuaction.' is not valid. class- or function-name must start with ajax!!!');
|
throw new Exception($_SERVER['PHP_SELF']. ' stopped for security reason. '.$menuaction.' is not valid. class- or function-name must start with ajax!!!');
|
||||||
exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($template))
|
if (isset($template))
|
||||||
@ -212,7 +211,7 @@ class egw_json_response
|
|||||||
*/
|
*/
|
||||||
public function haveJSONResponse()
|
public function haveJSONResponse()
|
||||||
{
|
{
|
||||||
return (boolean) $this->responseArray;
|
return $this->responseArray || $this->beforeSendDataProcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -220,19 +219,22 @@ class egw_json_response
|
|||||||
*/
|
*/
|
||||||
private function sendHeader()
|
private function sendHeader()
|
||||||
{
|
{
|
||||||
|
$file = $line = null;
|
||||||
if (headers_sent($file, $line))
|
if (headers_sent($file, $line))
|
||||||
{
|
{
|
||||||
error_log(__METHOD__."() header already sent by $file line $line: ".function_backtrace());
|
error_log(__METHOD__."() header already sent by $file line $line: ".function_backtrace());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
//Send the character encoding header
|
{
|
||||||
header('content-type: application/json; charset='.translation::charset());
|
//Send the character encoding header
|
||||||
|
header('content-type: application/json; charset='.translation::charset());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private function which is used to send the result via HTTP
|
* Private function which is used to send the result via HTTP
|
||||||
*/
|
*/
|
||||||
public function sendResult()
|
public static function sendResult()
|
||||||
{
|
{
|
||||||
$inst = self::get();
|
$inst = self::get();
|
||||||
|
|
||||||
@ -265,7 +267,7 @@ class egw_json_response
|
|||||||
*/
|
*/
|
||||||
public function printOutput()
|
public function printOutput()
|
||||||
{
|
{
|
||||||
// do nothing, as output is triggered by destructor
|
// do nothing, as output is triggered by egw::__destruct()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -288,7 +290,7 @@ class egw_json_response
|
|||||||
public function initResponseArray()
|
public function initResponseArray()
|
||||||
{
|
{
|
||||||
$return = $this->responseArray;
|
$return = $this->responseArray;
|
||||||
$this->responseArray = array();
|
$this->responseArray = $this->beforeSendDataProcs = array();
|
||||||
$this->hasData = false;
|
$this->hasData = false;
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
@ -571,16 +573,6 @@ class egw_json_response
|
|||||||
'params' => $params
|
'params' => $params
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor
|
|
||||||
*/
|
|
||||||
public function __destruct()
|
|
||||||
{
|
|
||||||
//Only send the response if this instance is the singleton instance
|
|
||||||
if ($this == self::get())
|
|
||||||
$this->sendResult();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -216,6 +216,10 @@ class egw_link extends solink
|
|||||||
{
|
{
|
||||||
self::$file_access_cache = array();
|
self::$file_access_cache = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// register self::save_session_cache to run on shutdown
|
||||||
|
egw::on_shutdown(array(__CLASS__, 'save_session_cache'));
|
||||||
|
|
||||||
//error_log(__METHOD__.'() items in title-cache: '.count(self::$title_cache).' file-access-cache: '.count(self::$file_access_cache));
|
//error_log(__METHOD__.'() items in title-cache: '.count(self::$title_cache).' file-access-cache: '.count(self::$file_access_cache));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,9 +264,6 @@ class egw_link extends solink
|
|||||||
//error_log(__METHOD__.'() items in title-cache: '.count(self::$title_cache).' file-access-cache: '.count(self::$file_access_cache));
|
//error_log(__METHOD__.'() items in title-cache: '.count(self::$title_cache).' file-access-cache: '.count(self::$file_access_cache));
|
||||||
$GLOBALS['egw']->session->appsession('link_title_cache','phpgwapi',self::$title_cache);
|
$GLOBALS['egw']->session->appsession('link_title_cache','phpgwapi',self::$title_cache);
|
||||||
$GLOBALS['egw']->session->appsession('link_file_access_cache','phpgwapi',self::$file_access_cache);
|
$GLOBALS['egw']->session->appsession('link_file_access_cache','phpgwapi',self::$file_access_cache);
|
||||||
|
|
||||||
// send out notifications about added, changed or removed links
|
|
||||||
self::run_notifies();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -434,7 +435,7 @@ class egw_link extends solink
|
|||||||
if (empty($only_app) || $only_app == self::VFS_APPNAME ||
|
if (empty($only_app) || $only_app == self::VFS_APPNAME ||
|
||||||
($only_app[0] == '!' && $only_app != '!'.self::VFS_APPNAME))
|
($only_app[0] == '!' && $only_app != '!'.self::VFS_APPNAME))
|
||||||
{
|
{
|
||||||
if ($vfs_ids = self::list_attached($app,$id))
|
if (($vfs_ids = self::list_attached($app,$id)))
|
||||||
{
|
{
|
||||||
$ids += $vfs_ids;
|
$ids += $vfs_ids;
|
||||||
}
|
}
|
||||||
@ -496,7 +497,7 @@ class egw_link extends solink
|
|||||||
{
|
{
|
||||||
$links[$id] = array();
|
$links[$id] = array();
|
||||||
}
|
}
|
||||||
if ($vfs_ids = self::list_attached($app,$id))
|
if (($vfs_ids = self::list_attached($app,$id)))
|
||||||
{
|
{
|
||||||
$links[$id] += $vfs_ids;
|
$links[$id] += $vfs_ids;
|
||||||
}
|
}
|
||||||
@ -506,7 +507,7 @@ class egw_link extends solink
|
|||||||
{
|
{
|
||||||
// agregate links by app
|
// agregate links by app
|
||||||
$app_ids = array();
|
$app_ids = array();
|
||||||
foreach($links as $src_id => &$targets)
|
foreach($links as &$targets)
|
||||||
{
|
{
|
||||||
foreach($targets as $link)
|
foreach($targets as $link)
|
||||||
{
|
{
|
||||||
@ -799,7 +800,7 @@ class egw_link extends solink
|
|||||||
}
|
}
|
||||||
$method = $reg['title'];
|
$method = $reg['title'];
|
||||||
|
|
||||||
$title = ExecMethod($method,$id);
|
if (true) $title = ExecMethod($method,$id);
|
||||||
|
|
||||||
if ($id && is_null($title)) // $app,$id has been deleted ==> unlink all links to it
|
if ($id && is_null($title)) // $app,$id has been deleted ==> unlink all links to it
|
||||||
{
|
{
|
||||||
@ -858,7 +859,7 @@ class egw_link extends solink
|
|||||||
}
|
}
|
||||||
if ($ids_to_query)
|
if ($ids_to_query)
|
||||||
{
|
{
|
||||||
for ($n = 0; $ids = array_slice($ids_to_query,$n*self::MAX_TITLES_QUERY,self::MAX_TITLES_QUERY); ++$n)
|
for ($n = 0; ($ids = array_slice($ids_to_query,$n*self::MAX_TITLES_QUERY,self::MAX_TITLES_QUERY)); ++$n)
|
||||||
{
|
{
|
||||||
foreach(ExecMethod(self::$app_register[$app]['titles'],$ids) as $id => $t)
|
foreach(ExecMethod(self::$app_register[$app]['titles'],$ids) as $id => $t)
|
||||||
{
|
{
|
||||||
@ -1039,6 +1040,7 @@ class egw_link extends solink
|
|||||||
if ($app == self::VFS_APPNAME && is_array($link) && !empty($link['type']))
|
if ($app == self::VFS_APPNAME && is_array($link) && !empty($link['type']))
|
||||||
{
|
{
|
||||||
$path = self::vfs_path($link['app2'], $link['id2'], $link['id'], true);
|
$path = self::vfs_path($link['app2'], $link['id2'], $link['id'], true);
|
||||||
|
$p = null;
|
||||||
if (self::mime_open($path, $link['type'], $p))
|
if (self::mime_open($path, $link['type'], $p))
|
||||||
{
|
{
|
||||||
$popup = $p;
|
$popup = $p;
|
||||||
@ -1169,11 +1171,11 @@ class egw_link extends solink
|
|||||||
* @param string $file VFS path to link to
|
* @param string $file VFS path to link to
|
||||||
* @param string $comment='' comment to add to the link
|
* @param string $comment='' comment to add to the link
|
||||||
*/
|
*/
|
||||||
static function link_file($app,$id,$file,$comment='')
|
static function link_file($app,$id,$file)//,$comment='')
|
||||||
{
|
{
|
||||||
$app_path = self::vfs_path($app,$id);
|
$app_path = self::vfs_path($app,$id);
|
||||||
$ok = true;
|
$ok = true;
|
||||||
if (file_exists($app_path) || ($Ok = mkdir($app_path,0,true)))
|
if (file_exists($app_path) || ($ok = mkdir($app_path,0,true)))
|
||||||
{
|
{
|
||||||
if (!egw_vfs::stat($file))
|
if (!egw_vfs::stat($file))
|
||||||
{
|
{
|
||||||
@ -1370,6 +1372,10 @@ class egw_link extends solink
|
|||||||
{
|
{
|
||||||
if ($link_id && isset(self::$app_register[$notify_app]) && isset(self::$app_register[$notify_app]['notify']))
|
if ($link_id && isset(self::$app_register[$notify_app]) && isset(self::$app_register[$notify_app]['notify']))
|
||||||
{
|
{
|
||||||
|
if (!self::$notifies)
|
||||||
|
{
|
||||||
|
egw::on_shutdown(array(__CLASS__, 'run_notifies'));
|
||||||
|
}
|
||||||
self::$notifies[] = array(
|
self::$notifies[] = array(
|
||||||
'method' => self::$app_register[$notify_app]['notify'],
|
'method' => self::$app_register[$notify_app]['notify'],
|
||||||
'type' => $type,
|
'type' => $type,
|
||||||
@ -1383,7 +1389,7 @@ class egw_link extends solink
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run notifications called by egw_link::save_session_cache from egw::shutdown, after regular processing is finished
|
* Run notifications called by egw::on_shutdown(), after regular processing is finished
|
||||||
*/
|
*/
|
||||||
static public function run_notifies()
|
static public function run_notifies()
|
||||||
{
|
{
|
||||||
@ -1451,13 +1457,11 @@ class egw_link extends solink
|
|||||||
//error_log(__METHOD__."($app,$id,$title,$file_access)");
|
//error_log(__METHOD__."($app,$id,$title,$file_access)");
|
||||||
if (!is_null($title))
|
if (!is_null($title))
|
||||||
{
|
{
|
||||||
$cache =& self::get_cache($app,$id);
|
self::$title_cache[$app.':'.$id] = $title;
|
||||||
$cache = $title;
|
|
||||||
}
|
}
|
||||||
if (!is_null($file_access))
|
if (!is_null($file_access))
|
||||||
{
|
{
|
||||||
$cache =& self::get_cache($app,$id,'file_access');
|
self::$file_access_cache[$app.':'.$id] = $file_access;
|
||||||
$cache = $file_access;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user