diff options
author | javalizard@gmail.com <> | 2012-10-31 02:35:01 +0000 |
---|---|---|
committer | javalizard@gmail.com <> | 2012-10-31 02:35:01 +0000 |
commit | 9ed8e2fff531f9188dc55a99e3006f94edc59a5e (patch) | |
tree | 8218e8929c49a550c4031705b748760e469df735 /framework/Util/TCallChain.php | |
parent | cd88852b2f67529a9071622988d7c4a76429a670 (diff) |
MAJOR UPGRADE to TComponent
This adds global 'fx' events, behaviors, class-wide behaviors, intra-object/behavior 'dy' events, and tweaks the raiseEvent to be more advanced (yet backward compatible). A large amount of documentation is in here too. Slight changes to the TApplication object is made to provide events with priorities. TComponent has a massive amount of test cases as well… There are now 512 assertions. Test cases have been added for testing the GetJS and SetJS and ensure functionality of these new getters and setters.
The Behaviors are all tested and fully integrated into the TComponent Object. Behaviors are more transparently and widely integrated into TComponent.
Class Behaviors rely on the global events to add behaviors to instanced objects. Class behaviors also allow for behaviors to be added during the instancing of new objects of the class.
Dynamic events enable the object to send events directly to behaviors as intra-object events. Dynamic events can be chained as multiple behaviors may implement the event. This allows for parameter filtering.
RaiseEvent allows for raising global events, capturing results, and feeding results forward into the next handlers parameters should the need arise. This is a forward thinking feature to enable new processes to be designed into the code for PRADO version 3.3 and future version 4.0. This functionality is transparent when unused.
We are hoping this is fully backward compatible with the existing code base. It was designed for maximum backward compatibility while expanding the functional base exponentially.
This clears the way for a new way of thinking about how objects relate.
Diffstat (limited to 'framework/Util/TCallChain.php')
-rw-r--r-- | framework/Util/TCallChain.php | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/framework/Util/TCallChain.php b/framework/Util/TCallChain.php new file mode 100644 index 00000000..ae6e02fc --- /dev/null +++ b/framework/Util/TCallChain.php @@ -0,0 +1,147 @@ +<?php +/** + * TCallChain class file. + * + * @author Brad Anderson <javalizard@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2008-2011 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 <javalizard@gmail.com> + * @version $Id: TCallChain.php 564 2009-01-21 22:07:10Z javalizard $ + * @package system.base + * @since 3.2 + */ +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 + * <code> + * $originalobject->dyExampleMethod('param1', 'param2', 'param3') + * </code> + * <code> + * $callchain->dyExampleMethod('alt1', 'alt2') + * </code> + * then the next call in the call chain will recieve the parameters as if this were called + * <code> + * $behavior->dyExampleMethod('alt1', 'alt2', 'param3', $callchainobject) + * </code> + * + * 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 + * <code> + * $originalobject->dyExampleMethod('param1', 'param2', 'param3') + * </code> + * and within the chained dynamic events, this can be called + * <code> + * class DyBehavior extends TBehavior { + * public function dyExampleMethod($param1, $param2, $param3, $callchain) + * $callchain->dyExampleMethod($param1, $param2, $param3) + * } + * { + * </code> + * 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 |