| 1 |  |  | <?php declare(strict_types = 1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | namespace Venta\Container; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | use Closure; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | use InvalidArgumentException; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | use ReflectionFunction; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | use ReflectionFunctionAbstract; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | use ReflectionMethod; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  |  * Class Invokable | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |  * @package Venta\Container | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | class Invokable | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |      * @var callable | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  |     private $callable; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |      * @var ReflectionFunctionAbstract | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  |     private $reflection; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |      * ReflectedCallable constructor. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |      * @param callable|ReflectionFunctionAbstract $callable | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 33 |  |  |      */ | 
            
                                                                        
                            
            
                                    
            
            
                | 34 | 53 |  |     public function __construct($callable) | 
            
                                                                        
                            
            
                                    
            
            
                | 35 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 36 | 53 |  |         if ($callable instanceof ReflectionFunctionAbstract) { | 
            
                                                                        
                            
            
                                    
            
            
                | 37 | 15 |  |             $this->callable = $this->reflectionCallable($callable); | 
            
                                                                        
                            
            
                                    
            
            
                | 38 | 15 |  |             $this->reflection = $callable; | 
            
                                                                        
                            
            
                                    
            
            
                | 39 |  |  |         } else { | 
            
                                                                        
                            
            
                                    
            
            
                | 40 | 45 |  |             $this->callable = $this->normalizeCallable($callable); | 
            
                                                                        
                            
            
                                    
            
            
                | 41 |  |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 42 | 46 |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |      * @return callable | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 | 40 |  |     public function callable() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 | 40 |  |         return $this->callable; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |      * @return bool | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 | 33 |  |     public function isFunction(): bool | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 | 33 |  |         return !is_array($this->callable); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |      * @return ReflectionFunctionAbstract|ReflectionMethod|ReflectionFunction | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 | 33 |  |     public function reflection(): ReflectionFunctionAbstract | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 | 33 |  |         if (empty($this->reflection)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 | 25 |  |             $this->reflection = $this->isFunction() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 | 11 |  |                 ? new ReflectionFunction($this->callable) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 | 14 |  |                 : new ReflectionMethod($this->callable[0], $this->callable[1]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 | 33 |  |         return $this->reflection; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |      * @param $callable | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |      * @return callable | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |      * @throws InvalidArgumentException | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 | 45 |  |     private function normalizeCallable($callable) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 | 45 |  |         if (is_object($callable)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 | 14 |  |             if ($callable instanceof Closure) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 | 9 |  |                 return $callable; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |             } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 | 5 |  |                 if (!method_exists($callable, '__invoke')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 | 1 |  |                     throw new InvalidArgumentException('Invalid callable provided.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |                 // Callable object is an instance with magic __invoke() method. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 | 4 |  |                 return [$callable, '__invoke']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 | 31 |  |         if (is_string($callable)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |             // Existing function is always callable. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 | 20 |  |             if (function_exists($callable)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 | 5 |  |                 return $callable; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 | 15 |  |             if (method_exists($callable, '__invoke')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |                 // We allow to call class by name if `__invoke()` method is implemented. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 | 2 |  |                 return [$callable, '__invoke']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 | 13 |  |             if (strpos($callable, '::') !== false) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |                 // Replace "ClassName::methodName" string with ["ClassName", "methodName"] array. | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 | 10 |  |                 $callable = explode('::', $callable); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |         // Is correct callable array. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 | 24 |  |         if (is_array($callable) && isset($callable[0], $callable[1]) && method_exists($callable[0], $callable[1])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 | 18 |  |             return $callable; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 | 6 |  |         throw new InvalidArgumentException('Invalid callable provided.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |      * @param ReflectionFunctionAbstract $reflection | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |      * @return array|Closure|string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |      * @throws InvalidArgumentException | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 | 15 |  |     private function reflectionCallable(ReflectionFunctionAbstract $reflection) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 | 15 |  |         if ($reflection instanceof ReflectionMethod) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 | 15 |  |             return [$reflection->class, $reflection->name]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |         if ($reflection instanceof ReflectionFunction) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |             return $reflection->isClosure() ? $reflection->getClosure() : $reflection->name; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |         throw new InvalidArgumentException('Invalid callable provided.'); | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 132 |  |  |     } | 
            
                                                        
            
                                    
            
            
                | 133 |  |  | } | 
            
                        
This check looks for the generic type
arrayas a return type and suggests a more specific type. This type is inferred from the actual code.