Hooks = $this->Application->makeClass('kHookManager');
$this->ScheduledTasks = $this->Application->makeClass('kScheduledTaskManager');
$this->Request = $this->Application->makeClass('kRequestManager');
}
/**
* Sets data from cache to object
*
* @param Array $data
* @access public
*/
public function setFromCache(&$data)
{
$this->Hooks->setFromCache($data);
$this->ScheduledTasks->setFromCache($data);
$this->buildEvents = $data['EventManager.buildEvents'];
}
/**
* Gets object data for caching
*
* @return Array
* @access public
*/
public function getToCache()
{
return array_merge(
$this->Hooks->getToCache(),
$this->ScheduledTasks->getToCache(),
Array (
'EventManager.buildEvents' => $this->buildEvents,
)
);
}
/**
* Returns information about registered scheduled tasks
*
* @param bool $from_cache
* @return Array
* @access public
*/
public function getScheduledTasks($from_cache = false)
{
return $this->ScheduledTasks->getAll($from_cache);
}
/**
* Add new scheduled task
*
* @param string $short_name name to be used to store last maintenance run info
* @param string $event_string
* @param int $run_schedule run schedule like for Cron
* @param string $module
* @param int $status
* @access public
*/
public function registerScheduledTask($short_name, $event_string, $run_schedule, $module, $status = STATUS_ACTIVE)
{
$this->ScheduledTasks->add($short_name, $event_string, $run_schedule, $module, $status);
}
/**
* Run registered scheduled tasks with specified event type
*
* @param bool $from_cron
* @access public
*/
public function runScheduledTasks($from_cron = false)
{
$this->ScheduledTasks->runAll($from_cron);
}
/**
* Runs scheduled task based on given data
*
* @param Array $scheduled_task_data
* @return bool
* @access public
*/
public function runScheduledTask($scheduled_task_data)
{
return $this->ScheduledTasks->run($scheduled_task_data);
}
/**
* Registers Hook from sub-prefix event to master prefix event
*
* Pattern: Observer
*
* @param string $hook_event
* @param string $do_event
* @param int $mode
* @param bool $conditional
* @access public
*/
public function registerHook($hook_event, $do_event, $mode = hAFTER, $conditional = false)
{
$this->Hooks->registerHook($hook_event, $do_event, $mode, $conditional);
}
/**
* Registers build event for given pseudo class
*
* @param string $pseudo_class
* @param string $event_name
* @access public
*/
public function registerBuildEvent($pseudo_class, $event_name)
{
$this->buildEvents[$pseudo_class] = $event_name;
}
/**
* Runs build event for given $pseudo_class instance, when defined
*
* @param string $prefix_special
* @param string $pseudo_class
* @param Array $event_params
* @access public
*/
public function runBuildEvent($prefix_special, $pseudo_class, $event_params)
{
if ( !isset($this->buildEvents[$pseudo_class]) ) {
return ;
}
$event = new kEvent($prefix_special . ':' . $this->buildEvents[$pseudo_class], $event_params);
$this->HandleEvent($event);
}
/**
* Check if event is called twice, that causes recursion
*
* @param kEvent $event
* @return bool
* @access protected
*/
protected function isRecursion($event)
{
$event_key = $event->getPrefixSpecial() . ':' . $event->Name;
return in_array($event_key, $this->recursionStack);
}
/**
* Adds event to recursion stack
*
* @param kEvent $event
* @access protected
*/
protected function pushEvent($event)
{
$event_key = $event->getPrefixSpecial() . ':' . $event->Name;
array_push($this->recursionStack, $event_key);
}
/**
* Removes event from recursion stack
*
* @access protected
*/
protected function popEvent()
{
array_pop($this->recursionStack);
}
/**
* Allows to process any type of event
*
* @param kEvent $event
* @return void
* @access public
*/
public function HandleEvent($event)
{
if ( $this->isRecursion($event) || !$this->verifyEventPrefix($event) ) {
return;
}
$this->pushEvent($event);
if ( !$event->SkipBeforeHooks ) {
$this->Hooks->runHooks($event, hBEFORE);
if ( $event->status == kEvent::erFATAL ) {
return;
}
}
/** @var kEventHandler $event_handler */
$event_handler = $this->Application->recallObject($event->Prefix . '_EventHandler');
$event_handler->processEvent($event);
if ( $event->status == kEvent::erFATAL ) {
return;
}
if ( !$event->SkipAfterHooks ) {
$this->Hooks->runHooks($event, hAFTER);
}
$this->popEvent();
}
/**
* Notifies event subscribers, that event has occured
*
* @param kEvent $event
* @return void
*/
public function notifySubscribers(kEvent $event)
{
if ( $event->status != kEvent::erSUCCESS ) {
return;
}
$cache_key = 'email_to_event_mapping[%EmailTemplateSerial%]';
$event_mapping = $this->Application->getCache($cache_key);
if ( $event_mapping === false ) {
$this->Conn->nextQueryCachable = true;
$sql = 'SELECT TemplateId, TemplateName, Type, BindToSystemEvent
FROM ' . $this->Application->getUnitConfig('email-template')->getTableName() . '
WHERE BindToSystemEvent <> ""';
$event_mapping = $this->Conn->Query($sql, 'BindToSystemEvent');
$this->Application->setCache($cache_key, $event_mapping);
}
$email_template = Array ();
if ( isset($event_mapping[(string)$event]) ) {
$email_template = $event_mapping[(string)$event];
}
elseif ( isset($event_mapping[$event->Prefix . '.*:' . $event->Name]) ) {
$email_template = $event_mapping[$event->Prefix . '.*:' . $event->Name];
}
if ( !$email_template ) {
return;
}
$where_clause = Array ();
$where_clause['EmailTemplateId'] = 'EmailTemplateId = ' . $email_template['TemplateId'];
try {
$category_ids = Array ();
/** @var kDBItem $category */
$category = $this->Application->recallObject('c');
if ( $category->isLoaded() ) {
$category_ids = explode('|', substr($category->GetDBField('ParentPath'), 1, -1));
}
}
catch (Exception $e) {
}
$where_clause['CategoryId'] = $this->_getSubscriberFilter('CategoryId', $category_ids, true);
try {
$item_id = $parent_item_id = false;
/** @var kDBItem $object */
$object = $event->getObject();
if ( $object->isLoaded() ) {
$item_id = $object->GetID();
$parent_prefix = $event->getUnitConfig()->getParentPrefix();
if ( $parent_prefix ) {
$parent_item_id = $object->getParentId($parent_prefix);
}
}
}
catch (Exception $e) {
}
$where_clause['ItemId'] = $this->_getSubscriberFilter('ItemId', $item_id);
$where_clause['ParentItemId'] = $this->_getSubscriberFilter('ParentItemId', $parent_item_id);
$event_params = Array (
'EmailTemplateId' => $email_template['TemplateId'],
'CategoryIds' => $category_ids,
'ItemId' => $item_id,
'ParentId' => $parent_item_id,
'where_clause' => $where_clause,
);
$sql_event = new kEvent($event->getPrefixSpecial() . ':OnGetEventSubscribersQuery', $event_params);
$sql_event->MasterEvent = $event;
$this->HandleEvent($sql_event);
$subscribers = $this->Conn->GetIterator($sql_event->getEventParam('sql'));
if ( !count($subscribers) ) {
// mapping exists, but nobody has subscribed
return;
}
$send_params = Array (
'Prefix' => $event->Prefix,
'Special' => $event->Special,
'PrefixSpecial' => $event->getPrefixSpecial(),
);
$send_method = $email_template['Type'] == EmailTemplate::TEMPLATE_TYPE_FRONTEND ? 'emailUser' : 'emailAdmin';
foreach ($subscribers as $subscriber_info) {
$send_params['to_name'] = $subscriber_info['SubscriberEmail'];
$send_params['to_email'] = $subscriber_info['SubscriberEmail'];
$this->Application->$send_method($email_template['TemplateName'], $subscriber_info['UserId'], $send_params);
}
}
/**
* Returns filter for searching event subscribers
*
* @param string $field
* @param mixed $value
* @param bool $is_category
* @return string
* @access protected
*/
protected function _getSubscriberFilter($field, $value, $is_category = false)
{
if ( $value ) {
// send to this item subscribers AND to subscribers to all items
if ( $is_category ) {
$clause = 'IF(IncludeSublevels = 1, ' . $field . ' IN (' . implode(',', $value) . '), ' . $field . ' = ' . end($value) . ')';
}
else {
$clause = $field . ' = ' . $this->Conn->qstr($value);
}
return $clause . ' OR ' . $field . ' IS NULL';
}
// send to subscribers to all items
return $field . ' IS NULL';
}
/**
* Checks, that given event is implemented
*
* @param kEvent $event
* @return bool
* @access public
*/
public function eventImplemented(kEvent $event)
{
if ( !$this->verifyEventPrefix($event, true) ) {
return false;
}
/** @var kEventHandler $event_handler */
$event_handler = $this->Application->recallObject($event->Prefix . '_EventHandler');
return $event_handler->getEventMethod($event) != '';
}
/**
* Checks if event prefix is valid
*
* @param kEvent $event
* @param bool $is_fatal
* @return string
* @access public
*/
public function verifyEventPrefix($event, $is_fatal = false)
{
if ( !$this->Application->prefixRegistred($event->Prefix) ) {
// when "l-cdata" is requested, then load "l", that will clone "l-cdata" unit config
$this->Application->UnitConfigReader->loadConfig($event->Prefix);
if ( !$this->Application->prefixRegistred($event->Prefix) ) {
$error_msg = 'Prefix "' . $event->Prefix . '" not registred (requested event "' . $event->Name . '")';
if ($is_fatal) {
throw new Exception($error_msg);
}
else {
trigger_error($error_msg, E_USER_WARNING);
}
return false;
}
}
return true;
}
/**
* Processes request
*
* @access public
*/
public function ProcessRequest()
{
$this->Request->process();
}
/**
* Allows to add new element to opener stack
*
* @param string $template
* @param Array $params
* @access public
*/
public function openerStackPush($template = '', $params = Array ())
{
$this->Request->openerStackPush($template, $params);
}
/**
* Set's new event for $prefix_special
* passed
*
* @param string $prefix_special
* @param string $event_name
* @access public
*/
public function setEvent($prefix_special,$event_name)
{
/** @var Params $actions */
$actions = $this->Application->recallObject('kActions');
$actions->Set('events[' . $prefix_special . ']', $event_name);
}
/**
* 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
* @access public
*/
public function eventRunning($event_key)
{
return array_search($event_key, $this->recursionStack) !== false;
}
}