fruffl icon

AOP/Injectable Object

fruffl | 01/16/13 03:40:11 PM UTC | 0 ⭐ | 280 👁️ | Never ⏰ | []
PHP |

15.92 KB

|

None

|

0 👍

/

0 👎

<?PHP
    NAMESPACE ILLI\Core;
    USE ILLI\Core\StaticObject\iAdapter;
    USE ILLI\Core\StaticObject\iClass;
    USE ILLI\Core\StaticObject\iFilter;
    USE ILLI\Core\StaticObject\iMethod;
    USE ILLI\Core\StaticObject\iMethodFacade;
    USE ILLI\Core\StaticObject\iMethodProto;
    USE ILLI\Core\StaticObject\iObserver;
    USE ILLI\Core\StaticObject\iSignal;
    USE ILLI\Core\StaticObject\iTo;
    USE ILLI\Core\StaticObject\tAdapter;
    USE ILLI\Core\StaticObject\tFilter;
    USE ILLI\Core\StaticObject\tInvoke;
    USE ILLI\Core\StaticObject\tObserver;
    USE ILLI\Core\StaticObject\tSignal;
    USE ILLI\Core\StaticObject\tClass;
    USE ILLI\Core\StaticObject\tTo;
    USE ILLI\Core\StaticObject\tMethod;
    USE ILLI\Core\StaticObject\tMethodFacade;
    USE ILLI\Core\StaticObject\tMethodProto;
    USE ILLI\Core\Filter;
    
    INTERFACE iStaticObject EXTENDS iAdapter, iClass, iFilter, iMethod, iMethodFacade, iMethodProto, iObserver, iSignal, iTo
    {
        public static function __load();
        
        public static function parents($__className = NULL);
        public static function traits($__className = NULL);
        
        public static function construct(array $__options = []);
        public static function __callstatic($__name, array $__parameters = []);
        
        public static function env(array $__options = []);
        public static function extend();
        public static function to($__format, array $__options = []);
    }
    
    CLASS StaticObject IMPLEMENTS iStaticObject
    {
        USE tMethodFacade
        {
            Core_StaticObject_tMethodFacade_register    AS public registerMethodFacade;
            Core_StaticObject_tMethodFacade_unregister  AS public unregisterMethodFacade;
            Core_StaticObject_tMethodFacade_exists      AS public isMethodFacade;
        }
        
        USE tAdapter
        {
            Core_StaticObject_tAdapter_register     AS public registerAdapter;
            Core_StaticObject_tAdapter_unregister       AS public unregisterAdapter;
            Core_StaticObject_tAdapter_exists       AS public isAdapter;
        }
        
        USE tClass
        {
            Core_StaticObject_tClass_register       AS public registerClass;
            Core_StaticObject_tClass_unregister     AS public unregisterClass;
            Core_StaticObject_tClass_exists         AS public isClass;
        }
        
        USE tFilter
        {
            Core_StaticObject_tFilter_register      AS public registerFilter;
            Core_StaticObject_tFilter_unregister        AS public unregisterFilter;
            Core_StaticObject_tFilter_exists        AS public isFilter;
        }
        
        USE tMethod
        {
            Core_StaticObject_tMethod_register      AS public registerMethod;
            Core_StaticObject_tMethod_unregister        AS public unregisterMethod;
            Core_StaticObject_tMethod_exists        AS public isMethod;
        }
        
        USE tObserver
        {
            Core_StaticObject_tObserver_register        AS public registerObserver;
            Core_StaticObject_tObserver_unregister      AS public unregisterObserver;
            Core_StaticObject_tObserver_exists      AS public isObserver;
        }
        
        USE tSignal
        {
            Core_StaticObject_tSignal_register      AS public registerSignal;
            Core_StaticObject_tSignal_unregister        AS public unregisterSignal;
            Core_StaticObject_tSignal_exists        AS public isSignal;
        }
        
        USE tTo
        {
            Core_StaticObject_tTo_register          AS public registerTo;
            Core_StaticObject_tTo_unregister        AS public unregisterTo;
            Core_StaticObject_tTo_exists            AS public isTo;
        }
        
        USE tMethodProto
        {
            Core_StaticObject_tMethodProto_register     AS public registerMethodProto;
            Core_StaticObject_tMethodProto_unregister   AS public unregisterMethodProto;
            Core_StaticObject_tMethodProto_exists       AS public isMethodProto;
        }
        
        USE tInvoke;
        
        protected static $__defaultConfig   = [];
        protected static $__autoConfig      = [];
        protected static $__defaultOptions  = [];
        
        protected static $__env         = [];
        protected static $__initConfig      = [];
        
        protected static $__parentClasses   = [];
        protected static $__usedTraits      = [];
        
        private static $__baseOptions       = 
        [
            '__run'     => TRUE,
            '__main'    => '__main',
            '__delegate'    => NULL,
            '__adapter' => [],
            '__filter'  => [],
            '__proto'   => [],
            '__method'  => [],
            '__observer'    => [],
            '__signal'  => [],
            '__class'   => [],
            '__to'      =>
            [
                'string'    => 'toString',
                'array'     => 'toArray'
            ],
            '__protoprefix' => 'prototype'
        ];
        
        protected static function __main()
        {
            var_dump(__METHOD__);
        }
        
        public static function __load()
        {
            $class = get_called_class();
            self::$__env[$class]        = [];
            self::$__initConfig[$class] = [];
        }
        
        private function __construct()
        {
        }
        
        final public static function construct(array $__options = [])
        {
            $class = get_called_class();
            
            var_dump(__METHOD__);
            
            self::$__initConfig[$class] = static::extend(TRUE, self::$__baseOptions, static::$__defaultOptions, $__options);
            
            if(TRUE === self::$__initConfig[$class]['__run'])
                static::__run();
        }
        
        public static function env(array $__env = [])
        {
            $class = get_called_class();
            
            foreach(self::$__env[$class] as $passable => $val)
            {
                if(FALSE === isset($__env[$passable]))
                    continue;
                    
                self::$__env[$class][$passable] = is_array(self::$__env[$class][$passable]) && is_array($__env[$passable])
                    ? static::extend(TRUE, self::$__env[$class][$passable], $__env[$passable])
                    : $__env[$passable];
                
                $key = "{$passable}";
                if(TRUE === isset(static::${$key}))
                    static::${$key} = &self::$__env[$class][$passable];
            }
        }
        
        protected static function __run()
        {
            $class = get_called_class();
            
            static::__configure();
            var_dump(__METHOD__);
                        static::Core_StaticObject_tMethod_install       (self::$__initConfig[$class]['__method']);
                        static::Core_StaticObject_tMethodProto_install      (self::$__initConfig[$class]['__proto']);
                        static::Core_StaticObject_tAdapter_install      (self::$__initConfig[$class]['__delegate']);
                        static::Core_StaticObject_tAdapter_install      (self::$__initConfig[$class]['__adapter']);
                        static::Core_StaticObject_tObserver_install     (self::$__initConfig[$class]['__observer']);
                        static::Core_StaticObject_tSignal_install       (self::$__initConfig[$class]['__signal']);
                        static::Core_StaticObject_tFilter_install       (self::$__initConfig[$class]['__filter']);
                        static::Core_StaticObject_tTo_install           (self::$__initConfig[$class]['__to']);
                        static::Core_StaticObject_tClass_install        (self::$__initConfig[$class]['__class']);
            static::prototype('construct', self::$__env[$class]);
        }
        
        protected static function __configure()
        {
            var_dump(__METHOD__);
            $class = get_called_class();
            
            $defaultConfig      =& static::$__defaultConfig;
            $autoConfig     =& static::$__autoConfig;
            $initConfig     =& self::$__initConfig[$class];
            $env            =& self::$__env[$class];
            
            foreach($autoConfig as $key => $flag)
            {
                // option not given. use default value
                if(!isset($initConfig[$key])
                && isset($defaultConfig[$key]))
                {
                    $env[$key] = $defaultConfig[$key];
                    continue;
                }
                
                if(!isset($initConfig[$flag])
                && isset($defaultConfig[$flag]))
                {
                    $env[$flag] = $defaultConfig[$flag];
                    continue;
                }
                
                if($flag === 'merge') // initConfig + defaultConfig
                {
                    if(isset($defaultConfig[$key]))
                    {
                        if(is_array($initConfig[$key])
                        && is_array($defaultConfig[$key]))
                        {
                            $env[$key] = static::extend
                            (
                                TRUE,
                                $initConfig[$key],
                                $defaultConfig[$key]
                            );
                        }
                        else
                        {
                            $env[$key] =
                                $initConfig[$key]
                                + $defaultConfig[$key];
                        }
                        
                    }
                    else
                    {
                        $env[$key] = $initConfig[$key];
                    }
                }
                else // initConfig[${key}]
                if(isset($initConfig[$key]))
                {
                    $env[$key] = $initConfig[$key];
                }
                else // initConfig[${flag}]
                if(isset($initConfig[$flag]))
                {
                    $env[$flag] = $initConfig[$flag];
                }
                else // defaultConfig[${key}]
                if(isset($defaultConfig[$key]))
                {
                    $env[$key] = $defaultConfig[$key];
                }
                else // default[${flag}]
                if(isset($defaultConfig[$flag]))
                {
                    $env[$flag] = $defaultConfig[$flag];
                }
                else
                {
                    $env[$flag] = NULL;
                }
            }
            
            // accessible as property
            foreach($env as $passable => &$value)
            {
                $key = "{$passable}";
                
                if(FALSE === isset(static::${$key}))
                    continue;
                    
                static::${$key} = &$value;
                
                if(isset($initConfig[$passable]))
                    unset($initConfig[$passable]);
            }
        }
        
        protected static function prototype($__function, array $__parameters = [])
        {
            var_dump(__METHOD__);
            $__class = get_called_class();
            
            if(isset($__parameters['this']))
                unset($__parameters['this']);
            
            if(TRUE === static::Core_StaticObject_tAdapter_exists($__function))
                return static::Core_StaticObject_tAdapter_emit($__function, $__parameters);
            
            $__parameters = static::Core_StaticObject_tFilter_emit($__function, 'PARAMS', $__parameters, ['return' => $__parameters]);
            
            static::Core_StaticObject_tSignal_emit($__function, 'PRE_EVENT', [$__parameters], ['return' => $__parameters]);
            
            $__result = static::Core_StaticObject_tMethodFacade_emit($__function, $__parameters, function(array $__params) use ($__class, $__function)
            {
                $result = NULL;
                
                if(TRUE === static::Core_StaticObject_tMethodProto_exists($__function))
                {
                    $result = static::Core_StaticObject_tMethodProto_emit($__function, $params);
                }
                else
                {
                    $proto = $__function === 'construct'
                        ? self::$__initConfig[$__class]['__main']
                        : self::$__initConfig[$__class]['__protoprefix'].$__function;
                
                    if($proto === $__function)
                    {
                    }
                    else
                    if(method_exists($__class, $proto))
                    {
                        $result = static::Core_StaticObject_tInvoke_method($proto, $__params);
                    }
                }
                
                return $result;
            });
            
            $__result = static::Core_StaticObject_tFilter_emit($__function, 'RETURN', $__result, ['return' => $__result]);
            
            static::Core_StaticObject_tObserver_emit($__function, [$__result, $__parameters]);
            static::Core_StaticObject_tSignal_emit($__function, 'POST_EVENT',  [$__result, $__parameters], ['return' => $__result]);
            
            return $__result;
        }
        
        public static function parents($__className = NULL)
        {
            $parentClasses = &self::$__parentClasses;
            
            $class = NULL === $__className ? get_called_class() : $__className;
            
            if(isset($parentClasses[$class]))
                return $parentClasses[$class];
            
            $classes = [$class];
                while($class = get_parent_class($class))
                    $classes[] = $class;
                
                $classes = array_reverse($classes);
                $parentClasses[$class] = $classes;
                
                return $classes;
        }
        
        public static function traits($__className = NULL)
        {
            $usedTraits = &self::$__usedTraits;
            
            $class = NULL === $__className ? get_called_class() : $__className;
            $classes = self::parents($class);
            
            if(isset($usedTraits[$class]))
                return $usedTraits[$class];
            
            $traits = [];
            foreach($classes as $class)
                foreach((new \ReflectionClass($class))->getTraits() as $trait)
                    $traits[] = $trait->name;
            
                $usedTraits[$class] = $traits;
                
                return $traits;
        }
        
        public static function extend()
        {
            $class      = get_called_class();
            $args       = func_get_args();
            $tar        = $args[0];
            $i      = 1;
            $length     = count($args);
            $rec        = false;
            
            if($tar === true || $tar === false)
            {
                $rec = $tar;
                $tar = isset($args[1]) ? $args[1] : [];
                $i = 2;
            }
            
            if(!is_array($tar) && !is_object($tar))
                $tar = [];
                
            if($length === $i)
            {
                //if(FALSE === ($this instanceof \Iterator))
                //  throw new \Exception('Unable to iterate throw '.get_called_class());
                
                $tar = $class;
                --$i;
            }
            
            for( ; $i < $length; $i++)
            {
                if(NULL === ($opt = $args[$i]))
                    continue;
                
                foreach($opt as $key => $value)
                {
                    if(is_array($tar))
                    {
                        if(TRUE === $rec && is_array($value) && isset($tar[$key]) && is_array($tar[$key]))
                        {
                            $tar[$key] = static::extend($rec, $tar[$key], $value);
                            continue;
                        }
                        
                        if(is_object($value))
                        {
                            //$tar[$key] = TRUE === $rec ? clone $value : $value;
                            $tar[$key] = $value;
                            continue;
                        }
                        
                        $tar[$key] = $opt[$key];
                        continue;
                    }
                    
                    if(is_object($tar))
                    {
                        if(TRUE === $rec && is_array($value) && isset($tar->$key) && is_array($tar->$key))
                        {
                            $tar->$key = static::extend($rec, $tar->$key, $value);
                            continue;
                        }
                        
                        if(is_object($value))
                        {
                            //$tar[$key] = TRUE === $rec ? clone $value : $value;
                            $tar->$key = $value;
                            continue;
                        }
                        
                        $tar->$key = $opt[$key];
                        continue;
                    }
                    
                    if(is_string($tar))
                    {
                        if(isset(self::$__env[$class][$key]))
                        {
                            static::env([$key => $value]);
                            continue;
                        }
                        
                        if(TRUE === $rec && is_array($value) && isset(static::${$key}) && is_array(static::${$key}))
                        {
                            static::${$key} = static::extend($rec, static::${$key}, $value);
                            continue;
                        }
                        
                        if(is_object($value))
                        {
                            //static::${$key} = TRUE === $rec ? clone $value : $value;
                            static::${$key} = $value;
                            continue;
                        }
                        
                        static::${$key} = $opt[$key];
                    }
                }
            }
            
            return $tar;
        }
        
        public static function __callstatic($__name, array $__parameters = [])
        {
            if(FALSE === static::Core_StaticObject_tMethod_exists($__name))
                throw new \Exception(get_called_class().'::'.$__name.'() is not a function.');
                
            return static::Core_StaticObject_tMethod_emit($__name, $__parameters);
        }
        
        public static function to($__format, array $__options = [])
        {
            $__options +=
            [
                'handlers'  => []
            ];
            
            return static::Core_StaticObject_tTo_emit($__format, [$__options]);
        }
        
        protected static function toString(array $__options = [])
        {
            return get_called_class();
        }
        
        protected static function toArray(array $__options = [])
        {
            $__options +=
            [
                'filter'    => function($__propertyName, $__value)
                {
                    return !(substr($__propertyName, 0, 2) === '__');
                }
            ];
            
            $props = [];
            $lookup = $class = get_called_class();
            
            do
            {
                foreach((new \ReflectionClass($lookup))->getStaticProperties() as $property => $value)
                {
                    // normalize $space[ClassName] => $data to $space => $data
                    if(isset(self::${$property})
                    && is_array(self::${$property})
                    && in_array($property, ['__initConfig', '__env'])
                    && isset(self::${$property}[$class]))
                        $value = self::${$property}[$class];
                    
                    $props[$property] = (is_array($value) && TRUE === isset($props[$property]))
                        ? array_merge($value, $props[$property])
                        : $value;
                }
            }
            while($lookup = get_parent_class($lookup));
            
            $result = [];
            
            foreach($props as $property => $value)
            {
                if(is_callable($__options['filter'])
                && FALSE === $__options['filter']($property, $value))
                    continue;
                
                switch(true):
                    case is_array($value):
                    case (!is_object($property)):
                        $result[$property] = $value;
                        break;
                    case (isset($__options['handlers'][$class = get_class($value)])):
                        $result[$property] = $__options['handlers'][$class]($value);
                        break;
                    case (method_exists($value, 'to')):
                        $result[$property] = $value->to('array', $__options);
                        break;
                    case ($vars = get_object_vars($value)):
                        $result[$property] = $vars;
                        break;
                    case (method_exists($value, '__toString')):
                        $result[$property] = (string) $value;
                        break;
                    default:
                        $result[$property] = $value;
                        break;
                endswitch;
            }
            
            return [$class => $result];
        }
    }

Comments