Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- abstract class Component extends stdCLass implements ArrayAccess, Countable
- {
- protected $Decorators = array();
- protected $Water = 0;
- protected $SharedProps = 0;
- public function GetProperties(Component $Child)
- {
- foreach($this as $k => $v)
- {
- $Child->{$k} = &$this->{$k};
- }
- if(!isset($this->datahash))
- {
- $Child->base = &$this;
- $Child->datahash = spl_object_hash($this);
- }
- }
- public function AddDecorator($func, $args = array())
- {
- if(is_callable($func))
- {
- array_push($this->Decorators, array($func, $args));
- }
- else
- {
- throw new InvalidArgumentException(sprintf('%s::AddDecorator(callable $func, array $args): Invalid function ( %s ).', get_class($this), var_export($func, true)));
- }
- }
- public function RemoveDecorator($func, $args = array())
- {
- foreach($this->Decorators as & $decorator)
- {
- if($decorator === array($func, $args))
- {
- unset($decorator);
- return true;
- }
- }
- return false;
- }
- public function Decorate()
- {
- foreach($this->Decorators as $call)
- {
- call_user_func_array($call[0], $call[1]);
- }
- }
- public function __call($Key, $Params)
- {
- $prev = debug_backtrace();
- $Key = (string)$Key;
- $base = isset($this->base)
- ? $this->base
- : $this
- ;
- if(!isset($this->{$Key}) && !isset($base->{$Key}))
- {
- throw new BadMethodCallException(sprintf('Call to undefined method `%s::%s()`', get_class($this), $Key));
- return;
- }
- if(is_callable($this->{$Key}))
- {
- return call_user_func_array($this->{$Key}, $Params);
- }
- elseif(is_callable($base->{$Key}))
- {
- return call_user_func_array($base->{$Key}, $Params);
- }
- else
- {
- throw new BadMethodCallException(sprintf('Call to undefined method `%s::{%s}()`.', get_class($this), var_export($this->{$Key}, true)));
- return;
- }
- }
- private function getHash()
- {
- return isset($this->datahash)
- ? $this->datahash
- : $this->datahash = spl_object_hash($this)
- ;
- }
- public function offsetSet($offset, $value)
- {
- static $count = 0;
- $hash = $this->getHash();
- if (is_null($offset))
- {
- $this->{$hash.$count++} = $value;
- $this->SharedProps++;
- }
- else
- {
- if(!isset($this[$offset])) $this->SharedProps++;
- $this->{$hash.$offset} = $value;
- }
- }
- public function offsetExists($offset)
- {
- return isset($this->{$this->getHash().$offset});
- }
- public function offsetUnset($offset)
- {
- $hash = $this->getHash();
- if(isset($this->{$hash.$offset})) $this->SharedProps--;
- unset($this->{$hash.$offset});
- }
- public function &offsetGet($offset)
- {
- return $this->{$this->getHash().$offset};
- }
- public function count()
- {
- return count($this->SharedProps);
- }
- protected function nop(){;}
- public function SetFunction($name, $func = 'nop')
- {
- $base = isset($this->base)
- ? $this->base
- : $this
- ;
- $old = isset($base->{$name})
- ? $base->{$name}
- : NULL
- ;
- if(!is_callable(array($this, $func)))
- {
- var_dump($this, $func);
- throw new InvalidArgumentException(sprintf('%s::SetFunction(): Undefined method `%s`', get_class($this), var_export($func, true)));
- }
- $this->{$name} = $base->{$name} = array($this, $func);
- return $old;
- }
- // Note Uses shared version of water and can cause notices
- function PourWater()
- {
- printf('Adding Water: %d%s', $this['Water'], "\n");
- }
- }
- abstract class Decorator extends Component
- {
- public function __construct(Component $Parent)
- {
- $this->parent = &$Parent;
- $Parent->GetProperties($this);
- }
- public function __call($Key, $Params)
- {
- $prev = debug_backtrace();
- $prev = $prev[0]['class'];
- if($prev == __CLASS__)
- {
- if(!is_callable(array($this->parent, $Key)))
- {
- throw new BadMethodCallException(sprintf('Call to undefined method `%s::%s()`', get_class($this), $Key));
- return;
- }
- return call_user_func_array(array($this->parent, $Key), $Params);
- }
- parent::__call($Key, $Params);
- }
- }
- class SimpleCofee extends Component
- {
- protected $Name = 'Cofee';
- protected $Cup = array();
- public function __construct($Parent = NULL)
- {
- $this->Water = 150;
- $this->Cup['cofeee'] = 25;
- if($Parent instanceof Component)
- {
- $Parent->GetProperties($this);
- }
- else
- {
- $this['Name'] = $this->Name;
- $this['Water'] = $this->Water;
- $this['Cup'] = $this->Cup;
- }
- $this->SetFunction('Produce', 'doProduce');
- $this->SetFunction('SuperChain', 'doSuperChain');
- }
- public function doProduce()
- {
- printf("Making %s....\n", $this->Name);
- $this->Decorate();
- //.....
- $this->PourWater();
- //......
- printf("Making %s: %s\n", $this['Name'], var_export($this['Cup'], true));
- }
- public function doSuperChain()
- {
- print __CLASS__.'::SuperChain('.var_export(func_get_args(), true).")\n";
- }
- }
- class SimpleTea extends SimpleCofee
- {
- protected $Name = 'Tea';
- public function __construct($Parent = NULL)
- {
- $this->Water = 150;
- $this->Cup['tea'] = 25;
- if($Parent instanceof Component)
- {
- $Parent->GetProperties($this);
- }
- else
- {
- $this['Name'] = $this->Name;
- $this['Water'] = $this->Water;
- $this['Cup'] = $this->Cup;
- }
- $this->SetFunction('Produce', 'doProduce');
- $this->SetFunction('SuperChain', 'doSuperChain');
- }
- public function doSuperChain()
- {
- print __CLASS__.'::SuperChain('.var_export(func_get_args(), true).")\n";
- parent::doSuperChain(__CLASS__);
- }
- }
- class SugarCube extends Decorator
- {
- public function __construct(Component $Parent)
- {
- parent::__construct($Parent);
- $Parent->AddDecorator(array($this, 'AddSugar'));
- $this->SetFunction('SuperChain', 'doSuperChain');
- }
- public function AddSugar()
- {
- $this['Cup']['Spoon'] = 1;
- $this['Ammount'] = @$this['Ammount'] + 1;
- $this['Water'] -= 10;
- printf('Adding sugar: %d%s', 1, "\n");
- }
- public function doSuperChain()
- {
- print __CLASS__.'::SuperChain('.var_export(func_get_args(), true).")\n";
- parent::doSuperChain(__CLASS__);
- }
- }
- class DoubleSugarCube extends SugarCube
- {
- protected $old;
- public function __construct(Component $Component)
- {
- parent::__construct($Component);
- $this->old = $this->SetFunction('Produce', 'doProduce');
- $this->SetFunction('SuperChain', 'doSuperChain');
- }
- public function AddSugar()
- {
- // Call parent class then parent object
- $this['Cup']['Spoon'] = 1;
- $this['Ammount'] = @$this['ammount'] + 2;
- $this['Water'] -= 20;
- printf('Adding sugar: %d%s', 2, "\n");
- }
- public function doProduce()
- {
- print "\nI have take over Produce!\n";
- print "But I'm a nice guy so I'll call my parent\n\n";
- // Call parent objects function
- $this->parent->doProduce();
- }
- public function doSuperChain()
- {
- static $count = 0;
- print __CLASS__.'::SuperChain('.var_export(func_get_args(), true).")\n";
- parent::doSuperChain(__CLASS__);
- }
- }
- $Sugar = 1;
- $DoubleSugar = 1;
- $Cofee = new SimpleCofee();
- $Tea = new SimpleTea();
- $Cofee->Produce();
- $Tea->Produce();
- print "\n============\n\n";
- if($Sugar)
- {
- new SugarCube($Cofee);
- $Cofee->Produce();
- new SugarCube($Cofee);
- $Cofee->Produce();
- }
- if($DoubleSugar)
- {
- new DoubleSugarCube($Tea);
- $Tea->Produce();
- new DoubleSugarCube($Tea);
- $Tea->Produce();
- }
- print "\n============\n\n";
- $Tea->SuperChain('test');
Add Comment
Please, Sign In to add comment