Advertisement
fruffl

merge protected

Jan 18th, 2013
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 6.39 KB | None | 0 0
  1. <?PHP
  2.  
  3.     CLASS A EXTENDS FU
  4.     {
  5.         protected static $__autoConfig =
  6.         [
  7.             'baz' => 'merge', 'bob', 'foo'
  8.         ];
  9.        
  10.         protected static $__defaultConfig =
  11.         [
  12.             'baz' => 1,
  13.             'bob' => 10,
  14.             'foo' => 100,
  15.         ];
  16.     }
  17.    
  18.     CLASS B EXTENDS A
  19.     {
  20.         protected static $__autoConfig =
  21.         [
  22.             'baz', 'bob' => 'merge', 'bar'
  23.         ];
  24.        
  25.         protected static $__defaultConfig =
  26.         [
  27.             'baz' => 5,
  28.             'bob' => 50,
  29.             'bar' => 5000,
  30.         ];
  31.     }
  32.    
  33.     /*
  34.            A::baz => merge
  35.            A::bob
  36.            A::foo
  37.            
  38.            B : A
  39.            
  40.            B::baz
  41.            B::bob => merge
  42.            B::bar
  43.            
  44.        expected:
  45.            B::baz
  46.            B::bob => merge
  47.            B::foo
  48.            B::bar
  49.     */
  50.     $fu = new B;
  51.     var_dump($fu);
  52.    
  53.     return;
  54.  
  55. /*
  56. object(root\B)#6 (2) {
  57.   ["__initConfig":protected]=>
  58.   array(5) {
  59.     ["__run"]=>
  60.     bool(true)
  61.     ["baz"]=>
  62.     int(5)
  63.     ["bob"]=>
  64.     int(50)
  65.     ["foo"]=>
  66.     int(100)
  67.     ["bar"]=>
  68.     int(5000)
  69.   }
  70.   ["debug"]=>
  71.   &array(2) {
  72.     ["__autoConfig"]=>
  73.     array(4) {
  74.       [0]=>
  75.       string(3) "baz"
  76.       ["bob"]=>
  77.       string(5) "merge"
  78.       [1]=>
  79.       string(3) "bar"
  80.       [2]=>
  81.       string(3) "foo"
  82.     }
  83.     ["__defaultConfig"]=>
  84.     array(4) {
  85.       ["baz"]=>
  86.       int(5)
  87.       ["bob"]=>
  88.       int(50)
  89.       ["foo"]=>
  90.       int(100)
  91.       ["bar"]=>
  92.       int(5000)
  93.     }
  94.   }
  95. }
  96. */
  97.  
  98.     class fu
  99.     {
  100.         /**
  101.          * @late-state
  102.          */
  103.         protected static $__defaultConfig   = [];
  104.  
  105.         /**
  106.          * @late-state
  107.          */
  108.         protected static $__autoConfig      = [];
  109.        
  110.         /**
  111.          * @read-only
  112.          */
  113.         protected $__initConfig         = [];
  114.        
  115.         /**
  116.          * @cache
  117.          */
  118.         private static $__configCache       = [];
  119.  
  120.         /**
  121.          * @cache
  122.          */
  123.         private static $__parentClassCache  = [];
  124.  
  125.         /**
  126.          * @template
  127.          */
  128.         private static $__baseConfig        =
  129.         [
  130.             '__run' => TRUE
  131.         ];
  132.        
  133.         final public function __construct(array $__options = [])
  134.         {
  135.             $this->collect()->__initConfig = $this->extend
  136.             (
  137.                 TRUE,
  138.                 self::$__baseConfig,
  139.                 self::$__configCache[get_called_class()]['__defaultConfig'],
  140.                 $__options
  141.             );
  142.            
  143.             $this->debug =& self::$__configCache[get_called_class()];
  144.            
  145.             return TRUE === $this->__initConfig['__run']
  146.                 ? $this->__run()
  147.                 : $this;
  148.         }
  149.        
  150.         protected function __run()
  151.         {
  152.         }
  153.        
  154.         public static function parents($__className = NULL)
  155.         {
  156.             $parentClasses = &self::$__parentClassCache;
  157.            
  158.             $class = NULL === $__className ? get_called_class() : $__className;
  159.            
  160.             if(isset($parentClasses[$class]))
  161.                 return $parentClasses[$class];
  162.            
  163.             $classes = [];
  164.                    
  165.             do
  166.             {
  167.                     $classes[] = $class;
  168.             }
  169.             while($class = get_parent_class($class));
  170.                
  171.                 $parentClasses[$class] = $classes;
  172.                
  173.                 return $classes;
  174.         }
  175.        
  176.        
  177.         /**
  178.          *
  179.          *
  180.          * replace:
  181.          *  $c->extend(['myNewBar' => ['foo' => 'blop']]);
  182.          *  $c->extend(['myNewBar' => ['fob' => 'baz']]);
  183.          *
  184.          *  ["myNewBar"]=>
  185.          *      array(1) {
  186.          *          ["fob"]=>
  187.          *          string(3) "baz"
  188.          *      }
  189.          *
  190.          *
  191.          * extend:
  192.          *  $c->extend(['myNewBar' => ['foo' => 'blop']]);
  193.          *  $c->extend(true, ['myNewBar' => ['fob' => 'baz']]);
  194.          *
  195.          *  ["myNewBar"]=>
  196.          *      array(2) {
  197.          *          ["foo"]=>
  198.          *          string(4) "blop"
  199.          *          ["fob"]=>
  200.          *          string(3) "baz"
  201.          *      }
  202.          *
  203.          * extend multi:
  204.          *  $c->extend(['myNewBar' => ['foo' => 'blop']]);
  205.          *  $c->extend(true, $c, ['myNewBar' => ['fob' => 'baz']], ['myNewBar' => ['bla' => 'baz']]);
  206.          *
  207.          *  ["myNewBar"]=>
  208.          *      array(3) {
  209.          *          ["foo"]=>
  210.          *          string(4) "blop"
  211.          *          ["fob"]=>
  212.          *          string(3) "baz"
  213.          *          ["bla"]=>
  214.          *          string(3) "baz"
  215.          *      }
  216.          *
  217.          * @callable array $__data
  218.          * @callable array $__target, array $__data
  219.          * @callable bool $__recursive, array $__data
  220.          * @callable bool $__recursive, array $__target, array $__data
  221.          * @param mixed
  222.          * @return array|this
  223.          * @note $tar is not a referenced array
  224.          */
  225.         public function extend()
  226.         {
  227.             $args       = func_get_args();
  228.             $tar        = $args[0];
  229.             $i      = 1;
  230.             $length     = count($args);
  231.             $rec        = false;
  232.            
  233.             if($tar === true || $tar === false)
  234.             {
  235.                 $rec = $tar;
  236.                 $tar = isset($args[1]) ? $args[1] : [];
  237.                 $i = 2;
  238.             }
  239.            
  240.             if(!is_array($tar) && !is_object($tar))
  241.                 $tar = [];
  242.                
  243.             if($length === $i)
  244.             {
  245.                 $tar = $this;
  246.                 --$i;
  247.             }
  248.            
  249.             for( ; $i < $length; $i++)
  250.             {
  251.                 if(NULL === ($opt = $args[$i]))
  252.                     continue;
  253.                
  254.                 foreach($opt as $key => $value)
  255.                 {
  256.                     switch(TRUE):
  257.                         case is_array($tar):
  258.                             $tar[$key] = (TRUE === $rec && is_array($value) && isset($tar[$key]) && is_array($tar[$key]))
  259.                                 ? $this->extend($rec, $tar[$key], $value)
  260.                                 : $value;
  261.                             break;
  262.                         case is_object($tar):
  263.                             $tar->$key = (TRUE === $rec && is_array($value) && isset($tar->$key) && is_array($tar->$key))
  264.                                 ? $this->extend($rec, $tar->$key, $value)
  265.                                 : $value;
  266.                             break;
  267.                         case is_string($tar):
  268.                             $tar::${$key} = (TRUE === $rec && is_array($value) && is_array($tar::${$key}))
  269.                                 ? $this->extend($rec, $tar::${$key}, $value)
  270.                                 : $value;
  271.                             break;
  272.                     endswitch;
  273.                 }
  274.             }
  275.            
  276.             return $tar;
  277.         }
  278.  
  279.         private function __collect()
  280.         {
  281.             $class = get_called_class();
  282.            
  283.             if(isset(self::$__configCache[$class]))
  284.                 return $this;
  285.                
  286.             self::$__configCache[$class] = [];
  287.            
  288.             // merge + cache __autoConfig, __defaultConfig from childClass up to baseClass
  289.             // __autoConfig: array_unique(array_merge())
  290.             // __defaultConfig: childClass extends recursively parentClass
  291.             $cache = &self::$__configCache[$class];
  292.            
  293.             foreach($this->parents($class) as $lookup)
  294.             {
  295.                 foreach(['__autoConfig', '__defaultConfig'] as $property)
  296.                 {
  297.                     if(!isset($lookup::${$property}))
  298.                         continue;
  299.                    
  300.                     $value = $lookup::${$property};
  301.                    
  302.                     if(!isset($cache[$property]))
  303.                         $cache[$property] = [];
  304.                    
  305.                     switch($property):
  306.                         case '__autoConfig':
  307.                             foreach($value as $key => $flag)
  308.                             {
  309.                                 $search = is_string($key) ? $key : $flag;
  310.                                
  311.                                 if(isset($cache[$property][$search]))
  312.                                     continue;
  313.                                    
  314.                                 $cache[$property][$search] = is_string($key) ? $flag : '';
  315.                             }
  316.                             break;
  317.                         case '__defaultConfig':
  318.                             if(is_array($cache[$property]) && is_array($value))
  319.                                 $cache[$property] = $this->extend(TRUE, $value, $cache[$property]);
  320.                             break;
  321.                     endswitch;
  322.                 }
  323.             }
  324.            
  325.             return $this;
  326.         }
  327.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement