Last active
October 1, 2020 18:45
-
-
Save Loupax/fa011ac275b0b3f71ef0d76fdaf00449 to your computer and use it in GitHub Desktop.
SomethingLikeValueResolver
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace App\Listener; | |
use App\MyDto; | |
use Symfony\Component\HttpFoundation\JsonResponse; | |
use Symfony\Component\HttpFoundation\Response; | |
use Symfony\Component\HttpKernel\Event\ControllerEvent; | |
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; | |
use Symfony\Component\Validator\Validator\ValidatorInterface; | |
class ControllerListener | |
{ | |
private $validator; | |
private $denormalizer; | |
public function __construct( | |
DenormalizerInterface $denormalizer, | |
ValidatorInterface $validator | |
) | |
{ | |
$this->denormalizer = $denormalizer; | |
$this->validator = $validator; | |
} | |
public function onKernelController(ControllerEvent $event): void | |
{ | |
$argName = false; | |
// 1: Check if the current controller expects a MyDto as an argument | |
// 2: If it does, create it and inject it in the request so that the controller can have access to it | |
// 2.5: If the DTO is invalid, return intercept the request and just return a Bad Request response | |
/** @var \ReflectionParameter $reflectionParameter */ | |
foreach ($this->extractCallableParams($event->getController()) as $reflectionParameter) { | |
if ((string)$reflectionParameter->getType() === MyDto::class) { | |
$argName = $reflectionParameter->getName(); | |
break; | |
} | |
} | |
if ($argName === false) { | |
return; | |
} | |
$request = $event->getRequest(); | |
$dto = $this->denormalizer->denormalize($request->query->all(), MyDto::class); | |
$validationErrors = $this->validator->validate($dto); | |
if ($validationErrors->count() > 0) { | |
$event->setController(function () use ($validationErrors) { | |
return new JsonResponse( | |
[ | |
'errors' => array_map(function($err){return $err->getMessage();}, $validationErrors), | |
], | |
Response::HTTP_BAD_REQUEST | |
); | |
}); | |
$event->stopPropagation(); | |
return; | |
} | |
$event->getRequest()->attributes->set($argName, $dto); | |
} | |
private function extractCallableParams(callable $callable): array | |
{ | |
if ($callable instanceof Closure || is_object($callable)) { | |
$name = ''; | |
is_callable($callable, false, $name); | |
if (strpos($name, '::') !== false) { | |
$r = new \ReflectionMethod($name); | |
} else { | |
$r = new \ReflectionFunction($name); | |
} | |
} else { | |
$r = new \ReflectionFunction($callable); | |
} | |
return $r->getParameters(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment