vendor/friendsofsymfony/rest-bundle/EventListener/ParamFetcherListener.php line 39

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of the FOSRestBundle package.
  4. *
  5. * (c) FriendsOfSymfony <http://friendsofsymfony.github.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 FOS\RestBundle\EventListener;
  11. use FOS\RestBundle\FOSRestBundle;
  12. use FOS\RestBundle\Request\ParamFetcherInterface;
  13. use Symfony\Component\HttpKernel\Event\ControllerEvent;
  14. /**
  15. * This listener handles various setup tasks related to the query fetcher.
  16. *
  17. * Setting the controller callable on the query fetcher
  18. * Setting the query fetcher as a request attribute
  19. *
  20. * @author Lukas Kahwe Smith <smith@pooteeweet.org>
  21. *
  22. * @internal
  23. */
  24. class ParamFetcherListener
  25. {
  26. private $paramFetcher;
  27. private $setParamsAsAttributes;
  28. public function __construct(ParamFetcherInterface $paramFetcher, bool $setParamsAsAttributes = false)
  29. {
  30. $this->paramFetcher = $paramFetcher;
  31. $this->setParamsAsAttributes = $setParamsAsAttributes;
  32. }
  33. public function onKernelController(ControllerEvent $event): void
  34. {
  35. $request = $event->getRequest();
  36. if (!$request->attributes->get(FOSRestBundle::ZONE_ATTRIBUTE, true)) {
  37. return;
  38. }
  39. $controller = $event->getController();
  40. if (is_callable($controller) && (is_object($controller) || is_string($controller)) && method_exists($controller, '__invoke')) {
  41. $controller = [$controller, '__invoke'];
  42. }
  43. $this->paramFetcher->setController($controller);
  44. $attributeName = $this->getAttributeName($controller);
  45. $request->attributes->set($attributeName, $this->paramFetcher);
  46. if ($this->setParamsAsAttributes) {
  47. $params = $this->paramFetcher->all();
  48. foreach ($params as $name => $param) {
  49. if ($request->attributes->has($name) && null !== $request->attributes->get($name)) {
  50. $msg = sprintf("ParamFetcher parameter conflicts with a path parameter '$name' for route '%s'", $request->attributes->get('_route'));
  51. throw new \InvalidArgumentException($msg);
  52. }
  53. $request->attributes->set($name, $param);
  54. }
  55. }
  56. }
  57. private function getAttributeName(callable $controller): string
  58. {
  59. list($object, $name) = $controller;
  60. $method = new \ReflectionMethod($object, $name);
  61. foreach ($method->getParameters() as $param) {
  62. if ($this->isParamFetcherType($param)) {
  63. return $param->getName();
  64. }
  65. }
  66. // If there is no typehint, inject the ParamFetcher using a default name.
  67. return 'paramFetcher';
  68. }
  69. private function isParamFetcherType(\ReflectionParameter $controllerParam): bool
  70. {
  71. $type = $controllerParam->getType();
  72. foreach ($type instanceof \ReflectionUnionType ? $type->getTypes() : [$type] as $type) {
  73. if (null === $type || $type->isBuiltin() || !$type instanceof \ReflectionNamedType) {
  74. continue;
  75. }
  76. $class = new \ReflectionClass($type->getName());
  77. if ($class->implementsInterface(ParamFetcherInterface::class)) {
  78. return true;
  79. }
  80. }
  81. return false;
  82. }
  83. }