Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F823746
in-portal
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Mon, Mar 10, 2:06 PM
Size
18 KB
Mime Type
text/x-diff
Expires
Wed, Mar 12, 2:06 PM (1 d, 1 h)
Engine
blob
Format
Raw Data
Handle
585831
Attached To
rINP In-Portal
in-portal
View Options
Index: branches/RC/core/kernel/event_manager.php
===================================================================
--- branches/RC/core/kernel/event_manager.php (revision 9731)
+++ branches/RC/core/kernel/event_manager.php (revision 9732)
@@ -1,592 +1,592 @@
<?php
define('hBEFORE', 1);
define('hAFTER', 2);
define('reBEFORE', 1);
define('reAFTER', 2);
class kEventManager extends kBase {
/**
* Connection to database
*
* @var kDBConnection
* @access public
*/
var $Conn;
/**
* Cache of QueryString parameters
* from config, that are represented
* in enviroment variable
*
* @var Array
*/
var $queryMaps = Array();
/**
* Build events registred for
* pseudo classes. key - pseudo class
* value - event name
*
* @var Array
* @access private
*/
var $buildEvents=Array();
/**
* Events, that should be run before parser initialization
*
* @var Array
*/
var $beforeRegularEvents = Array();
/**
* Events, that should be run after parser initialization
*
* @var Array
*/
var $afterRegularEvents = Array();
/**
* Holds before hooks
* key - prefix.event (to link to)
* value - hooked event info
*
* @var Array
* @access private
*/
var $beforeHooks=Array();
/**
* Holds after hooks
* key - prefix.event (to link to)
* value - hooked event info
*
* @var Array
* @access private
*/
var $afterHooks = Array();
var $recursionStack = Array();
function kEventManager()
{
parent::kBase();
$this->Conn =& $this->Application->GetADODBConnection();
}
/**
* Set's new enviroment parameter mappings
* between their names as application vars
*
* @param Array $new_query_maps
* @access public
*/
/*function setQueryMaps($new_query_maps)
{
$this->queryMaps = $new_query_maps;
}*/
/**
* Adds new query map to already parsed query maps
*
* @param string $prefix
*/
function setQueryMap($prefix_special)
{
list($prefix) = explode('.', $prefix_special);
$query_map = $this->getQueryMap($prefix);
if ($query_map) {
$this->queryMaps[$prefix_special] = $query_map;
}
else {
unset($this->queryMaps[$prefix]);
}
// 'passed' is set later in ProcessRequest - do we really need it here? (it breakes HTTPQuery initialization...)
// $this->Application->SetVar('passed', implode(',', array_keys($this->queryMaps)) );
return $query_map;
}
/**
* Returns QueryMap for requested unit config. In case if unit config is a clone, then get parent item's (from prefix) config to create clone
*
* @param string $prefix
* @return Array
*/
function getQueryMap($prefix)
{
$query_map = $this->Application->getUnitOption($prefix, 'QueryString');
if (!$query_map) {
if (preg_match('/(.*?)-(.*)/', $prefix, $regs)) {
// #prefix - format for configs, that are only cloned & optionally used for hooking (without # is old format)
$prefix = $this->Application->UnitConfigReader->prefixRegistred('#'.$regs[2]) ? '#'.$regs[2] : $regs[2];
return $this->Application->getUnitOption($prefix, 'QueryString');
}
}
return $query_map;
}
/**
* Registers new regular event
*
* @param string $short_name name to be used to store last maintenace run info
* @param string $event_name
* @param int $run_interval run interval in seconds
* @param int $type before or after regular event
*/
function registerRegularEvent($short_name, $event_name, $run_interval, $type = reBEFORE)
{
if($type == reBEFORE)
{
$this->beforeRegularEvents[$short_name] = Array('EventName' => $event_name, 'RunInterval' => $run_interval);
}
else
{
$this->afterRegularEvents[$short_name] = Array('EventName' => $event_name, 'RunInterval' => $run_interval);
}
}
function registerBuildEvent($pseudo_class,$build_event_name)
{
$this->buildEvents[$pseudo_class]=$build_event_name;
}
/**
* Returns build event by pseudo class
* name if any defined in config
*
* @param string $pseudo_class
* @return kEvent
* @access public
*/
function &getBuildEvent($pseudo_class)
{
$false = false;
if( !isset($this->buildEvents[$pseudo_class]) ) return $false;
$event = new kEvent();
$event->Name=$this->buildEvents[$pseudo_class];
$event->MasterEvent=null;
return $event;
}
/**
* Check if event is called twice, that causes recursion
*
* @param kEvent $event
*/
function isRecursion(&$event)
{
$event_key = $event->getPrefixSpecial().':'.$event->Name;
return in_array($event_key, $this->recursionStack) ? true : false;
}
function pushEvent(&$event)
{
$event_key = $event->getPrefixSpecial().':'.$event->Name;
array_push($this->recursionStack, $event_key);
}
function popEvent()
{
array_pop($this->recursionStack);
}
/**
* Allows to process any type of event
*
* @param kEvent $event
* @access public
*/
function HandleEvent(&$event)
{
if ($this->isRecursion($event)) {
return true;
}
$this->pushEvent($event);
if( !$this->Application->prefixRegistred($event->Prefix) )
{
$unit_config_reader =& $this->Application->recallObject('kUnitConfigReader');
$unit_config_reader->loadConfig($event->Prefix);
if( !$this->Application->prefixRegistred($event->Prefix) )
{
trigger_error('Prefix <b>'.$event->Prefix.'</b> not registred (requested event <b>'.$event->Name.'</b>)', E_USER_NOTICE);
return false;
}
}
if (!$event->SkipBeforeHooks) {
$this->processHooks($event, hBEFORE);
if ($event->status == erFATAL) return true;
}
$event_handler =& $this->Application->recallObject($event->Prefix.'_EventHandler');
/* @var $event_handler kEventHandler */
$event_handler->processEvent($event);
if ($event->status == erFATAL) return true;
if (!$event->SkipAfterHooks) {
$this->processHooks($event, hAFTER);
}
$this->popEvent();
return true;
}
function ProcessRequest()
{
$this->processOpener();
// 1. get events from $_POST
$events = $this->Application->GetVar('events');
if ($events === false) $events = Array();
// 2. if nothing there, then try to find them in $_GET
if ($this->queryMaps && !$events) {
// if we got $_GET type submit (links, not javascript)
foreach ($this->queryMaps as $prefix_special => $query_map) {
$query_map = array_flip($query_map);
if (isset($query_map['event'])) {
$event_name = $this->Application->GetVar($prefix_special.'_event');
if ($event_name) {
$events[$prefix_special] = $event_name;
}
}
}
$actions = $this->Application->GetVar('do');
if ($actions) {
list($prefix, $event_name) = explode('_', $actions);
$events[$prefix] = $event_name;
}
}
// 3. store all prefixes passed before event processing, because they are used by GetTopmostPrefix
$all_passed = explode(',', $this->Application->GetVar('passed'));
foreach ($events as $prefix_special => $event_name) {
if (!$event_name) continue;
$prefix_special = explode('.',$prefix_special);
array_push($all_passed, $prefix_special[0]);
}
$this->Application->SetVar('all_passed', implode(',', $all_passed));
foreach ($events as $prefix_special => $event_name) {
if (!$event_name) continue;
if (is_array($event_name)) {
$event_name = key($event_name);
$events[$prefix_special] = $event_name;
$this->Application->SetVar($prefix_special.'_event', $event_name);
}
$event = new kEvent();
$event->Name = $event_name;
$event->Prefix_Special = $prefix_special;
$prefix_special = explode('.',$prefix_special);
$event->Prefix = $prefix_special[0];
// array_push($passed, $prefix_special[0]);
$event->Special = isset($prefix_special[1]) ? $prefix_special[1] : '';
$event->redirect_params = Array('opener' => 's', 'pass' => 'all');
$event->redirect = true;
$event_handler =& $this->Application->recallObject($event->Prefix.'_EventHandler');
/* @var $event_handler kEventHandler */
- if (preg_match('/(.*?)-(.*)/', $event->Prefix, $regs)) {
+ if (preg_match('/(.*?)-(.*)/', $event->Prefix, $regs) && $this->Application->UnitConfigReader->prefixRegistred($regs[1])) {
// this is event from cloned config -> load parent config to create valid clone
$this->Application->UnitConfigReader->loadConfig($regs[1]);
$this->Application->HandleEvent( new kEvent($regs[1].':OnAfterConfigRead') );
}
$event->setEventParam('top_prefix', $this->Application->GetTopmostPrefix($event->Prefix, true));
if (($this->Application->RecallVar('user_id') == -1) || $event_handler->CheckPermission($event)) {
$this->HandleEvent($event);
}
if ($event->status == erSTOP) {
// event requested to stop processing at this point
safeDefine('DBG_SKIP_REPORTING', 1);
$this->Application->Session->SaveData();
exit;
}
if ($event->status == erPERM_FAIL) {
// should do redirect but to no_permissions template
$event->redirect = $this->Application->IsAdmin() ? 'no_permission' : $this->Application->ConfigValue('NoPermissionTemplate');
$event->redirect_params['pass'] = 'm';
$event->redirect_params['m_cat_id'] = 0;
// restore stuff, that processOpener() changed
$wid = $this->Application->GetVar('m_wid');
$this->Application->RestoreVar(rtrim('opener_stack_'.$wid, '_'));
// don't save last_template, because no_permission template does js history.back and could cause invalid opener_stack content
$this->Application->SetVar('skip_last_template', 1);
}
if ( ($event->status == erSUCCESS || $event->status == erPERM_FAIL) && ($event->redirect === true || strlen($event->redirect) > 0)) {
// we need to pass category if the action was submitted to self-template, with the category passed
// and it has not explicly set redirect template or pass_cateogry param
if ($event->redirect === true && !isset($event->redirect_params['pass_category']) && $this->Application->GetVar('m_cat_id')) {
$event->redirect_params['pass_category'] = 1;
}
$wid = $this->Application->GetVar('m_wid');
if ($wid && $event->redirect_params['opener'] == 'u') {
$event->redirect_params['opener'] = 's'; // because Application->HREF will react differently when 'opener' = 'u'
$event->redirect = defined('CLOSE_POPUP_TPL') ? CLOSE_POPUP_TPL : 'incs/close_popup';
}
$this->Application->Redirect($event->redirect, $event->redirect_params, null, $event->redirect_script);
}
}
$this->Application->SetVar('events', $events);
$this->Application->SetVar('passed', implode(',', $all_passed));
}
function processOpener()
{
$wid = $this->Application->GetVar('m_wid');
$opener_stack = $this->Application->RecallVar(rtrim('opener_stack_'.$wid, '_'));
$opener_stack = $opener_stack ? unserialize($opener_stack) : Array();
$opener_action = $this->Application->GetVar('m_opener');
switch ($opener_action) {
case 'r': // "reset" opener stack
$opener_stack = Array();
break;
case 'd': // "down/push" new template to opener stack, deeplevel++
if ($this->Application->GetVar('front')) {
$front_session =& $this->Application->recallObject('Session.front');
array_push($opener_stack, '../'.$front_session->RecallVar('last_template') );
}
else {
array_push($opener_stack, $this->Application->RecallVar('last_template') );
}
break;
case 'u': // "up/pop" last template from opener stack, deeplevel--
array_pop($opener_stack);
break;
case 'p': // pop-up - generate new wid
$parent_wid = $this->Application->GetVar('m_wid'); // window_id of popup's parent window
$popup_wid = (int)$this->Application->RecallVar('last_wid') + 1;
$this->Application->StoreVar('last_wid', $popup_wid);
$this->Application->SetVar('m_wid', $popup_wid);
if ($this->Application->GetVar('front')) {
$front_session =& $this->Application->recallObject('Session.front');
$last_template = $front_session->RecallVar(rtrim('last_template_popup_'.$parent_wid, '_'));
$last_template = '../'.$last_template;
}
else {
$last_template = $this->Application->RecallVar(rtrim('last_template_popup_'.$parent_wid, '_'));
}
$opener_stack = Array ( $last_template );
$this->Application->SetVar('m_opener', 's');
$wid = $popup_wid;
break;
default: // "s/0," stay on same deep level
break;
}
$this->Application->SetVar('m_opener', 's');
$this->Application->StoreVar(rtrim('opener_stack_'.$wid, '_'), serialize($opener_stack));
}
/**
* Used from relationship event handler
*
* @param string $t
* @param Array $params
* @param string $pass
*/
function openerStackPush($t, $params, $pass = 'all', $wid=null)
{
if (!isset($wid)) $wid = $this->Application->GetVar('m_wid');
$stack_name = rtrim('opener_stack_'.$wid, '_');
$opener_stack = $this->Application->RecallVar($stack_name);
$opener_stack = $opener_stack ? unserialize($opener_stack) : Array();
$redirect_params = array_merge_recursive2(Array('m_opener' => 'u', '__URLENCODE__' => 1), $params);
$new_level = $this->Application->BuildEnv($t, $redirect_params, $pass, true);
array_push($opener_stack, 'index.php|'.ltrim($new_level, ENV_VAR_NAME.'=') );
$this->Application->StoreVar($stack_name, serialize($opener_stack));
}
function registerHook($hookto_prefix, $hookto_special, $hookto_event, $mode, $do_prefix, $do_special, $do_event, $conditional)
{
if( !$this->Application->prefixRegistred($hookto_prefix) )
{
if ($this->Application->isDebugMode()) {
trigger_error('Prefix <b>'.$hookto_prefix.'</b> doesn\'t exist when trying to hook from <b>'.$do_prefix.':'.$do_event.'</b>', E_USER_WARNING);
}
return;
}
$hookto_prefix_special = rtrim($hookto_prefix.'.'.$hookto_special, '.');
if ($mode == hBEFORE) {
$this->beforeHooks[strtolower($hookto_prefix_special.'.'.$hookto_event)][] = Array(
'DoPrefix' => $do_prefix,
'DoSpecial' => $do_special,
'DoEvent' => $do_event,
'Conditional' => $conditional,
);
}
elseif ($mode == hAFTER) {
$this->afterHooks[strtolower($hookto_prefix_special.'.'.$hookto_event)][] = Array(
'DoPrefix' => $do_prefix,
'DoSpecial' => $do_special,
'DoEvent' => $do_event,
'Conditional' => $conditional,
);
}
}
/**
* Enter description here...
*
* @param kEvent $event
* @param int $mode hBEFORE or hAFTER
* @return Array
*/
function &getHooks(&$event, $mode, $special = null)
{
$event_key = !isset($special) ? $event->Prefix_Special : $event->Prefix.'.'.$special;
if ($mode == hBEFORE) {
$mode_hooks =& $this->beforeHooks;
}
else {
$mode_hooks =& $this->afterHooks;
}
if (!isset($mode_hooks[strtolower($event_key.'.'.$event->Name)])) {
$hooks = array();
return $hooks;
}
return $mode_hooks[strtolower($event_key.'.'.$event->Name)];
}
/**
* Enter description here...
*
* @param kEvent $event
* @param int $mode hBEFORE or hAFTER
*/
function processHooks(&$event, $mode)
{
// * - get hooks that are valid with any special of given prefix
$hooks = array_merge($this->getHooks($event, $mode, '*'), $this->getHooks($event, $mode));
if ($hooks) {
foreach ($hooks as $hook) {
if ($hook['DoSpecial'] == '*') {
// use same special as master event
$hook['DoSpecial'] = $event->Special;
}
$prefix_special = rtrim($hook['DoPrefix'].'_'.$hook['DoSpecial'], '_');
if ( $hook['Conditional'] && !$this->Application->GetVar($prefix_special) ) {
continue;
}
$hook_event = new kEvent( Array('name'=>$hook['DoEvent'],'prefix'=>$hook['DoPrefix'],'special'=>$hook['DoSpecial']) );
$hook_event->MasterEvent =& $event;
$this->HandleEvent($hook_event);
}
}
}
/**
* Set's new event for $prefix_special
* passed
*
* @param string $prefix_special
* @param string $event_name
* @access public
*/
function setEvent($prefix_special,$event_name)
{
$actions =& $this->Application->recallObject('kActions');
$actions->Set('events['.$prefix_special.']',$event_name);
}
/**
* Run registred regular events with specified event type
*
* @param int $event_type
*/
function RunRegularEvents($event_type = reBEFORE, $from_cron=false)
{
if (defined('IS_INSTALL')) return ;
// if RegularEvents are set to run from cron
if (!$from_cron && $this->Application->ConfigValue('UseCronForRegularEvent')) return ;
$events_source = ($event_type == reBEFORE) ? $this->beforeRegularEvents : $this->afterRegularEvents;
/*if(rand(0, 100) < 90)
{
return;
}*/
$sql = 'SELECT Data
FROM '.TABLE_PREFIX.'Cache
WHERE VarName = "RegularEventRuns"';
$event_last_runs = $this->Conn->GetOne($sql);
$event_last_runs = $event_last_runs ? unserialize($event_last_runs) : Array();
$user_id = $this->Application->RecallVar('user_id');
$this->Application->StoreVar('user_id', -1); // to prevent permission checking inside events
foreach ($events_source as $short_name => $event_data) {
$event_last_run = getArrayValue($event_last_runs, $short_name);
if ($event_last_run && $event_last_run > adodb_mktime() - $event_data['RunInterval']) {
continue;
}
else {
$event = new kEvent($event_data['EventName']);
$event->redirect = false;
$this->Application->HandleEvent($event);
$event_last_runs[$short_name] = adodb_mktime();
}
}
$this->Application->StoreVar('user_id', $user_id);
$fields_hash = Array (
'VarName' => 'RegularEventRuns',
'Data' => serialize($event_last_runs),
'Cached' => adodb_mktime(),
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX.'Cache', 'REPLACE');
}
/**
* Allows to determine, that required event is beeing processed right now
*
* @param string $event_key Event name in format prefix[.special]:event_name
* @return bool
*/
function eventRunning($event_key)
{
return array_search($event_key, $this->recursionStack) !== false;
}
}
?>
\ No newline at end of file
Property changes on: branches/RC/core/kernel/event_manager.php
___________________________________________________________________
Modified: cvs2svn:cvs-rev
## -1 +1 ##
-1.44.18.3
\ No newline at end of property
+1.44.18.4
\ No newline at end of property
Event Timeline
Log In to Comment