<?php declare(strict_types=1);
namespace App\Framework\EventListener;
use App\Framework\Serializer\APISerializerGroup;
use ReflectionMethod;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Serializer\SerializerInterface;
class APISerializerEventListener
{
private SerializerInterface $serializer;
public function __construct(SerializerInterface $serializer)
{
$this->serializer = $serializer;
}
public function onKernelController(ControllerEvent $event): void
{
$request = $event->getRequest();
if ($event->getRequestType() !== HttpKernelInterface::MASTER_REQUEST) {
return;
}
$controller = $event->getController();
$reflection = new ReflectionMethod($controller[0], $controller[1]);
$attrs = $reflection->getAttributes(APISerializerGroup::class);
// TODO: Anyway to prevent multiple of one attribute?
$groups = [];
foreach ($attrs as $attr) {
$attrInstance = $attr->newInstance();
foreach ($attrInstance->groups as $g) {
$groups[] = $g;
}
}
if (count($groups) === 0) {
$groups[] = 'default';
}
$request->attributes->set('api_serializer_groups', $groups);
}
public function onKernelView(ViewEvent $event): void
{
$request = $event->getRequest();
if ($event->getRequestType() !== HttpKernelInterface::MASTER_REQUEST) {
return;
}
// Normalize the result
$groups = $request->attributes->get('api_serializer_groups');
$result = $this->serializer->normalize($event->getControllerResult(), null, ['groups' => $groups]);
// Convert normalized result to proper Response
if (in_array('application/json', $request->getAcceptableContentTypes(), true)) {
// Convert to a json response
$response = new JsonResponse($result);
$event->setResponse($response);
} else {
// Convert to a html response
$content = json_encode($result, JSON_PRETTY_PRINT);
$response = new Response();
$response->setContent(
'<html><body><pre class="prettyprint lang-json">' .
htmlspecialchars($content) .
'</pre>' .
'<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>' .
'</body></html>'
);
$event->setResponse($response);
}
}
}