Created
October 25, 2011 09:24
-
-
Save phpnode/1312008 to your computer and use it in GitHub Desktop.
Yii based event system with no dependencies
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Eventable { | |
/** | |
* The events attached to this class | |
* @var Event[] | |
*/ | |
protected $_events = array(); | |
/** | |
* Determines whether an event is defined. | |
* An event is defined if the class has a method named like 'onXXX'. | |
* Note, event name is case-insensitive. | |
* @param string $name the event name | |
* @return boolean whether an event is defined | |
*/ | |
public function hasEvent($name) | |
{ | |
return !strncasecmp($name,'on',2) && method_exists($this,$name); | |
} | |
/** | |
* Checks whether the named event has attached handlers. | |
* @param string $name the event name | |
* @return boolean whether an event has been attached one or several handlers | |
*/ | |
public function hasEventHandler($name) | |
{ | |
$name=strtolower($name); | |
return isset($this->_events[$name]) && count($this->_events[$name])>0; | |
} | |
/** | |
* Returns the list of attached event handlers for an event. | |
* @param string $name the event name | |
* @return array list of attached event handlers for the event | |
* @throws Exception if the event is not defined | |
*/ | |
public function getEventHandlers($name) | |
{ | |
if($this->hasEvent($name)) | |
{ | |
$name=strtolower($name); | |
if(!isset($this->_events[$name])) | |
$this->_events[$name]=array(); | |
return $this->_events[$name]; | |
} | |
else | |
throw new Exception('Event "'.get_class($this).'.'.$name.'" is not defined.'); | |
} | |
/** | |
* Attaches an event handler to an event. | |
* | |
* An event handler must be a valid PHP callback, i.e., a string referring to | |
* a global function name, or an array containing two elements with | |
* the first element being an object and the second element a method name | |
* of the object. | |
* | |
* An event handler must be defined with the following signature, | |
* <pre> | |
* function handlerName($event) {} | |
* </pre> | |
* where $event includes parameters associated with the event. | |
* | |
* This is a convenient method of attaching a handler to an event. | |
* It is equivalent to the following code: | |
* <pre> | |
* $component->getEventHandlers($eventName)->add($eventHandler); | |
* </pre> | |
* | |
* Using {@link getEventHandlers}, one can also specify the excution order | |
* of multiple handlers attaching to the same event. For example: | |
* <pre> | |
* $component->getEventHandlers($eventName)->insertAt(0,$eventHandler); | |
* </pre> | |
* makes the handler to be invoked first. | |
* | |
* @param string $name the event name | |
* @param callback $handler the event handler | |
* @throws Exception if the event is not defined | |
* @see detachEventHandler | |
*/ | |
public function attachEventHandler($name,$handler) | |
{ | |
$name=strtolower($name); | |
if(!isset($this->_events[$name])) | |
$this->_events[$name]=array(); | |
$this->_events[$name][] = $handler; | |
} | |
/** | |
* Detaches an existing event handler. | |
* This method is the opposite of {@link attachEventHandler}. | |
* @param string $name event name | |
* @param callback $handler the event handler to be removed | |
* @return boolean if the detachment process is successful | |
* @see attachEventHandler | |
*/ | |
public function detachEventHandler($name,$handler) | |
{ | |
$name = strtolower($name); | |
if($this->hasEventHandler($name)) { | |
foreach($this->_events[$name] as $n => $eventHandler){ | |
if ($handler === $eventHandler) { | |
unset($this->_events[$name][$n]); | |
return true; | |
} | |
} | |
return false; | |
} | |
else | |
return false; | |
} | |
/** | |
* Raises an event. | |
* This method represents the happening of an event. It invokes | |
* all attached handlers for the event. | |
* @param string $name the event name | |
* @param Event $event the event parameter | |
* @throws Exception if the event is undefined or an event handler is invalid. | |
*/ | |
public function raiseEvent($name,$event) | |
{ | |
$name=strtolower($name); | |
if(isset($this->_events[$name])) | |
{ | |
foreach($this->_events[$name] as $handler) | |
{ | |
if(is_string($handler)) | |
call_user_func($handler,$event); | |
else if(is_callable($handler,true)) | |
{ | |
if(is_array($handler)) | |
{ | |
// an array: 0 - object, 1 - method name | |
list($object,$method)=$handler; | |
if(is_string($object)) // static method call | |
call_user_func($handler,$event); | |
else if(method_exists($object,$method)) | |
$object->$method($event); | |
else | |
throw new Exception(strtr('Event "{class}.{event}" is attached with an invalid handler "{handler}".', | |
array('{class}'=>get_class($this), '{event}'=>$name, '{handler}'=>$handler[1]))); | |
} | |
else // PHP 5.3: anonymous function | |
call_user_func($handler,$event); | |
} | |
else | |
throw new Exception(strtr('Event "{class}.{event}" is attached with an invalid handler "{handler}".', | |
array('{class}'=>get_class($this), '{event}'=>$name, '{handler}'=>gettype($handler)))); | |
// stop further handling if param.handled is set true | |
if(($event instanceof Event) && $event->handled) | |
return; | |
} | |
} | |
else if(!$this->hasEvent($name)) | |
throw new Exception(strtr('Event "{class}.{event}" is not defined.', | |
array('{class}'=>get_class($this), '{event}'=>$name))); | |
} | |
} | |
class Event { | |
/** | |
* @var object the sender of this event | |
*/ | |
public $sender; | |
/** | |
* @var boolean whether the event is handled. Defaults to false. | |
* When a handler sets this true, the rest of the uninvoked event handlers will not be invoked anymore. | |
*/ | |
public $handled=false; | |
/** | |
* @var mixed additional event parameters. | |
*/ | |
public $params; | |
/** | |
* Whether the event is valid or not | |
* @var boolean | |
*/ | |
public $isValid = true; | |
/** | |
* Constructor. | |
* @param mixed $sender sender of the event | |
* @param mixed $params additional parameters for the event | |
*/ | |
public function __construct($sender=null,$params=null) | |
{ | |
$this->sender=$sender; | |
$this->params=$params; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment