_chain = $chain;
}
public function __call($name, $args)
{
$this->_isMethod = true;
$this->_name = $name;
$this->_arguments = $args;
$this->_chain[] = $this;
return new ChainCollectorNode($this->_chain);
}
public function __get($name)
{
$this->_isMethod = false;
$this->_name = $name;
$this->_chain[] = $this;
return new ChainCollectorNode($this->_chain);
}
public function finish()
{
return ChainRunner::getInstance()->runChain($this->_chain);
}
/**
* Returns the chain as an array of ChainCollectorNodes
*
* @return Array
*/
public function getChain()
{
return $this->_chain;
}
public function getName()
{
return $this->_name;
}
public function getArguments()
{
return $this->_arguments;
}
public function isMethodCall()
{
return $this->_isMethod;
}
public function isPropertyGet()
{
return !$this->_isMethod;
}
}
class ChainCollectorStartNode extends ChainCollectorNode
{
private $_className;
public function __construct($className)
{
parent::__construct();
$this->_className = $className;
}
public function getClassName()
{
return $this->_className;
}
}
class ChainRunner
{
private $_specialCalls = array();
private static $_instance;
private function __construct()
{
// $this->_specialCalls['if'] = new IfChainParser();
}
/**
* Return a ChainRunner instance
*
* @return ChainRunner
*/
public static function getInstance()
{
if(!self::$_instance)
self::$_instance = new ChainRunner();
return self::$_instance;
}
/**
* Runs a chain
* @param Array $chain Array of chaincollectornodes
* @return Mixed result
*/
public function runChain($chain)
{
$firstClass = $chain[0]->getClassName();
$node = array_shift($chain);
$obj = new $firstClass();
$index = 0;
while($node != null)
{
if($node->isMethodCall())
{
$methodName = $node->getName();
$arguments = $node->getArguments();
if($this->_isSpecial($methodName))
{
$this->_specialCalls[$methodName]->setChain($chain)
->parseIndex($index, $arguments);
}
else
{
//echo "Mtd ".get_class($obj)." $methodName
";
$obj = call_user_func_array(array($obj,$methodName),$arguments);
}
}
else
{
$propertyName = $node->getName();
//echo "Prop ".get_class($obj)." $propertyName
";
$obj = $obj->$propertyName;
}
$node = array_shift($chain);
$index++;
}
//echo "Returning ".get_class($obj)."
";
return $obj;
}
private function _isSpecial($name)
{
return array_key_exists($name, $this->_specialCalls);
}
}