Advertisement
fruffl

AOP/Injectable Object

Jan 10th, 2013
48
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 9.81 KB | None | 0 0
  1. <?PHP
  2.     NAMESPACE ILLI\Core;
  3.     USE ILLI\Core\Object\tAdapter;
  4.     USE ILLI\Core\Object\tFilter;
  5.     USE ILLI\Core\Object\tObserver;
  6.     USE ILLI\Core\Object\tSignal;
  7.     USE ILLI\Core\Object\tClass;
  8.     USE ILLI\Core\Object\tTo;
  9.     USE ILLI\Core\Object\tMethod;
  10.    
  11.     CLASS Object
  12.     {
  13.         USE tTo;
  14.         USE tClass;
  15.         USE tAdapter;
  16.         USE tFilter;
  17.         USE tObserver;
  18.         USE tSignal;
  19.         USE tMethod;
  20.        
  21.         protected static $__parentClasses   = [];
  22.        
  23.         /**
  24.          * allowed/expected fields: [optionName1 => flag, optionName2, ...]
  25.          */
  26.         protected $__autoConfig         = [];
  27.        
  28.         /**
  29.          * runtime options: init + defaults
  30.          */
  31.         protected $__runtimeConfig      = [];
  32.        
  33.         /**
  34.          * default options
  35.          */
  36.         protected $__defaultConfig      = [];
  37.        
  38.         /**
  39.          * constructor initial config
  40.          */
  41.         protected $__initConfig         = [];
  42.        
  43.         /**
  44.          * Lib::load()  -> ::__init()
  45.          *
  46.          * __construct
  47.          * [
  48.          *  __run?:true
  49.          *      -> __configure()
  50.          *      -> __install()
  51.          *      -> __run()
  52.          *          -> tSignal  __construct runtimeConfig PRE_EVENT
  53.          *          -> __main()
  54.          *          -> tFilter  __construct runtimeConfig *
  55.          *          -> tObserver    __construct runtimeConfig
  56.          *          -> tSignal  __construct runtimeConfig POST_EVENT
  57.          * ]
  58.          */
  59.         public function __construct(array $__options = [])
  60.         {
  61.             $defaults =
  62.             [
  63.                 '__run'     => TRUE,        // excecute setup()
  64.                 '__main'    => '__main',        // onConstructEvent
  65.                 '__delegate'    => NULL,        // class-delegate: adapter for every method; instance or className
  66.                
  67.                 '__adapter' =>          // trigger__FUNCTION__ => hook | trigger__FUNCTION__ => [event => hook]
  68.                 [
  69.                     __FUNCTION__ => []      // 0 => class|instance, 1 => method | 0 => closure; overwrites methods from __delegate
  70.                 ],
  71.                
  72.                 '__filter'  =>          // trigger__FUNCTION__ => hook
  73.                 [
  74.                     __FUNCTION__ => []      // [filter 1, filter 2, filter n ...] | [eventName => [filter 1, filter 2, filter n]]; default event is '*'
  75.                 ],
  76.                
  77.                 '__method'  =>
  78.                 [
  79.                                     // name => closure; public virtual methods, called by __call
  80.                 ],
  81.                
  82.                 '__observer'    =>
  83.                 [
  84.                     __FUNCTION__ => []      // event => [notify 1, notify 2, ...]
  85.                 ],
  86.                
  87.                 '__signal' =>
  88.                 [
  89.                     __FUNCTION__ =>         // trigger__FUNCTION__ => [event => hook]
  90.                     [
  91.                         'PRE_EVENT' =>  [], // event => [signal 1, signal 2, ...]
  92.                         'POST_EVENT' => []  // event => [signal 1, signal 2, ...]
  93.                     ],
  94.                 ],
  95.                 '__class'   => [],          // class alias hook: new __class['Alias']() instead of new hardCodedClassName()
  96.                 '__to'      =>          // cast to: type => handler
  97.                 [
  98.                     //'string' => 'toString',
  99.                     //'array'  => 'toArray'
  100.                 ]
  101.             ];
  102.            
  103.             $this->__initConfig = $this->extend(TRUE, $__options, $defaults);
  104.            
  105.             if(TRUE === $this->__initConfig['__run'])
  106.                 $this->__run();
  107.                
  108.             return $this;
  109.         }
  110.        
  111.         public function extend()
  112.         {
  113.             $args       = func_get_args();
  114.             $tar        = $args[0];
  115.             $i      = 1;
  116.             $length     = count($args);
  117.             $rec        = false;
  118.            
  119.             if($tar === true || $tar === false)
  120.             {
  121.                 $rec = $tar;
  122.                 $tar = isset($args[1]) ? $args[1] : [];
  123.                 $i = 2;
  124.             }
  125.            
  126.             if(!is_array($tar) && !is_object($tar))
  127.                 $tar = [];
  128.                
  129.             if($length === $i)
  130.             {
  131.                 if(FALSE === ($this instanceof \Iterator))
  132.                     throw new \Exception('Unable to iterate throw '.get_called_class());
  133.                
  134.                 $tar = $this;
  135.                 --$i;
  136.             }
  137.            
  138.             for( ; $i < $length; $i++)
  139.             {
  140.                 if(NULL === ($opt = $args[$i]))
  141.                     continue;
  142.                
  143.                 foreach($opt as $key => $value)
  144.                 {
  145.                     if(is_array($value) && isset($tar[$key]) && is_array($tar[$key]))
  146.                     {
  147.                         $tar[$key] = $this->extend($tar[$key], $value);
  148.                         continue;
  149.                     }
  150.                    
  151.                     if(is_object($value))
  152.                     {
  153.                         //$tar[$key] = TRUE === $rec ? clone $value : $value;
  154.                         $tar[$key] = $value;
  155.                         continue;
  156.                     }
  157.                    
  158.                     $value = $opt[$key];
  159.                     $tar[$key] = $value;
  160.                 }
  161.             }
  162.            
  163.             return $tar;
  164.         }
  165.        
  166.         public function __clone()
  167.         {
  168.                         if($this instanceOf iLink)
  169.                                 return $this->link();
  170.                         if($this instanceOf iCopy)
  171.                                 return $this->copy();
  172.  
  173.                         throw new \Exception('Not supported');
  174.         }
  175.        
  176.         /**
  177.          * referenced runtime to create new object from called-class
  178.          */
  179.         public function link()
  180.         {
  181.             $class  = get_called_class();
  182.             return $class::__construct($this->__runtimeConfig);
  183.         }
  184.        
  185.         /**
  186.          * dereference runtime and create new object from called-class
  187.          */
  188.         public function copy()
  189.         {
  190.             $class = get_called_class();
  191.             $config = $this->__runtimeConfig;   // config is a reference!
  192.             unset($this->__runtimeConfig);      // unlink
  193.             $this->__runtimeConfig = $config;   // re-reference original
  194.             return new $class($config);     // build
  195.         }
  196.        
  197.        
  198.         /**
  199.          * fileOnLoad event
  200.          *
  201.          * @see Lib::load()
  202.          */
  203.         public static function __init()
  204.         {
  205.         }
  206.        
  207.         /**
  208.          * construct-event
  209.          */
  210.         protected function __main()
  211.         {
  212.         }
  213.        
  214.         protected function __run()
  215.         {
  216.             $this->__install();
  217.            
  218.             $this->Core_Object_tSignal_emit(get_called_class(), '__construct', 'PRE_EVENT', $this->__runtimeConfig);
  219.  
  220.             $this->{$this->__initConfig['__main']}();
  221.  
  222.             $filtered = $this->Core_Object_tFilter_emit(get_called_class(), '__construct', [$this->__runtimeConfig])[0];
  223.             $this->Core_Object_tObserver_emit('__construct', $filtered);
  224.             $this->Core_Object_tSignal_emit(get_called_class(), '__construct', 'POST_EVENT', $this->__runtimeConfig);
  225.            
  226.             return $this;
  227.         }
  228.        
  229.         protected function __install()
  230.         {
  231.             $this->__configure();
  232.            
  233.             $class = get_called_class();
  234.            
  235.             $this->Core_Object_tClass_install   ($this->__initConfig['__class']);
  236.             $this->Core_Object_tMethod_install  ($this->__initConfig['__method']);
  237.             $this->Core_Object_tTo_install      ($this->__initConfig['__to']);
  238.            
  239.             $this->Core_Object_tAdapter_install ($class, $this->__initConfig['__delegate']);
  240.             $this->Core_Object_tAdapter_install ($class, $this->__initConfig['__adapter']);
  241.             $this->Core_Object_tObserver_install    ($class, $this->__initConfig['__observer']);
  242.             $this->Core_Object_tSignal_install  ($class, $this->__initConfig['__signal']);
  243.             $this->Core_Object_tFilter_install  ($class, $this->__initConfig['__filter']);
  244.            
  245.             return $this;
  246.         }
  247.        
  248.         protected function __configure()
  249.         {
  250.             if($this->__autoConfig === [])
  251.                 return $this;
  252.            
  253.             foreach($this->__autoConfig as $key => $flag)
  254.             {
  255.                 // option not given. use default
  256.                 if(!isset($this->__initConfig[$key])
  257.                 && isset($this->__defaultConfig[$key]))
  258.                 {
  259.                     $this->__runtimeConfig[$key] = $this->__defaultConfig[$key];
  260.                     continue;
  261.                 }
  262.                
  263.                 if(!isset($this->__initConfig[$flag])
  264.                 && isset($this->__defaultConfig[$flag]))
  265.                 {
  266.                     $this->__runtimeConfig[$flag] = $this->__defaultConfig[$flag];
  267.                     continue;
  268.                 }
  269.                
  270.                 if($flag === 'merge') // init + default
  271.                 {
  272.                     if(isset($this->__defaultConfig[$key])) // if exists...
  273.                     {
  274.                         $this->__runtimeConfig[$key] = $this->__initConfig[$key] + $this->__defaultConfig[$key];
  275.                     }
  276.                     else
  277.                     {
  278.                         $this->__runtimeConfig[$key] = $this->__initConfig[$key];
  279.                     }
  280.                 }
  281.                 else // init[${key}]
  282.                 if(isset($this->__initConfig[$key]))
  283.                 {
  284.                     $this->__runtimeConfig[$flag] = $this->__initConfig[$flag];
  285.                 }
  286.                 else // init[${flag}]
  287.                 if(isset($this->__initConfig[$flag]))
  288.                 {
  289.                     $this->__runtimeConfig[$flag] = $this->__initConfig[$flag];
  290.                 }
  291.                 else // default[${key}]
  292.                 if(isset($this->__defaultConfig[$key]))
  293.                 {
  294.                     $this->__runtimeConfig[$key] = $this->__defaultConfig[$key];
  295.                 }
  296.                 else // default[${flag}]
  297.                 if(isset($this->__defaultConfig[$flag]))
  298.                 {
  299.                     $this->__runtimeConfig[$flag] = $this->__defaultConfig[$flag];
  300.                 }
  301.                 else
  302.                 {
  303.                     $this->__runtimeConfig[$flag] = NULL;
  304.                 }
  305.             }
  306.            
  307.             foreach($this->__runtimeConfig as $property => &$value)
  308.             {
  309.                 $this->{$property} =& $value;
  310.                 unset($this->__initConfig[$property]);
  311.             }
  312.            
  313.             return $this;
  314.         }
  315.        
  316.         public function __call($__name, array $__parameters = [])
  317.         {
  318.             return $this->Core_Object_tMethod_emit($__name, $__parameters);
  319.         }
  320.        
  321.         public static function __set_state($data)
  322.         {
  323.             $this->__export = $data;
  324.             $class = get_called_class();
  325.             $object = new $class();
  326.        
  327.             foreach($object as $property => $value)
  328.                 $object->{$property} = $value;
  329.            
  330.             return $object;
  331.         }
  332.        
  333.         public static function getParents($__className = NULL)
  334.         {
  335.             $class = NULL === $__className ? get_called_class() : $__className;
  336.        
  337.             if(!isset(self::$__parentClasses[$class]))
  338.                 self::$__parentClasses[$class] = class_parents($class);
  339.            
  340.             return self::$__parentClasses[$class];
  341.         }
  342.        
  343.         public function to($__format, array $__options = [])
  344.         {
  345.             $__options +=
  346.             [
  347.                 'internal' => FALSE,
  348.                 'handlers' => []
  349.             ];
  350.            
  351.             return $this->Core_Object_tTo_emit($__format, [$__options]);
  352.         }
  353.        
  354.         public function toString(array $__options = [])
  355.         {
  356.             return get_called_class();
  357.         }
  358.        
  359.         public function toArray(array $__options = [])
  360.         {
  361.             $result = [];
  362.        
  363.             foreach($this as $property => $value)
  364.             {
  365.                 if(substr($property, 0, 2) === '__')
  366.                     continue;
  367.                    
  368.                 switch(true):
  369.                     case is_array($value):
  370.                     case (!is_object($property)):
  371.                         $result[$property] = $value;
  372.                         break;
  373.                     case (isset($__options['handlers'][$class = get_class($value)])):
  374.                         $result[$property] = $__options['handlers'][$class]($value);
  375.                         break;
  376.                     case (method_exists($property, 'to')):
  377.                         $result[$property] = $value->to('array', $__options);
  378.                         break;
  379.                     case ($vars = get_object_vars($value)):
  380.                         $result[$property] = $vars;
  381.                         break;
  382.                     case (method_exists($value, '__toString')):
  383.                         $result[$property] = (string) $value;
  384.                         break;
  385.                     default:
  386.                         $result[$property] = $value;
  387.                         break;
  388.                 endswitch;
  389.             }
  390.            
  391.             return $result;
  392.         }
  393.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement