/home/edulekha/studygroup.edulekha.com/ow_core/event_manager.php
<?php
/**
* EXHIBIT A. Common Public Attribution License Version 1.0
* The contents of this file are subject to the Common Public Attribution License Version 1.0 (the “License”);
* you may not use this file except in compliance with the License. You may obtain a copy of the License at
* http://www.oxwall.org/license. The License is based on the Mozilla Public License Version 1.1
* but Sections 14 and 15 have been added to cover use of software over a computer network and provide for
* limited attribution for the Original Developer. In addition, Exhibit A has been modified to be consistent
* with Exhibit B. Software distributed under the License is distributed on an “AS IS” basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language
* governing rights and limitations under the License. The Original Code is Oxwall software.
* The Initial Developer of the Original Code is Oxwall Foundation (http://www.oxwall.org/foundation).
* All portions of the code written by Oxwall Foundation are Copyright (c) 2011. All Rights Reserved.
* EXHIBIT B. Attribution Information
* Attribution Copyright Notice: Copyright 2011 Oxwall Foundation. All rights reserved.
* Attribution Phrase (not exceeding 10 words): Powered by Oxwall community software
* Attribution URL: http://www.oxwall.org/
* Graphic Image as provided in the Covered Code.
* Display of Attribution Information is required in Larger Works which are defined in the CPAL as a work
* which combines Covered Code or portions thereof with code not governed by the terms of the CPAL.
*/
/**
* The class provides access to event system of framework.
* Works as simple as it can be - plugins add PHP listeners (callbacks) to manager stack.
* When event triggered the whole stack is called.
*
* @author Sardar Madumarov <madumarov@gmail.com>
* @package ow_core
* @since 1.0
*/
class OW_EventManager
{
/* list of predefined system events: application lifecycle */
const ON_APPLICATION_INIT = 'core.app_init';
const ON_PLUGINS_INIT = 'core.plugins_init';
const ON_AFTER_ROUTE = 'core.after_route';
const ON_AFTER_REQUEST_HANDLE = 'core.after_dispatch';
const ON_BEFORE_DOCUMENT_RENDER = 'core.before_document_render';
const ON_AFTER_DOCUMENT_RENDER = 'core.document_render';
const ON_FINALIZE = 'core.finalize';
const ON_AFTER_PLUGIN_INSTALL = 'core.plugin_install';
const ON_BEFORE_PLUGIN_UNINSTALL = 'core.plugin_uninstall';
const ON_AFTER_PLUGIN_UNINSTALL = 'core.after_plugin_uninstall';
const ON_AFTER_PLUGIN_ACTIVATE = 'core.plugin_activate';
const ON_BEFORE_PLUGIN_DEACTIVATE = 'core.plugin_deactivate';
const ON_AFTER_PLUGIN_DEACTIVATE = 'core.after_plugin_deactivate';
const ON_AFTER_PLUGIN_UPDATE = "core.plugin_update";
const ON_CLI_RUN = 'cli.run';
/* list of predefined system events: general events */
const ON_BEFORE_USER_REGISTER = 'base.before_user_register';
const ON_BEFORE_USER_LOGIN = 'base.before_user_login';
const ON_USER_REGISTER = 'base.user_register';
const ON_USER_UNREGISTER = 'base.user_unregister';
const ON_USER_LOGIN = 'base.user_login';
const ON_USER_LOGOUT = 'base.user_logout';
const ON_USER_SUSPEND = 'base.user_suspend';
const ON_USER_UNSUSPEND = 'base.user_unsuspend';
const ON_USER_EDIT = 'base.user_edit';
const ON_USER_EDIT_BY_ADMIN = 'base.user_edit_by_admin';
const ON_JOIN_FORM_RENDER = 'base.join_form_render';
const ON_USER_BLOCK = 'base.on_user_block';
const ON_USER_UNBLOCK = 'base.on_user_unblock';
const ON_USER_APPROVE = 'base.on_user_approve';
const ON_USER_DISAPPROVE = 'base.on_user_disapprove';
const ON_USER_MARK_FEATURED = 'base.on_user_mark_featured';
const ON_USER_UNMARK_FEATURED = 'base.on_user_unmark_featured';
const ON_BEFORE_USER_COMPLETE_PROFILE = 'base.on_before_user_complete_profile';
const ON_AFTER_USER_COMPLETE_PROFILE = 'base.on_after_user_complete_profile';
const ON_BEFORE_USER_COMPLETE_ACCOUNT_TYPE = 'base.on_before_user_complete_account_type';
/**
* @var array
*/
private $eventsToSkip = array(
"core.get_text",
"core.get_storage",
"class.get_instance",
"base.before_decorator",
"core.sql.get_query_result",
"core.sql.set_query_result",
"core.sql.exec_query",
"core.performance_test"
);
/**
* @var int
*/
private $maxItemsInLog = 200;
/**
* @var boolean
*/
private $devMode = false;
/**
* @var array
*/
private $eventsLog = array();
/**
* @var UTIL_Profiler
*/
private $profiler;
/**
* List of binded listeners.
*
* @var array
*/
private $listeners = array();
/**
* Constructor.
*/
private function __construct()
{
$this->profiler = UTIL_Profiler::getInstance('event_manager');
}
/**
* Singleton instance.
*
* @var OW_EventManager
*/
private static $classInstance;
/**
* Returns an instance of class (singleton pattern implementation).
*
* @return OW_EventManager
*/
public static function getInstance()
{
if ( self::$classInstance === null )
{
self::$classInstance = new self();
}
return self::$classInstance;
}
/**
* Binds listener to event.
* Callback should be valid `PHP callback`.
*
* @param string $name
* @param callback $listener
* @param null $priority
*/
public function bind( $name, $listener, $priority = null )
{
$priority = ($priority === null) ? 1000 : (int) $priority;
if ( !isset($this->listeners[$name][$priority]) )
{
$this->listeners[$name][$priority] = array();
}
$this->listeners[$name][$priority][] = $listener;
}
/**
* Unbinds listener from event.
* Callback should be valid `PHP callback`.
*
* @param string $name
* @param callback $listener
*/
public function unbind( $name, $listener )
{
foreach ( $this->listeners[$name] as $priority => $data )
{
foreach ( $data as $key => $handler )
{
if ( $handler == $listener )
{
unset($this->listeners[$name][$priority][$key]);
return;
}
}
}
}
/**
* Triggers event listeners.
*
* @param OW_Event $event
* @return OW_Event
*/
public function trigger( OW_Event $event )
{
if ( isset($this->listeners[$event->getName()]) && !empty($this->listeners[$event->getName()]) )
{
ksort($this->listeners[$event->getName()]);
// log triggered events for developer mode
if ( $this->devMode )
{
$startTime = UTIL_Profiler::getInstance()->getTotalTime();
$this->profiler->reset();
foreach ( $this->listeners[$event->getName()] as $priority => $data )
{
foreach ( $data as $listener )
{
if ( call_user_func($listener, $event) === false || $event->isStopped() )
{
break 2;
}
}
}
if ( !in_array($event->getName(), $this->eventsToSkip) && count($this->eventsLog) < $this->maxItemsInLog )
{
$this->eventsLog[] = array('type' => 'trigger', 'start' => $startTime, 'exec' => $this->profiler->getTotalTime(),
'event' => $event, 'listeners' => $this->listeners[$event->getName()]);
}
}
else
{
foreach ( $this->listeners[$event->getName()] as $priority => $data )
{
foreach ( $data as $listener )
{
if ( call_user_func($listener, $event) === false || $event->isStopped() )
{
break 2;
}
}
}
}
}
else
{
// log events with no listeners
$startTime = UTIL_Profiler::getInstance()->getTotalTime();
if ( $this->devMode && !in_array($event->getName(), $this->eventsToSkip) && count($this->eventsLog) < $this->maxItemsInLog )
{
$this->eventsLog[] = array('type' => 'trigger', 'start' => $startTime, 'event' => $event, 'listeners' => array(),
'exec' => 0);
}
}
return $event;
}
/**
* Calls last event listener and returns it's result value.
*
* @param string $eventName
* @param array $eventParams
* @return mixed
*/
public function call( $eventName, $eventParams = array() )
{
$event = new OW_Event($eventName, $eventParams);
if ( !empty($this->listeners[$eventName]) )
{
ksort($this->listeners[$event->getName()]);
// log triggered events for developer mode
if ( $this->devMode )
{
$startTime = UTIL_Profiler::getInstance()->getTotalTime();
$this->profiler->reset();
$handlers = reset($this->listeners[$eventName]);
$result = call_user_func(end($handlers), $event);
if ( !in_array($event->getName(), $this->eventsToSkip) && count($this->eventsLog) < $this->maxItemsInLog )
{
$this->eventsLog[] = array('type' => 'call', 'start' => $startTime, 'exec' => $this->profiler->getTotalTime(),
'event' => $event, 'listeners' => $this->listeners[$event->getName()]);
}
}
else
{
$handlers = reset($this->listeners[$eventName]);
$result = call_user_func(end($handlers), $event);
}
return $result;
}
else
{
// log events with no listeners
$startTime = UTIL_Profiler::getInstance()->getTotalTime();
if ( $this->devMode && !in_array($event->getName(), $this->eventsToSkip) && count($this->eventsLog) < $this->maxItemsInLog )
{
$this->eventsLog[] = array('type' => 'call', 'start' => $startTime, 'event' => $event, 'listeners' => array(),
'exec' => 0);
}
}
}
/**
* @param boolean $devMode
*/
public function setDevMode( $devMode )
{
$this->devMode = (bool) $devMode;
}
/**
* @return array
*/
public function getLog()
{
return array('bind' => $this->listeners, 'call' => $this->eventsLog);
}
}