Skip to content

Instantly share code, notes, and snippets.

@OJezu
Created August 28, 2017 10:05
Show Gist options
  • Save OJezu/0d8f6db59aa77dcd44589b5f306c82a2 to your computer and use it in GitHub Desktop.
Save OJezu/0d8f6db59aa77dcd44589b5f306c82a2 to your computer and use it in GitHub Desktop.
<?php
namespace OJezu\FormatResponseBundle\Annotation\Controller;
/**
* @Annotation
*/
class FormatResponse
{
}
<?php
namespace OJezu\FormatResponseBundle\Listener;
use Doctrine\Common\Annotations\Reader;
use OJezu\FormatResponseBundle\Annotation\Controller\FormatResponse;
use OJezu\Common\Exception\BaseException;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ControllerResolver;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Event\KernelEvent;
use Symfony\Component\HttpKernel\Exception\HttpException;
class FormatResponseAnnotationListener
{
/**
* @var Reader
*/
private $reader;
/**
* @var ControllerResolver
*/
private $controllerResolver;
/**
* @param Reader $reader
* @param ControllerResolver $controllerResolver
*/
public function __construct(Reader $reader, ControllerResolver $controllerResolver)
{
$this->reader = $reader;
$this->controllerResolver = $controllerResolver;
}
/**
* @param GetResponseForExceptionEvent $responseEvent
*/
public function onResponseExceptionEvent(GetResponseForExceptionEvent $responseEvent)
{
$exception = $responseEvent->getException();
if ($this->isActionAnnotated($responseEvent)) {
if ($exception instanceof BaseException) {
// this response will pass through onResponseEvent too
$responseEvent->setResponse($exception->response());
} elseif ($exception instanceof HttpException) {
$responseEvent->setResponse(new Response(json_encode([
'code' => $exception->getStatusCode(),
'error' => [
'messageId' => 'http-status.'.$exception->getStatusCode(),
'message' => $exception->getMessage(),
'data' => [],
],
]), 200, ['X-Status-Code' => 200]));
}
}
}
/**
* @param GetResponseForControllerResultEvent $responseEvent
*/
public function onControllerResultEvent(GetResponseForControllerResultEvent $responseEvent)
{
if($this->isActionAnnotated($responseEvent)) {
$responseEvent->setControllerResult([
'code' => 200,
'response' => $responseEvent->getControllerResult(),
]);
}
}
/**
* @param FilterResponseEvent $responseEvent
*/
public function onResponseEvent(FilterResponseEvent $responseEvent)
{
if($this->isActionAnnotated($responseEvent)) {
$response = $responseEvent->getResponse();
if ($response instanceof RedirectResponse) {
$responseEvent->setResponse(new Response(json_encode([
'code' => $response->getStatusCode(),
'redirect' => [
'url' => $response->getTargetUrl(),
],
]), 200));
}
}
}
/**
* @param KernelEvent $responseEvent
*
* @return bool
*/
private function isActionAnnotated(KernelEvent $responseEvent) : bool
{
$hasAnnotation = false;
$callableController = $this->controllerResolver->getController($responseEvent->getRequest());
if ($callableController) {
$classReflection = new \ReflectionClass($callableController[0]);
$hasAnnotation = (bool)$this->reader->getClassAnnotation($classReflection, FormatResponse::class);
if (!$hasAnnotation) {
$methodReflection = $classReflection->getMethod($callableController[1]);
$hasAnnotation = (bool)$this->reader->getMethodAnnotation($methodReflection, FormatResponse::class);
}
}
return $hasAnnotation;
}
}
ojezu.format_response.listener.format_response:
class: 'OJezu\FormatResponseBundle\Listener\FormatResponseAnnotationListener'
arguments:
- '@annotation_reader'
- '@controller_resolver'
tags:
- name: 'kernel.event_listener'
event: 'kernel.view'
method: 'onControllerResultEvent'
priority: 110
- name: 'kernel.event_listener'
event: 'kernel.response'
method: 'onResponseEvent'
priority: 100
- name: 'kernel.event_listener'
event: 'kernel.exception'
method: 'onResponseExceptionEvent'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment