Want more features on Pastebin? Sign Up, it's FREE!
Guest

http://stackoverflow.com/questions/18114141/full-inheritance

By: a guest on Nov 20th, 2013  |  syntax: PHP  |  size: 7.48 KB  |  views: 43  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
This paste has a previous version, view the difference. Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. <?php
  2.  
  3. abstract class Component extends stdCLass implements ArrayAccess, Countable
  4. {
  5.         protected $Decorators   = array();
  6.         protected $Water                = 0;
  7.         protected $SharedProps  = 0;
  8.        
  9.         public function GetProperties(Component $Child)
  10.         {
  11.                 foreach($this as $k => $v)
  12.                 {
  13.                         $Child->{$k} = &$this->{$k};
  14.                 }
  15.                
  16.                 if(!isset($this->datahash))
  17.                 {
  18.                         $Child->base     = &$this;
  19.                         $Child->datahash = spl_object_hash($this);
  20.                 }
  21.         }
  22.        
  23.         public function AddDecorator($func, $args = array())
  24.         {
  25.                 if(is_callable($func))
  26.                 {
  27.                         array_push($this->Decorators, array($func, $args));
  28.                 }
  29.                 else
  30.                 {
  31.                         throw new InvalidArgumentException(sprintf('%s::AddDecorator(callable $func, array $args): Invalid function ( %s ).', get_class($this), var_export($func, true)));
  32.                 }
  33.         }
  34.        
  35.         public function RemoveDecorator($func, $args = array())
  36.         {
  37.                 foreach($this->Decorators as & $decorator)
  38.                 {
  39.                         if($decorator === array($func, $args))
  40.                         {
  41.                                 unset($decorator);
  42.                                 return true;
  43.                         }
  44.                 }
  45.                
  46.                 return false;
  47.         }
  48.        
  49.         public function Decorate()
  50.         {
  51.                 foreach($this->Decorators as $call)
  52.                 {
  53.                         call_user_func_array($call[0], $call[1]);
  54.                 }
  55.         }
  56.        
  57.         public function __call($Key, $Params)
  58.         {
  59.                 $prev = debug_backtrace();
  60.                 $Key  = (string)$Key;
  61.                 $base = isset($this->base)
  62.                         ? $this->base
  63.                         : $this
  64.                 ;
  65.                
  66.                 if(!isset($this->{$Key}) && !isset($base->{$Key}))
  67.                 {
  68.                         throw new BadMethodCallException(sprintf('Call to undefined method `%s::%s()`', get_class($this), $Key));
  69.                         return;
  70.                 }
  71.                
  72.                 if(is_callable($this->{$Key}))
  73.                 {
  74.                         return call_user_func_array($this->{$Key}, $Params);
  75.                 }
  76.                 elseif(is_callable($base->{$Key}))
  77.                 {
  78.                         return call_user_func_array($base->{$Key}, $Params);
  79.                 }
  80.                 else
  81.                 {
  82.                         throw new BadMethodCallException(sprintf('Call to undefined method `%s::{%s}()`.', get_class($this), var_export($this->{$Key}, true)));
  83.                         return;
  84.                 }
  85.                
  86.         }
  87.        
  88.         private function getHash()
  89.         {
  90.                 return isset($this->datahash)
  91.                         ? $this->datahash
  92.                         : $this->datahash = spl_object_hash($this)
  93.                 ;
  94.         }
  95.        
  96.         public function offsetSet($offset, $value)
  97.         {
  98.                 static $count = 0;
  99.                
  100.                 $hash = $this->getHash();
  101.                
  102.                 if (is_null($offset))
  103.                 {
  104.                         $this->{$hash.$count++} = $value;
  105.                         $this->SharedProps++;
  106.                 }
  107.                 else
  108.                 {
  109.                         if(!isset($this[$offset])) $this->SharedProps++;
  110.                        
  111.                         $this->{$hash.$offset} = $value;
  112.                 }
  113.         }
  114.        
  115.         public function offsetExists($offset)
  116.         {
  117.                 return isset($this->{$this->getHash().$offset});
  118.         }
  119.        
  120.         public function offsetUnset($offset)
  121.         {
  122.                 $hash = $this->getHash();
  123.                
  124.                 if(isset($this->{$hash.$offset})) $this->SharedProps--;
  125.                
  126.                 unset($this->{$hash.$offset});
  127.         }
  128.        
  129.         public function &offsetGet($offset)
  130.         {
  131.                 return $this->{$this->getHash().$offset};
  132.         }
  133.        
  134.         public function count()
  135.         {
  136.                 return count($this->SharedProps);
  137.         }
  138.        
  139.         protected function nop(){;}
  140.        
  141.         public function SetFunction($name, $func = 'nop')
  142.         {
  143.                 $base = isset($this->base)
  144.                         ? $this->base
  145.                         : $this
  146.                 ;
  147.                
  148.                 $old = isset($base->{$name})
  149.                         ? $base->{$name}
  150.                         : NULL
  151.                 ;
  152.                
  153.                 if(!is_callable(array($this, $func)))
  154.                 {
  155.                         var_dump($this, $func);
  156.                        
  157.                         throw new InvalidArgumentException(sprintf('%s::SetFunction(): Undefined method `%s`', get_class($this), var_export($func, true)));
  158.                 }
  159.                
  160.                 $this->{$name} = $base->{$name} = array($this, $func);
  161.                
  162.                 return $old;
  163.         }
  164.        
  165.         // Note Uses shared version of water and can cause notices
  166.         function PourWater()
  167.         {
  168.                 printf('Adding Water: %d%s', $this['Water'], "\n");
  169.         }
  170. }
  171.  
  172. abstract class Decorator extends Component
  173. {
  174.         public function __construct(Component $Parent)
  175.         {
  176.                 $this->parent = &$Parent;
  177.                
  178.                 $Parent->GetProperties($this);
  179.         }
  180.        
  181.         public function __call($Key, $Params)
  182.         {
  183.                 $prev   = debug_backtrace();
  184.                 $prev   = $prev[0]['class'];
  185.                
  186.                 if($prev == __CLASS__)
  187.                 {
  188.                         if(!is_callable(array($this->parent, $Key)))
  189.                         {
  190.                                 throw new BadMethodCallException(sprintf('Call to undefined method `%s::%s()`', get_class($this), $Key));
  191.                                 return;
  192.                         }
  193.                        
  194.                         return call_user_func_array(array($this->parent, $Key), $Params);
  195.                 }
  196.                
  197.                 parent::__call($Key, $Params);
  198.         }
  199. }
  200.  
  201. class SimpleCofee extends Component
  202. {
  203.         protected $Name                 = 'Cofee';
  204.         protected $Cup                  = array();
  205.        
  206.         public function __construct($Parent = NULL)
  207.         {
  208.                 $this->Water             = 150;
  209.                 $this->Cup['cofeee'] = 25;
  210.                
  211.                 if($Parent instanceof Component)
  212.                 {
  213.                         $Parent->GetProperties($this);
  214.                 }
  215.                 else
  216.                 {
  217.                         $this['Name']           = $this->Name;
  218.                         $this['Water']          = $this->Water;
  219.                         $this['Cup']            = $this->Cup;
  220.                 }
  221.                
  222.                 $this->SetFunction('Produce', 'doProduce');
  223.                 $this->SetFunction('SuperChain', 'doSuperChain');
  224.         }
  225.        
  226.         public function doProduce()
  227.         {
  228.                 printf("Making %s....\n", $this->Name);
  229.                
  230.                 $this->Decorate();
  231.                
  232.                 //.....
  233.                 $this->PourWater();
  234.                 //......
  235.                
  236.                 printf("Making %s: %s\n", $this['Name'], var_export($this['Cup'], true));              
  237.         }
  238.  
  239.         public function doSuperChain()
  240.         {
  241.                 print __CLASS__.'::SuperChain('.var_export(func_get_args(), true).")\n";
  242.         }
  243. }
  244.  
  245. class SimpleTea extends SimpleCofee
  246. {
  247.         protected $Name                 = 'Tea';
  248.        
  249.         public function __construct($Parent = NULL)
  250.         {
  251.                 $this->Water             = 150;
  252.                 $this->Cup['tea']        = 25;
  253.                
  254.                 if($Parent instanceof Component)
  255.                 {
  256.                         $Parent->GetProperties($this);
  257.                 }
  258.                 else
  259.                 {
  260.                         $this['Name']           = $this->Name;
  261.                         $this['Water']          = $this->Water;
  262.                         $this['Cup']            = $this->Cup;
  263.                 }
  264.  
  265.                 $this->SetFunction('Produce', 'doProduce');
  266.                 $this->SetFunction('SuperChain', 'doSuperChain');
  267.         }
  268.  
  269.         public function doSuperChain()
  270.         {
  271.                 print __CLASS__.'::SuperChain('.var_export(func_get_args(), true).")\n";
  272.                
  273.                 parent::doSuperChain(__CLASS__);
  274.         }
  275. }
  276.  
  277.  
  278. class SugarCube extends Decorator
  279. {
  280.         public function __construct(Component $Parent)
  281.         {
  282.                 parent::__construct($Parent);
  283.                
  284.                 $Parent->AddDecorator(array($this, 'AddSugar'));
  285.                
  286.                 $this->SetFunction('SuperChain', 'doSuperChain');
  287.         }
  288.        
  289.         public function AddSugar()
  290.         {
  291.                 $this['Cup']['Spoon']    = 1;
  292.                 $this['Ammount']                 = @$this['Ammount'] + 1;
  293.                 $this['Water']                  -= 10;
  294.                
  295.                 printf('Adding sugar: %d%s', 1, "\n");
  296.         }
  297.  
  298.         public function doSuperChain()
  299.         {
  300.                 print __CLASS__.'::SuperChain('.var_export(func_get_args(), true).")\n";
  301.                
  302.                 parent::doSuperChain(__CLASS__);
  303.         }
  304. }
  305.  
  306. class DoubleSugarCube extends SugarCube
  307. {
  308.         protected $old;
  309.  
  310.         public function __construct(Component $Component)
  311.         {
  312.                 parent::__construct($Component);
  313.                
  314.                 $this->old = $this->SetFunction('Produce', 'doProduce');
  315.                
  316.                 $this->SetFunction('SuperChain', 'doSuperChain');
  317.         }
  318.        
  319.         public function AddSugar()
  320.         {
  321.                 // Call parent class then parent object
  322.                 $this['Cup']['Spoon']    = 1;
  323.                 $this['Ammount']                 = @$this['ammount'] + 2;
  324.                 $this['Water']                  -= 20;
  325.                
  326.                 printf('Adding sugar: %d%s', 2, "\n");
  327.         }
  328.        
  329.         public function doProduce()
  330.         {
  331.                 print "\nI have take over Produce!\n";
  332.                 print "But I'm a nice guy so I'll call my parent\n\n";
  333.                
  334.                 // Call parent objects function
  335.                 $this->parent->doProduce();
  336.         }
  337.        
  338.         public function doSuperChain()
  339.         {
  340.                 static $count = 0;
  341.                
  342.                 print __CLASS__.'::SuperChain('.var_export(func_get_args(), true).")\n";
  343.                
  344.                 parent::doSuperChain(__CLASS__);
  345.         }
  346. }
  347.  
  348.  
  349. $Sugar = 1;
  350. $DoubleSugar = 1;
  351.  
  352. $Cofee = new SimpleCofee();
  353. $Tea   = new SimpleTea();
  354.  
  355. $Cofee->Produce();
  356. $Tea->Produce();
  357.  
  358. print "\n============\n\n";
  359.  
  360. if($Sugar)
  361. {
  362.         new SugarCube($Cofee);
  363.         $Cofee->Produce();
  364.         new SugarCube($Cofee);
  365.         $Cofee->Produce();
  366. }
  367.  
  368. if($DoubleSugar)
  369. {
  370.         new DoubleSugarCube($Tea);
  371.         $Tea->Produce();
  372.         new DoubleSugarCube($Tea);
  373.         $Tea->Produce();
  374. }
  375.  
  376. print "\n============\n\n";
  377.  
  378. $Tea->SuperChain('test');
clone this paste RAW Paste Data