src/EventSubscriber/CacheSubscriber.php line 94

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber;
  3. use App\Entity\Page;
  4. use App\Repository\PageRepository;
  5. use App\Service\CacheService;
  6. use DateTime;
  7. use Doctrine\ORM\NonUniqueResultException;
  8. use Exception;
  9. use Psr\Cache\CacheException;
  10. use Psr\Cache\InvalidArgumentException;
  11. use Symfony\Component\Cache\Adapter\TagAwareAdapter;
  12. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  13. use Symfony\Component\HttpFoundation\Request;
  14. use Symfony\Component\HttpFoundation\RequestStack;
  15. use Symfony\Component\HttpFoundation\Response;
  16. use Symfony\Component\HttpKernel\Event\RequestEvent;
  17. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  18. use Symfony\Component\HttpKernel\KernelEvents;
  19. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  20. use function dd;
  21. class CacheSubscriber implements EventSubscriberInterface
  22. {
  23.     protected TagAwareAdapter $cache;
  24.     /**
  25.      * CacheSubscriber constructor.
  26.      */
  27.     public function __construct(
  28.         protected string $env,
  29.         protected CacheService $cacheService,
  30.         protected PageRepository $pageRepository,
  31.         protected RequestStack $requestStack,
  32.         protected TokenStorageInterface $tokenStorage,
  33.         private string $masterLocale
  34.     ) {
  35.         $this->cache $this->cacheService->getAdapter();
  36.     }
  37.     /**
  38.      * @throws InvalidArgumentException
  39.      * @throws NonUniqueResultException
  40.      */
  41.     public function onKernelRequest(RequestEvent $event): void
  42.     {
  43.         $request $event->getRequest();
  44.         if (== $event->getRequestType() && $this->shouldUseCache($request)) {
  45.             $routeParams $request->attributes->get('_route_params');
  46.             if (isset($routeParams['path'])) {
  47.                 $cachingLevel   $this->pageRepository->getCachingLevelByPath($routeParams['path'], $routeParams['_locale'] ?? null);
  48.                 $cacheKey       null;
  49.                 $url            = isset($routeParams['_locale']) ? $routeParams['_locale'] . '/' $routeParams['path'] : $routeParams['path'];
  50.                 if ($url == "") {
  51.                     $url "home";
  52.                 }
  53.                 switch ($cachingLevel['cachingLevel']) {
  54.                     case Page::CACHING_BASIC:
  55.                         if (!$request->query->count()) {
  56.                             $cacheKey $this->cacheService->getCacheKey($url);
  57.                         }
  58.                         break;
  59.                     case Page::CACHING_SIMPLE:
  60.                         $cacheKey $this->cacheService->getCacheKey($url);
  61.                         break;
  62.                     case Page::CACHING_AGGRESSIVE:
  63.                         $cacheKey $this->cacheService->getCacheKey($url$request->query->all());
  64.                         break;
  65.                 }
  66.                 if ($cacheKey) {
  67.                     $data $this->cache->getItem($cacheKey);
  68.                     if ($data->isHit()) {
  69.                         $response = new Response($data->get());
  70.                         $response->headers->set('cached-data', ['true']);
  71.                         $event->setResponse($response);
  72.                     }
  73.                 }
  74.             }
  75.         }
  76.     }
  77.     /**
  78.      * @throws CacheException
  79.      * @throws InvalidArgumentException
  80.      * @throws NonUniqueResultException
  81.      */
  82.     public function onKernelResponse(ResponseEvent $event): void
  83.     {
  84.         $request  $event->getRequest();
  85.         $response $event->getResponse();
  86.         if (== $event->getRequestType() && Response::HTTP_OK == $response->getStatusCode() && $this->shouldUseCache($request) && !$response->headers->has('cached-data')) {
  87.             $routeParams $request->attributes->get('_route_params');
  88.             if (isset($routeParams['path'])) {
  89.                 /** @var Page $page */
  90.                 $page $this->pageRepository->findOneByPath($routeParams['path'], $routeParams['_locale'] ?? null);
  91.                 if (null !== $page && $page->isVisible() && $page->canBeSeen()) {
  92.                     switch ($page->getCachingLevel()) {
  93.                         case Page::CACHING_BASIC:
  94.                             if (!$request->query->count()) {
  95.                                 $response $this->cachePage($response$page);
  96.                             }
  97.                             break;
  98.                         case Page::CACHING_SIMPLE:
  99.                             $response $this->cachePage($response$page);
  100.                             break;
  101.                         case Page::CACHING_AGGRESSIVE:
  102.                             $response $this->cachePage($response$page$request->query->all());
  103.                             break;
  104.                     }
  105.                 }
  106.             }
  107.             $event->setResponse($response);
  108.         }
  109.     }
  110.     /**
  111.      * @throws CacheException
  112.      * @throws InvalidArgumentException
  113.      * @throws Exception
  114.      */
  115.     public function cachePage(Response $responsePage $page, array $queryParams = []): Response
  116.     {
  117.         if ($page->getCurrentPath(false)->getLocale() == $this->masterLocale) {
  118.             $cacheKey $this->cacheService->getCacheKey($page->getCurrentPath(true) == "" "home" $page->getCurrentPath(true), $queryParams);
  119.         } else {
  120.             $cacheKey $this->cacheService->getCacheKey($page->getCurrentPath(false)->getLocale() . '/' $page->getCurrentPath(true), $queryParams);
  121.         }
  122.         $data     $this->cache->getItem($cacheKey);
  123.         $view     $response->getContent();
  124.         $ttl $this->cacheService->handleTtl();
  125.         $data->expiresAfter($ttl);
  126.         $data->set($view);
  127.         $data->tag($this->cacheService->getTags($page));
  128.         $this->cache->save($data);
  129.         $response->setCache([
  130.             'etag'          => md5($cacheKey),
  131.             'last_modified' => new DateTime(),
  132.             'max_age'       => $ttl,
  133.             's_maxage'      => $ttl,
  134.             'public'        => true,
  135.         ]);
  136.         return $response;
  137.     }
  138.     protected function shouldUseCache(Request $request): bool
  139.     {
  140.         return
  141.             (!$this->tokenStorage->getToken() || !$this->tokenStorage->getToken()->getUser() || 'anon.' == $this->tokenStorage->getToken()->getUser())
  142.             && 'GET' == $request->getMethod()
  143.             && $this->cacheService->isEnabled()
  144.             && 'prod' == strtolower($this->env);
  145.     }
  146.     public static function getSubscribedEvents(): array
  147.     {
  148.         return [
  149.             KernelEvents::REQUEST  => [['onKernelRequest'1]],
  150.             KernelEvents::RESPONSE => [['onKernelResponse'2]],
  151.         ];
  152.     }
  153. }