mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-22 23:00:56 +01:00
b56175a0f4
Benefit over old default is, that we get a short etemplate_exec_id giving better performance for ajax requests. Drawback is currently poor garbadge collection only removing requests not used in 4 hours or which call egw_framework::window_close on server-side. We can improve garbadge-collection by binding to window on(before)unload sending a (synchronious) request to server to remove concerned eT2 request.
147 lines
4.4 KiB
PHP
147 lines
4.4 KiB
PHP
<?php
|
|
/**
|
|
* eGroupWare - eTemplate request object storing the data in EGroupware instance cache
|
|
*
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
* @package etemplate
|
|
* @subpackage api
|
|
* @link http://www.egroupware.org
|
|
* @author Ralf Becker <RalfBecker@outdoor-training.de>
|
|
* @copyright (c) 2014 by Ralf Becker <RalfBecker@outdoor-training.de>
|
|
* @version $Id$
|
|
*/
|
|
|
|
/**
|
|
* Class to represent the persitent information stored on the server for each eTemplate request
|
|
*
|
|
* The information is stored in EGroupware tree cache with a given fixed expiration time.
|
|
* We use tree cache with install-id as part of key to not loose all requests, if admin
|
|
* clears instance cache (Admin >> Clear cache and register hooks)!
|
|
*
|
|
* To enable the use of this handler, you have to set (in etemplate/inc/class.etemplate_request.inc.php):
|
|
*
|
|
* etemplate_request::$request_class = 'etemplate_request_cache';
|
|
*
|
|
* The request object should be instancated only via the factory method etemplate_request::read($id=null)
|
|
*
|
|
* $request = etemplate_request::read();
|
|
*
|
|
* // add request data
|
|
*
|
|
* $id = $request->id();
|
|
*
|
|
* b) open or modify an existing request:
|
|
*
|
|
* if (!($request = etemplate_request::read($id)))
|
|
* {
|
|
* // request not found
|
|
* }
|
|
*
|
|
* Ajax requests can use this object to open the original request by using the id, they have to transmit back,
|
|
* and register further variables, modify the registered ones or delete them AND then update the id, if it changed:
|
|
*
|
|
* if (($new_id = $request->id()) != $id)
|
|
* {
|
|
* $response->addAssign('etemplate_exec_id','value',$new_id);
|
|
* }
|
|
*
|
|
* For an example look in link_widget::ajax_search()
|
|
*/
|
|
|
|
class etemplate_request_cache extends etemplate_request
|
|
{
|
|
/**
|
|
* Expiration time of 4 hours
|
|
*/
|
|
const EXPIRATION = 7200;
|
|
|
|
/**
|
|
* request id
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $id;
|
|
|
|
/**
|
|
* Private constructor to force the instancation of this class only via it's static factory method read
|
|
*
|
|
* @param string $_id
|
|
*/
|
|
private function __construct($_id=null)
|
|
{
|
|
$this->id = $_id ? $_id : self::request_id();
|
|
//error_log(__METHOD__."($_id) this->id=$this->id");
|
|
}
|
|
|
|
/**
|
|
* return the id of this request
|
|
*
|
|
* @return string
|
|
*/
|
|
public function id()
|
|
{
|
|
//error_log(__METHOD__."() id=$this->id");
|
|
return $this->id;
|
|
}
|
|
|
|
/**
|
|
* Factory method to get a new request object or the one for an existing request
|
|
*
|
|
* @param string $id=null
|
|
* @return etemplate_request|boolean the object or false if $id is not found
|
|
*/
|
|
static function read($id=null)
|
|
{
|
|
$request = new etemplate_request_cache($id);
|
|
|
|
if (!is_null($id))
|
|
{
|
|
//error_log(__METHOD__."() reading $id");
|
|
if (!($request->data = egw_cache::getTree($GLOBALS['egw_info']['server']['install_id'].'_etemplate', $id)))
|
|
{
|
|
error_log("Error reading etemplate request data for id=$id!");
|
|
return false;
|
|
}
|
|
}
|
|
//error_log(__METHOD__."(id=$id) returning ".array2string($request));
|
|
return $request;
|
|
}
|
|
|
|
/**
|
|
* creates a new unique request-id
|
|
*
|
|
* @return string
|
|
*/
|
|
static function request_id()
|
|
{
|
|
return uniqid($GLOBALS['egw_info']['flags']['currentapp'].'_'.$GLOBALS['egw_info']['user']['account_lid'].'_',true);
|
|
}
|
|
|
|
/**
|
|
* saves content,readonlys,template-keys, ... via eGW's appsession function
|
|
*
|
|
* As a user may open several windows with the same content/template wie generate a location-id from microtime
|
|
* which is used as location for request to descriminate between the different windows. This location-id
|
|
* is then saved as a hidden-var in the form. The above mentions session-id has nothing to do / is different
|
|
* from the session-id which is constant for all windows opened in one session.
|
|
*/
|
|
function __destruct()
|
|
{
|
|
if ($this->remove_if_not_modified && !$this->data_modified && isset($this->data['last_saved']))
|
|
{
|
|
//error_log(__METHOD__."() destroying $this->id");
|
|
egw_cache::unsetTree($GLOBALS['egw_info']['server']['install_id'].'_etemplate', $this->id);
|
|
}
|
|
elseif (($this->data_modified ||
|
|
// if half of expiration time is over, save it anyway, to restart expiration time
|
|
isset($this->data['last_saved']) && (time()-$this->data['last_saved']) > self::EXPIRATION/2))
|
|
{
|
|
//error_log(__METHOD__."() saving $this->id");
|
|
$this->data['last_saved'] = time();
|
|
if (!egw_cache::setTree($GLOBALS['egw_info']['server']['install_id'].'_etemplate', $this->id, $this->data, self::EXPIRATION))
|
|
{
|
|
error_log("Error storing etemplate request data for id=$this->id!");
|
|
}
|
|
}
|
|
}
|
|
} |