/** * 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; }