<?php
namespace GC\SanityBundle\EventListener;
use GC\SanityBundle\ESIAdapter;
use GC\SanityBundle\ControllerResult;
use GC\SanityBundle\Configuration\ExplicitHTTPCacheLayer;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpFoundation\Response;
class ResponseListener implements EventSubscriberInterface
{
protected $esi;
protected $httpCacheLayer;
protected $lastModified;
public function __construct( ESIAdapter $esi )
{
$this->esi = $esi;
}
public static function getSubscribedEvents()
{
return array(
KernelEvents::VIEW => array('onKernelView', 128),
KernelEvents::RESPONSE => array('onKernelResponse'),
);
}
/**
* @param GetResponseForControllerResultEvent $event A GetResponseForControllerResultEvent instance
*/
public function onKernelView(ViewEvent $event)
{
$request = $event->getRequest();
$controllerResult = $event->getControllerResult();
$this->httpCacheLayer = $request->attributes->get('_http_cache_layer');
if($controllerResult instanceOf ControllerResult){
$this->lastModified = $controllerResult->getLatestDateTime();
if( !$this->httpCacheLayer )
$this->httpCacheLayer = new ExplicitHTTPCacheLayer([]);
if( !$controllerResult->hasResult() ){
if( $controllerResult->throwOnNoResult() )
throw new NotFoundHttpException;
if( $controllerResult->emptyResponseOnNoResult() )
$event->setResponse( new Response );
return;
}
} else if ($this->httpCacheLayer) { // just a twig template, use git date or default
$this->lastModified = $this->esi->getBaseLastModified();
}
if( $this->lastModified ) {
if( $this->esi->getProductionMode() ){
$response = new Response;
$response->setLastModified( $this->lastModified );
if ($response->isNotModified( $request )){
$event->setResponse( $response );
return;
}
}
if($controllerResult instanceOf ControllerResult){ // fetch and hydrate the objects
$result = $controllerResult->getResult();
$event->setControllerResult($result + [
'_controller_result' => [
'name' => $controllerResult->getName(),
'last_modified' => $this->lastModified,
'result' => $result
]
]);
}
}
}
/**
* @param FilterResponseEvent $event A FilterResponseEvent instance
*/
public function onKernelResponse(ResponseEvent $event)
{
if($this->lastModified && $this->httpCacheLayer){
$response = $event->getResponse();
$response->setLastModified( $this->lastModified );
$response->headers->set('x-esi-last-modified', $this->lastModified->format('r'));
if( $this->esi->getProductionMode() ){
$maxAge = $this->httpCacheLayer->getMaxAge();
if(!is_null($maxAge))
$response->setMaxAge( $maxAge );
$response->setSharedMaxAge( $this->httpCacheLayer->getSharedMaxAge() );
}
}
}
}