From 3fdbb2cbfe778fcf48c61bb9fe40d4ac85f8004f Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Thu, 19 Sep 2013 23:07:57 +0200 Subject: Committed TComponent patch by javalizard TComponent Update: Behaviors, Class Behaviors, fx global events, and dy one to one events. This patchset was currently available only on svn trunk/ --- framework/Util/TBehavior.php | 87 ++++++++++++++++++++++ framework/Util/TCallChain.php | 147 ++++++++++++++++++++++++++++++++++++++ framework/Util/TClassBehavior.php | 36 ++++++++++ 3 files changed, 270 insertions(+) create mode 100644 framework/Util/TBehavior.php create mode 100644 framework/Util/TCallChain.php create mode 100644 framework/Util/TClassBehavior.php (limited to 'framework/Util') diff --git a/framework/Util/TBehavior.php b/framework/Util/TBehavior.php new file mode 100644 index 00000000..951a758f --- /dev/null +++ b/framework/Util/TBehavior.php @@ -0,0 +1,87 @@ + + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2009 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * TBehavior is a convenient base class for behavior classes. + * @author Qiang Xue + * @version $Id: TBehaviour.php 3211 2012-10-31 02:35:01Z javalizard@gmail.com $ + * @package System.Util + * @since 3.2.3 + */ +class TBehavior extends TComponent implements IBehavior +{ + private $_enabled; + private $_owner; + + /** + * Declares events and the corresponding event handler methods. + * The events are defined by the {@link owner} component, while the handler + * methods by the behavior class. The handlers will be attached to the corresponding + * events when the behavior is attached to the {@link owner} component; and they + * will be detached from the events when the behavior is detached from the component. + * @return array events (array keys) and the corresponding event handler methods (array values). + */ + public function events() + { + return array(); + } + + /** + * Attaches the behavior object to the component. + * The default implementation will set the {@link owner} property + * and attach event handlers as declared in {@link events}. + * Make sure you call the parent implementation if you override this method. + * @param TComponent the component that this behavior is to be attached to. + */ + public function attach($owner) + { + $this->_owner=$owner; + foreach($this->events() as $event=>$handler) + $owner->attachEventHandler($event,array($this,$handler)); + } + + /** + * Detaches the behavior object from the component. + * The default implementation will unset the {@link owner} property + * and detach event handlers declared in {@link events}. + * Make sure you call the parent implementation if you override this method. + * @param TComponent the component that this behavior is to be detached from. + */ + public function detach($owner) + { + foreach($this->events() as $event=>$handler) + $owner->detachEventHandler($event,array($this,$handler)); + $this->_owner=null; + } + + /** + * @return TComponent the owner component that this behavior is attached to. + */ + public function getOwner() + { + return $this->_owner; + } + + /** + * @return boolean whether this behavior is enabled + */ + public function getEnabled() + { + return $this->_enabled; + } + + /** + * @param boolean whether this behavior is enabled + */ + public function setEnabled($value) + { + $this->_enabled=$value; + } +} \ No newline at end of file diff --git a/framework/Util/TCallChain.php b/framework/Util/TCallChain.php new file mode 100644 index 00000000..9d6144b3 --- /dev/null +++ b/framework/Util/TCallChain.php @@ -0,0 +1,147 @@ + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2008-2013 Pradosoft + * @license http://www.pradosoft.com/license/ + */ + +/** + * TCallChain is a recursive event calling mechanism. This class implements + * the {@link IDynamicMethods} class so that any 'dy' event calls can be caught + * and patched through to the intended recipient + * @author Brad Anderson + * @version $Id: TCallChain.php 564 2009-01-21 22:07:10Z javalizard $ + * @package System.Util + * @since 3.2.3 + */ +class TCallChain extends TList implements IDynamicMethods +{ + /** + * @var {@link TListIterator} for moving through the chained method calls + */ + private $_iterator=null; + + /** + * @var string the method name of the call chain + */ + private $_method=null; + + /** + * This initializes the list and the name of the method to be called + * @param string the name of the function call + */ + public function __construct($method) { + $this->_method=$method; + parent::__construct(); + } + + + /** + * This initializes the list and the name of the method to be called + * @param string|array this is a callable function as a string or array with + * the object and method name as string + * @param array The array of arguments to the function call chain + */ + public function addCall($method,$args) + { + $this->add(array($method,$args)); + } + + /** + * This method calls the next Callable in the list. All of the method arguments + * coming into this method are substituted into the original method argument of + * call in the chain. + * + * If the original method call has these parameters + * + * $originalobject->dyExampleMethod('param1', 'param2', 'param3') + * + * + * $callchain->dyExampleMethod('alt1', 'alt2') + * + * then the next call in the call chain will recieve the parameters as if this were called + * + * $behavior->dyExampleMethod('alt1', 'alt2', 'param3', $callchainobject) + * + * + * When dealing with {@link IClassBehaviors}, the first parameter of the stored argument + * list in 'dy' event calls is always the object containing the behavior. This modifies + * the parameter replacement mechanism slightly to leave the object containing the behavior + * alone and only replacing the other parameters in the argument list. As per {@link __call}, + * any calls to a 'dy' event do not need the object containing the behavior as the addition of + * the object to the argument list as the first element is automatic for IClassBehaviors. + * + * The last parameter of the method parameter list for any callable in the call chain + * will be the TCallChain object itself. This is so that any behavior implementing + * these calls will have access to the call chain. Each callable should either call + * the TCallChain call method internally for direct chaining or call the method being + * chained (in which case the dynamic handler will pass through to this call method). + * + * If the dynamic intra object/behavior event is not called in the behavior implemented + * dynamic method, it will return to this method and call the following behavior + * implementation so as no behavior with an implementation of the dynamic event is left + * uncalled. This does break the call chain though and will not act as a "parameter filter". + * + * When there are no handlers or no handlers left, it returns the first parameter of the + * argument list. + * + */ + public function call() + { + $args=func_get_args(); + if($this->getCount()===0) + return isset($args[0])?$args[0]:null; + + if(!$this->_iterator) + { + $chain_array=array_reverse($this->toArray()); + $this->_iterator=new TListIterator($chain_array); + } + if($this->_iterator->valid()) + do { + $handler=$this->_iterator->current(); + $this->_iterator->next(); + if(is_array($handler[0])&&$handler[0][0] instanceof IClassBehavior) + array_splice($handler[1],1,count($args),$args); + else + array_splice($handler[1],0,count($args),$args); + $handler[1][]=$this; + $result=call_user_func_array($handler[0],$handler[1]); + } while($this->_iterator->valid()); + else + $result = $args[0]; + return $result; + } + + + /** + * This catches all the unpatched dynamic events. When the method call matches the + * call chain method, it passes the arguments to the original __call (of the dynamic + * event being unspecified in TCallChain) and funnels into the method {@link call}, + * so the next dynamic event handler can be called. + * If the original method call has these parameters + * + * $originalobject->dyExampleMethod('param1', 'param2', 'param3') + * + * and within the chained dynamic events, this can be called + * + * class DyBehavior extends TBehavior { + * public function dyExampleMethod($param1, $param2, $param3, $callchain) + * $callchain->dyExampleMethod($param1, $param2, $param3) + * } + * { + * + * to call the next event in the chain. + * @param string method name of the unspecified object method + * @param array arguments to the unspecified object method + */ + public function __dycall($method,$args) + { + if($this->_method==$method) + return call_user_func_array(array($this,'call'),$args); + return null; + } +} \ No newline at end of file diff --git a/framework/Util/TClassBehavior.php b/framework/Util/TClassBehavior.php new file mode 100644 index 00000000..9d29dbf4 --- /dev/null +++ b/framework/Util/TClassBehavior.php @@ -0,0 +1,36 @@ + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2008-2011 Pradosoft + * @license http://www.pradosoft.com/license/ + */ + +/** + * TClassBehavior is a convenient base class for whole class behaviors. + * @author Brad Anderson + * @version $Id: TClassBehavior.php 564 2009-01-21 22:07:10Z javalizard $ + * @package System.Util + * @since 3.2.3 + */ +class TClassBehavior extends TComponent implements IClassBehavior +{ + + /** + * Attaches the behavior object to the component. + * @param TComponent the component that this behavior is to be attached to. + */ + public function attach($component) + { + } + + /** + * Detaches the behavior object from the component. + * @param TComponent the component that this behavior is to be detached from. + */ + public function detach($component) + { + } +} \ No newline at end of file -- cgit v1.2.3