<?php
class Exception_Event extends Exception {}
class Event extends stdClass{
public $target=null;
public $type=null;
public function __construct($type){
$this->type=trim($type);
}
public function __toString(){
return $this->type;
}
}
class EventDispatcher{
private $_callback_method;
public function attach(Event $event,$method,$class=null){
$event->target=$this;
$eventstr=$this->_create_event_str($event);
if($this->has($event,$method,$class))
return true;
if($class!=null){
$this->_check_method($class,$method);
$this->_callback_method[$eventstr][]=$this->_create_listener_method($eventstr,$class,$method);
}else{
$this->_check_function($method);
$this->_callback_method[$eventstr][]=$this->_create_listener_fn($eventstr,$method);
}
return true;
}
public function dispatch(Event $event){
$eventstr=$this->_create_event_str($event);
if($this->_check_callback($eventstr)){
foreach ($this->_callback_method[$eventstr] as $v){
if($v['object']){
if(is_object($v['class'])){
$v['class']->$v['method']($event);
}else{
call_user_func(array($v['class'], $v['method']),$event);
}
}else{
$v['function']($event);
}
}
}
}
public function detact(Event $event,$method,$class=null){
$eventstr=$this->_create_event_str($event);
if(!$this->_check_callback($eventstr))
return true;
if(!$this->has($event,$method,$class))
return true;
if($class!=null){
$this->_check_method($class,$method);
foreach ($this->_callback_method[$eventstr] as $k=>$v) {
if(($v==$this->_create_listener_method($eventstr,$class,$method))){
unset($this->_callback_method[$eventstr][$k]);
return true;
}
}
return true;
}else{
$this->_check_function($method);
foreach ($this->_callback_method[$eventstr] as $k=>$v) {
if(($v==$this->_create_listener_fn($eventstr,$method))){
unset($this->_callback_method[$eventstr][$k]);
return true;
}
}
return true;
}
}
public function has(Event $event,$method,$class=null){
$eventstr=$this->_create_event_str($event);
if(($class!=null)){
$this->_check_method($class,$method);
if($this->_check_callback($eventstr)){
foreach($this->_callback_method[$eventstr] as $v){
if(is_object($v['class'])){
$v_class=get_class($v['class']);
}else{
$v_class=$v['class'];
}
if(is_object($class)){
$s_class=get_class($class);
}else{
$s_class=$class;
}
$temp_v=array(
"class"=>$v_class,
"method"=>$method,
);
$temp_s=array(
"class"=>$s_class,
"method"=>$method,
);
if($temp_v==$temp_s){
return true;
}
}
}
}else{
$this->_check_function($method);
if($this->_check_callback($eventstr)){
foreach($this->_callback_method[$eventstr] as $v){
if($method==$v['function']){
return true;
}
}
}
}
return false;
}
private function _check_method($class,$method){
if(!method_exists($class,$method)){
throw new Exception_Event(get_class($class)." not exist ".$method." method",1);
}
}
private function _check_function($function){
if(!function_exists($function)){
throw new Exception_Event($function." function not exist ",2);
}
}
private function _check_callback($eventstr){
if(isset($this->_callback_method[$eventstr])
&&is_array($this->_callback_method[$eventstr])
){
return true;
}
return false;
}
private function _create_listener_fn($eventstr,$function){
return array(
"object"=>false,
"function"=>$function,
);
}
private function _create_listener_method($eventstr,$class,$method){
return array(
"object"=>true,
"class"=>$class,
"method"=>$method,
);
}
private function _create_event_str(Event $event){
$classstr=strtolower(get_class($event));
$eventstr=(string)$event;
return $classstr.$eventstr;
}
}
class test extends EventDispatcher{
}
function t($e){
print_r($e->a);
}
$v=new test();
$e=new Event("test");
$v->attach($e,"t");
$v->detact($e,"t");
echo $v->has($e,"t");
$e->a="dd";
$v->dispatch($e);