src/EventSubscriber/AppCacheSubscriber.php line 91

Open in your IDE?
  1. <?php
  2. /**
  3.  * @license SILK SOFTWARE HOUSE SP Z O O
  4.  */
  5. namespace App\EventSubscriber;
  6. use App\Annotation\AppCache;
  7. use Symfony\Component\HttpFoundation\Response;
  8. use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
  9. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  10. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  11. use Symfony\Component\HttpKernel\KernelEvents;
  12. use Doctrine\Common\Annotations\Reader;
  13. use ReflectionClass;
  14. use ReflectionException;
  15. use Symfony\Component\Security\Core\Security;
  16. use Symfony\Contracts\Cache\TagAwareCacheInterface as CacheInterface;
  17. use Symfony\Contracts\Cache\ItemInterface;
  18. /**
  19.  * Class AppCacheSubscriber.
  20.  */
  21. class AppCacheSubscriber implements EventSubscriberInterface
  22. {
  23.     /**
  24.      * Annotation reader.
  25.      *
  26.      * @var Reader
  27.      */
  28.     private $annotationReader;
  29.     /**
  30.      * Cache.
  31.      *
  32.      * @var CacheInterface
  33.      */
  34.     private $cache;
  35.     /**
  36.      * Cache key.
  37.      *
  38.      * @var string
  39.      */
  40.     private $key;
  41.     /**
  42.      * Security.
  43.      *
  44.      * @var Security
  45.      */
  46.     private $security;
  47.     /**
  48.      * AppCacheSubscriber constructor.
  49.      *
  50.      * @param CacheInterface $cache
  51.      * @param Reader         $reader
  52.      * @param Security       $security
  53.      */
  54.     public function __construct(CacheInterface $cacheReader $readerSecurity $security)
  55.     {
  56.         $this->cache $cache;
  57.         $this->annotationReader $reader;
  58.         $this->security $security;
  59.     }
  60.     /**
  61.      * Get subscribed events.
  62.      *
  63.      * @return array
  64.      */
  65.     public static function getSubscribedEvents()
  66.     {
  67.         // return the subscribed events, their methods and priorities
  68.         return [
  69.             KernelEvents::CONTROLLER_ARGUMENTS => [
  70.                 ['onKernelController'1],
  71.             ],
  72.             KernelEvents::RESPONSE => [
  73.                 ['onKernelResponse'10],
  74.             ],
  75.         ];
  76.     }
  77.     /**
  78.      * On kernel controller.
  79.      *
  80.      * @param ControllerArgumentsEvent $event
  81.      */
  82.     public function onKernelController(ControllerArgumentsEvent $event)
  83.     {
  84.         $annotation $this->getAppCacheAnnotation($event->getController());
  85.         if (!$event->getRequest()->isMethod('GET') || !$this->security->getUser() || null === $annotation) {
  86.             return;
  87.         }
  88.         $this->key 'measurement_'.$event->getRequest()->get('id').'_'.preg_replace("/[^A-Za-z0-9 ]/"''$event->getRequest()->getPathInfo()).$this->security->getUser()->getId();
  89.         if ($cached $this->cache->getItem($this->key)->get()) {
  90.             $event->setController(function () use ($cached) {
  91.                 return $cached;
  92.             });
  93.             $event->stopPropagation();
  94.         }
  95.     }
  96.     /**
  97.      * On kernel response.
  98.      *
  99.      * @param ResponseEvent $event
  100.      */
  101.     public function onKernelResponse(ResponseEvent $event)
  102.     {
  103.         if (Response::HTTP_OK !== $event->getResponse()->getStatusCode()) {
  104.             return;
  105.         }
  106.         if (!isset($this->key)) {
  107.             return;
  108.         }
  109.         $tag 'measurement_'.$event->getRequest()->get('id');
  110.         $response $event->getResponse();
  111.         $this->cache->get($this->key, function (ItemInterface $item) use ($response$tag) {
  112.             $item->tag([$tag'user_'.$this->security->getUser()->getId()]);
  113.             return $response;
  114.         });
  115.     }
  116.     /**
  117.      * Does controller have idempotent annotation.
  118.      *
  119.      * @param callable $controllerData
  120.      *
  121.      * @return AppCache|null
  122.      */
  123.     private function getAppCacheAnnotation($controllerData)
  124.     {
  125.         $annotation null;
  126.         if (!is_array($controllerData)) {
  127.             return null;
  128.         }
  129.         list($controllerObject$methodName) = $controllerData;
  130.         try {
  131.             $controller = new ReflectionClass($controllerObject);
  132.             $method $controller->getMethod($methodName);
  133.             $annotation $this->annotationReader->getMethodAnnotation($methodAppCache::class);
  134.         } catch (ReflectionException $e) {
  135.             return null;
  136.         }
  137.         return $annotation instanceof AppCache $annotation null;
  138.     }
  139. }