123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- <?php
- namespace Illuminate\Support;
- use ReflectionClass;
- use ReflectionEnum;
- use ReflectionMethod;
- use ReflectionNamedType;
- use ReflectionUnionType;
- class Reflector
- {
- /**
- * This is a PHP 7.4 compatible implementation of is_callable.
- *
- * @param mixed $var
- * @param bool $syntaxOnly
- * @return bool
- */
- public static function isCallable($var, $syntaxOnly = false)
- {
- if (! is_array($var)) {
- return is_callable($var, $syntaxOnly);
- }
- if (! isset($var[0], $var[1]) || ! is_string($var[1] ?? null)) {
- return false;
- }
- if ($syntaxOnly &&
- (is_string($var[0]) || is_object($var[0])) &&
- is_string($var[1])) {
- return true;
- }
- $class = is_object($var[0]) ? get_class($var[0]) : $var[0];
- $method = $var[1];
- if (! class_exists($class)) {
- return false;
- }
- if (method_exists($class, $method)) {
- return (new ReflectionMethod($class, $method))->isPublic();
- }
- if (is_object($var[0]) && method_exists($class, '__call')) {
- return (new ReflectionMethod($class, '__call'))->isPublic();
- }
- if (! is_object($var[0]) && method_exists($class, '__callStatic')) {
- return (new ReflectionMethod($class, '__callStatic'))->isPublic();
- }
- return false;
- }
- /**
- * Get the class name of the given parameter's type, if possible.
- *
- * @param \ReflectionParameter $parameter
- * @return string|null
- */
- public static function getParameterClassName($parameter)
- {
- $type = $parameter->getType();
- if (! $type instanceof ReflectionNamedType || $type->isBuiltin()) {
- return;
- }
- return static::getTypeName($parameter, $type);
- }
- /**
- * Get the class names of the given parameter's type, including union types.
- *
- * @param \ReflectionParameter $parameter
- * @return array
- */
- public static function getParameterClassNames($parameter)
- {
- $type = $parameter->getType();
- if (! $type instanceof ReflectionUnionType) {
- return array_filter([static::getParameterClassName($parameter)]);
- }
- $unionTypes = [];
- foreach ($type->getTypes() as $listedType) {
- if (! $listedType instanceof ReflectionNamedType || $listedType->isBuiltin()) {
- continue;
- }
- $unionTypes[] = static::getTypeName($parameter, $listedType);
- }
- return array_filter($unionTypes);
- }
- /**
- * Get the given type's class name.
- *
- * @param \ReflectionParameter $parameter
- * @param \ReflectionNamedType $type
- * @return string
- */
- protected static function getTypeName($parameter, $type)
- {
- $name = $type->getName();
- if (! is_null($class = $parameter->getDeclaringClass())) {
- if ($name === 'self') {
- return $class->getName();
- }
- if ($name === 'parent' && $parent = $class->getParentClass()) {
- return $parent->getName();
- }
- }
- return $name;
- }
- /**
- * Determine if the parameter's type is a subclass of the given type.
- *
- * @param \ReflectionParameter $parameter
- * @param string $className
- * @return bool
- */
- public static function isParameterSubclassOf($parameter, $className)
- {
- $paramClassName = static::getParameterClassName($parameter);
- return $paramClassName
- && (class_exists($paramClassName) || interface_exists($paramClassName))
- && (new ReflectionClass($paramClassName))->isSubclassOf($className);
- }
- /**
- * Determine if the parameter's type is a Backed Enum with a string backing type.
- *
- * @param \ReflectionParameter $parameter
- * @return bool
- */
- public static function isParameterBackedEnumWithStringBackingType($parameter)
- {
- if (! $parameter->getType() instanceof ReflectionNamedType) {
- return false;
- }
- $backedEnumClass = $parameter->getType()?->getName();
- if (is_null($backedEnumClass)) {
- return false;
- }
- if (enum_exists($backedEnumClass)) {
- $reflectionBackedEnum = new ReflectionEnum($backedEnumClass);
- return $reflectionBackedEnum->isBacked()
- && $reflectionBackedEnum->getBackingType()->getName() == 'string';
- }
- return false;
- }
- }
|