vendor/pec-platform/platform-bundle/Security/CachedAccessDecisionManager.php line 53

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Pec\Bundle\PlatformBundle\Security;
  4. use Pec\Bundle\PlatformBundle\Entity\Interfaces\Identifiable;
  5. use Psr\Cache\InvalidArgumentException;
  6. use StingerSoft\PhpCommons\Builder\HashCodeBuilder;
  7. use Symfony\Component\Cache\Adapter\AdapterInterface;
  8. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  9. use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
  10. class CachedAccessDecisionManager implements AccessDecisionManagerInterface {
  11.     /**
  12.      * @var int
  13.      */
  14.     protected const DEFAULT_TTL 60;
  15.     protected const CACHE_PREFIX 'CachedAccessDecisionManager';
  16.     /**
  17.      * @var int
  18.      */
  19.     protected $ttl;
  20.     /**
  21.      * @var AccessDecisionManagerInterface
  22.      */
  23.     protected $decorated;
  24.     /**
  25.      * @var AdapterInterface
  26.      */
  27.     protected $cache;
  28.     /**
  29.      * CachedAccessDecisionManager constructor.
  30.      * @param AccessDecisionManagerInterface $decorated
  31.      * @param AdapterInterface $cache
  32.      */
  33.     public function __construct(AccessDecisionManagerInterface $decoratedAdapterInterface $cache) {
  34.         $this->decorated $decorated;
  35.         $this->cache $cache;
  36.     }
  37.     /**
  38.      * Decides whether the access is possible or not.
  39.      *
  40.      * @param TokenInterface $token
  41.      * @param array $attributes An array of attributes associated with the method being invoked
  42.      * @param object $object The object to secure
  43.      *
  44.      * @return bool true if the access is granted, false otherwise
  45.      */
  46.     public function decide(TokenInterface $token, array $attributes$object null): bool {
  47.         $username $token->getUsername();
  48.         if(!$username) {
  49.             return $this->decorated->decide($token$attributes$object);
  50.         }
  51.         if($object !== null && !($object instanceof Identifiable)) {
  52.             return $this->decorated->decide($token$attributes$object);
  53.         }
  54.         try {
  55.             $hashBuilder = new HashCodeBuilder();
  56.             $hashBuilder->append($username);
  57.             $hashBuilder->append($attributes);
  58.             if($object !== null) {
  59.                 $className get_class($object);
  60.                 if (class_exists('Symfony\Component\Security\Acl\Util\ClassUtils')) {
  61.                     $className \Symfony\Component\Security\Acl\Util\ClassUtils::getRealClass($className);
  62.                 }else if (class_exists('Doctrine\Common\Util\ClassUtils')) {
  63.                     $className \Doctrine\Common\Util\ClassUtils::getRealClass($className);
  64.                 }
  65.                 $hashBuilder->append($className '#' $object->getId());
  66.             }
  67.             $cacheKey self::CACHE_PREFIX '_' $hashBuilder->toHashCode();
  68.             $cacheItem $this->cache->getItem($cacheKey);
  69.             if(!$cacheItem->isHit()) {
  70.                 $cacheItem->set($this->decorated->decide($token$attributes$object));
  71.                 $cacheItem->expiresAfter($this->getTtl());
  72.                 $this->cache->save($cacheItem);
  73.             }
  74.             return (bool)$cacheItem->get();
  75.         } catch(\ReflectionException|InvalidArgumentException $re) {
  76.             return $this->decorated->decide($token$attributes$object);
  77.         }
  78.     }
  79.     /**
  80.      * @return int
  81.      */
  82.     protected function getTtl(): int {
  83.         return $this->ttl ?? self::DEFAULT_TTL;
  84.     }
  85.     public function setTtl(int $ttl): void {
  86.         $this->ttl $ttl;
  87.     }
  88. }