ArgumentMetadataFactory.php 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\HttpKernel\ControllerMetadata;
  11. /**
  12. * Builds {@see ArgumentMetadata} objects based on the given Controller.
  13. *
  14. * @author Iltar van der Berg <kjarli@gmail.com>
  15. */
  16. final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
  17. {
  18. public function createArgumentMetadata(string|object|array $controller, ?\ReflectionFunctionAbstract $reflector = null): array
  19. {
  20. $arguments = [];
  21. $reflector ??= new \ReflectionFunction($controller(...));
  22. $controllerName = $this->getPrettyName($reflector);
  23. foreach ($reflector->getParameters() as $param) {
  24. $attributes = [];
  25. foreach ($param->getAttributes() as $reflectionAttribute) {
  26. if (class_exists($reflectionAttribute->getName())) {
  27. $attributes[] = $reflectionAttribute->newInstance();
  28. }
  29. }
  30. $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param), $param->isVariadic(), $param->isDefaultValueAvailable(), $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null, $param->allowsNull(), $attributes, $controllerName);
  31. }
  32. return $arguments;
  33. }
  34. /**
  35. * Returns an associated type to the given parameter if available.
  36. */
  37. private function getType(\ReflectionParameter $parameter): ?string
  38. {
  39. if (!$type = $parameter->getType()) {
  40. return null;
  41. }
  42. $name = $type instanceof \ReflectionNamedType ? $type->getName() : (string) $type;
  43. return match (strtolower($name)) {
  44. 'self' => $parameter->getDeclaringClass()?->name,
  45. 'parent' => get_parent_class($parameter->getDeclaringClass()?->name ?? '') ?: null,
  46. default => $name,
  47. };
  48. }
  49. private function getPrettyName(\ReflectionFunctionAbstract $r): string
  50. {
  51. $name = $r->name;
  52. if ($r instanceof \ReflectionMethod) {
  53. return $r->class.'::'.$name;
  54. }
  55. if ($r->isAnonymous() || !$class = $r->getClosureCalledClass()) {
  56. return $name;
  57. }
  58. return $class->name.'::'.$name;
  59. }
  60. }