/** * @param callable $callable * * @return \ReflectionFunctionAbstract * * @throws NotCallableException * * TODO Use the `callable` type-hint once support for PHP 5.4 and up. */ public static function create($callable) { // Closure if ($callable instanceof \Closure) { return new \ReflectionFunction($callable); } // Array callable if (is_array($callable)) { list($class, $method) = $callable; if (!method_exists($class, $method)) { throw NotCallableException::fromInvalidCallable($callable); } return new \ReflectionMethod($class, $method); } // Callable object (i.e. implementing __invoke()) if (is_object($callable) && method_exists($callable, '__invoke')) { return new \ReflectionMethod($callable, '__invoke'); } // Callable class (i.e. implementing __invoke()) if (is_string($callable) && class_exists($callable) && method_exists($callable, '__invoke')) { return new \ReflectionMethod($callable, '__invoke'); } // Standard function if (is_string($callable) && function_exists($callable)) { return new \ReflectionFunction($callable); } throw new NotCallableException(sprintf('%s is not a callable', is_string($callable) ? $callable : 'Instance of ' . get_class($callable))); }
/** * @param callable|string|array $callable * @return callable * @throws NotCallableException */ private function resolveFromContainer($callable) { // Shortcut for a very common use case if ($callable instanceof \Closure) { return $callable; } $isStaticCallToNonStaticMethod = false; // If it's already a callable there is nothing to do if (is_callable($callable)) { $isStaticCallToNonStaticMethod = $this->isStaticCallToNonStaticMethod($callable); if (!$isStaticCallToNonStaticMethod) { return $callable; } } // The callable is a container entry name if (is_string($callable)) { try { return $this->container->get($callable); } catch (NotFoundException $e) { throw NotCallableException::fromInvalidCallable($callable, true); } } // The callable is an array whose first item is a container entry name // e.g. ['some-container-entry', 'methodToCall'] if (is_array($callable) && is_string($callable[0])) { try { // Replace the container entry name by the actual object $callable[0] = $this->container->get($callable[0]); return $callable; } catch (NotFoundException $e) { if ($isStaticCallToNonStaticMethod) { throw new NotCallableException(sprintf('Cannot call %s::%s() because %s() is not a static method and "%s" is not a container entry', $callable[0], $callable[1], $callable[1], $callable[0])); } throw new NotCallableException(sprintf('Cannot call %s on %s because it is not a class nor a valid container entry', $callable[1], $callable[0])); } } // Unrecognized stuff, we let it fail later return $callable; }