<?php
namespace App\Listener;
use App\Entity\User;
use App\Services\CacheService;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\KernelEvent;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\Security\Core\Security;
class CacheListener
{
/**
* @var CacheService
*/
private $cacheService;
/**
* @var array
*/
private $config;
/**
* @var Security
*/
private $security;
/**
* @var array
*/
private $cacheable = [];
/**
* CacheListener constructor.
* @param CacheService $cacheService
* @param array $config
* @param Security $security
*/
public function __construct(CacheService $cacheService, array $config, Security $security)
{
$this->cacheService = $cacheService;
$this->config = $config;
$this->security = $security;
foreach ($this->config as $key => $item) {
if ($item === null) {
$this->config[$key] = [];
}
}
}
/**
* Overwrites principal
* @param string $route
* @return array
*/
private function getRouteConfig(string $route)
{
return array_merge($this->config['config'], $this->config[$route]);
}
public function onKernelRequest(RequestEvent $event)
{
$route = $event->getRequest()->get('_route');
if (isset($this->config[$route])) {
$_config = $this->getRouteConfig($route);
$user = $this->security->getUser();
if (isset($_config['roles']) || isset($_config['reverse_roles'])) {
$roles = ($user instanceof User) ? $user->getRoles() : [];
$inclusions = $_config['roles'] ?? [];
$exclusions = $_config['reverse_roles'] ?? [];
//if the route has an inclusive roles list or an exclusive roles list
//if inclusions are detected and the role is not in the list
//or if it has exclusions and the role is in the list
if ((!empty($inclusions) && empty(array_intersect($roles, $inclusions))) ||
(!empty($exclusions) && !empty(array_intersect($roles, $exclusions)))) {
return;
}
}
$content = $this->cacheService->getCacheRoute($route, $_config, $event->getRequest());
if (!empty($content)) {
$response = new JsonResponse($content, 200, [], true);
$event->setResponse($response);
$event->stopPropagation();
} else {
$this->cacheable[$route] = $_config;
}
}
}
public function onKernelResponse(ResponseEvent $event)
{
$route = $event->getRequest()->get('_route', 'empty');
if (isset($this->cacheable[$route])) {
$this->cacheService->cacheRoute($route, $this->cacheable[$route], $event->getRequest(), $event->getResponse());
}
}
}