Advertisement
fruffl

Invoker

Jan 13th, 2013
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 7.41 KB | None | 0 0
  1. <?PHP
  2.     NAMESPACE ILLI\Core;
  3.     USE ILLI\Core\Invoke\tMethod;
  4.     USE ILLI\Core\Invoke\tStatic;
  5.     USE ILLI\Core\Invoke\tCallable;
  6.     USE ILLI\Core\Invoke\tClass;
  7.     USE Closure;
  8.    
  9.     CLASS Invoke
  10.     {
  11.         USE tMethod
  12.         {
  13.             tMethod_emit AS public emitMethod;
  14.         }
  15.        
  16.         USE tStatic
  17.         {
  18.             tStatic_emit AS public emitStatic;
  19.         }
  20.        
  21.         USE tCallable
  22.         {
  23.             tCallable_emit AS public emitCallable;
  24.         }
  25.        
  26.         USE tClass
  27.         {
  28.             tClass_emit AS public emitClass;
  29.         }
  30.        
  31.         /**
  32.          * emit normalized invokable array
  33.          *
  34.          *  string          -> tClass_emit      -> new string()
  35.          *  string, array       -> tClass_emit      -> new string(array)
  36.          *
  37.          *  object, string      -> tMethod_emit     -> object->string()
  38.          *  object, string, array   -> tMethod_emit     -> object->string(array)
  39.          *
  40.          *  string, string      -> tStatic_emit     -> string::string()
  41.          *  string, string, array   -> tStatic_emit     -> string::string(array)
  42.          *
  43.          *  closure         -> tCallable_emit   -> closure()
  44.          *  closure, array      -> tCallable_emit   -> closure(array)
  45.          *  object, closure     -> tCallable_emit   -> closure() use (object)
  46.          *  object, closure, array  -> tCallable_emit   -> closure(args) use (object)
  47.          *  string, closure     -> tCallable_emit   -> static::closure()
  48.          *  string, closure, array  -> tCallable_emit   -> static::closure(array)
  49.          *
  50.          * @see normalize()
  51.          */
  52.         public static function emit()
  53.         {
  54.             $args = func_get_args();
  55.             if([] === $args)
  56.                 return NULL;
  57.                
  58.            
  59.             switch(count($args)):
  60.                 case 0:
  61.                     return NULL;
  62.                     break;
  63.                 case 1:
  64.                     switch(TRUE):
  65.                         // [classname]
  66.                         case is_string($args[0]):
  67.                             return static::tClass_emit($args[0]);
  68.                             break;
  69.                         // [closure]
  70.                         case is_object($args[0]):
  71.                             return static::tCallable_emit($args[0]);
  72.                             break;
  73.                     endswitch;
  74.                     break;
  75.                 case 2:
  76.                     switch(TRUE):
  77.                         // [classname, args]
  78.                         case is_string($args[0]) && is_array($args[1]):
  79.                             return static::tClass_emit($args[0], $args[1]);
  80.                             break;
  81.                         // [closure, args]
  82.                         case is_object($args[0]) && is_array($args[1]):
  83.                             return static::tCallable_emit($args[0], $args[1]);
  84.                             break;
  85.                         // [instance, methodname]
  86.                         case is_object($args[0]) && is_string($args[1]):
  87.                             return static::tMethod_emit($args[0], $args[1]);
  88.                             break;
  89.                         // [classname, methodname]
  90.                         case is_string($args[0]) && is_string($args[1]):
  91.                             return static::tStatic_emit($args[0], $args[1]);
  92.                             break;
  93.                         // [instance, closure]
  94.                         case is_object($args[0]) && is_object($args[1]):
  95.                             return static::tCallable_emit($args[1]);
  96.                             break;
  97.                         // [classname, closure]
  98.                         case is_string($args[0]) && is_object($args[1]):
  99.                             return static::tCallable_emit($args[1]);
  100.                             break;
  101.                     endswitch;
  102.                     break;
  103.                 case 3:
  104.                 default:
  105.                     switch(TRUE):
  106.                         // [instance, methodname, args]
  107.                         case is_object($args[0]) && is_string($args[1]) && is_array($args[2]):
  108.                             return static::tMethod_emit($args[0], $args[1], $args[2]);
  109.                             break;
  110.                         // [classname, methodname, args]
  111.                         case is_string($args[0]) && is_string($args[1]) && is_array($args[2]):
  112.                             return static::tStatic_emit($args[0], $args[1], $args[2]);
  113.                             break;
  114.                         // [instance, closure, args]
  115.                         case is_object($args[0]) && is_object($args[1]) && is_array($args[2]):
  116.                             return static::tCallable_emit($args[1], $args[2]);
  117.                             break;
  118.                         // [classname, closure, args]
  119.                         case is_string($args[0]) && is_object($args[1]) && is_array($args[2]):
  120.                             return static::tCallable_emit($args[1], $args[2]);
  121.                             break;
  122.                     endswitch;
  123.                     break;
  124.             endswitch;
  125.            
  126.             $type = [];
  127.             foreach($args as $arg)
  128.                 $type[] = getType($arg);
  129.                
  130.             throw new \Exception('No Handler defined for ['.implode(', ', $type).'].');
  131.         }
  132.        
  133.         /**
  134.          * @param array $__subject normalized callable array
  135.          * @see normalize()
  136.          */
  137.         public static function emitable($__subject)
  138.         {
  139.             if(FALSE === is_array($__subject))
  140.                 return FALSE;
  141.            
  142.             $length = count($__subject);
  143.             if($length < 1 || $length > 2)
  144.                 return FALSE;
  145.            
  146.             if($length === 1)
  147.             {
  148.                 if(is_object($__subject[0]))
  149.                 {
  150.                     return method_exists($__subject[0], '__invoke');
  151.                 }
  152.                 else
  153.                 if(is_string($__subject[0]))
  154.                 {
  155.                     return class_exists($__subject[0]);
  156.                 }
  157.                
  158.                 return false;
  159.             }
  160.            
  161.             if(is_object($__subject[0])
  162.             || (is_string($__subject[0]) && class_exists($__subject[0])))
  163.             {
  164.                 if(is_string($__subject[1]))
  165.                 {
  166.                     return method_exists($__subject[0], $__subject[1]);
  167.                 }
  168.             }
  169.            
  170.             return false;
  171.         }
  172.        
  173.         /**
  174.          * create delegatable array from
  175.          *  - 'class::method'       => string + string  => [string, string] => class::method()
  176.          *  - 'method' + target     => object + string  => [object, string] => target->method()
  177.          *  - 'class'           => string       => [string]     => new class
  178.          *
  179.          *  - [] + target           => object       => [object]     => target->__invoke()
  180.          *  - ['method'] + target       => object + string  => [object, method] => target->method()
  181.          *  - [instance, 'method']      => object + string  => [string, string] => instance->method()
  182.          *  - ['class', 'method']       => string + string  => [string, string] => class::method()
  183.          *  - ['class']         => string       => [string]     => new class
  184.          *
  185.          * convert misc handler-configs to callable address
  186.          *
  187.          * @param array|string|object $__subject callable array, class::method-string or closure
  188.          * @param object|string $__target fallback-instance or -class
  189.          * @return array
  190.          * @note bind $__target to [closure $__subject]
  191.          * @see emit()
  192.          */
  193.         public static function normalize($__subject, $__target)
  194.         {
  195.             // [\foo]
  196.             if(is_object($__subject)
  197.             && method_exists($__subject, '__invoke'))
  198.             {
  199.                 if($__subject instanceOf Closure)
  200.                 {
  201.                     if(NULL === $__target)
  202.                         return [$__subject];
  203.                        
  204.                     $__subject = is_string($__target)
  205.                         ? Closure::bind($__subject, NULL, get_class($__target))
  206.                         : Closure::bind($__subject, $__target, get_class($__target));
  207.                 }
  208.                
  209.                 return [$__target, $__subject];
  210.             }
  211.                
  212.             if(is_callable($__subject) && is_array($__subject) && count($__subject) === 2)
  213.                 return $__subject;
  214.                
  215.             // '\foo::bar' | '\foo' | 'bar'
  216.             if(is_string($__subject))
  217.             {
  218.                 $subject    = explode('::', $__subject);
  219.                 $length     = count($subject);
  220.                
  221.                 if($length === 2)
  222.                 {
  223.                     // ['foo', 'bar']
  224.                     return $subject;
  225.                 }
  226.                 else
  227.                 if($length === 1)
  228.                 {
  229.                     if(class_exists($subject[0]))
  230.                     {
  231.                         // ['foo']
  232.                         return $subject;
  233.                     }
  234.                     else
  235.                     {
  236.                         // ['bar']
  237.                         $__subject = $subject;
  238.                     }
  239.                 }
  240.             }
  241.            
  242.             // [\foo] | ['\foo'] | ['bar'] | ['\foo', 'bar'] | [\foo, 'bar']
  243.             if(is_array($__subject))
  244.             {
  245.                 // []
  246.                 if(!isset($__subject[0]))
  247.                     return [$__target]; // target->__invoke()
  248.                
  249.                 if(count($__subject) === 2)
  250.                     // ['\foo', 'bar'] | [\foo, 'bar']
  251.                     return $__subject;
  252.                
  253.                 // [\foo] | ['\foo'] | ['bar']
  254.                 if(count($__subject) === 1)
  255.                 {
  256.                     // [\foo]
  257.                     if(is_object($__subject[0]))
  258.                         return $__subject; // \foo()
  259.                    
  260.                     // ['\foo'] | ['bar']
  261.                     if(is_string($__subject[0]))
  262.                     {
  263.                         // ['\foo']
  264.                         if(class_exists($__subject[0]))
  265.                             return $__subject; // new foo
  266.                        
  267.                         // ['bar']
  268.                         return [$__target , $__subject[0]]; // target->bar()
  269.                     }
  270.                 }
  271.             }
  272.            
  273.             // \foo -> function[]{}/object -> [\foo]
  274.             return static::normalize([$__subject], $__target);
  275.         }
  276.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement