vendor/symfony/src/Symfony/Component/Security/Acl/Domain/DoctrineAclCache.php
changeset 0 7f95f8617b0b
equal deleted inserted replaced
-1:000000000000 0:7f95f8617b0b
       
     1 <?php
       
     2 
       
     3 /*
       
     4  * This file is part of the Symfony package.
       
     5  *
       
     6  * (c) Fabien Potencier <fabien@symfony.com>
       
     7  *
       
     8  * For the full copyright and license information, please view the LICENSE
       
     9  * file that was distributed with this source code.
       
    10  */
       
    11 
       
    12 namespace Symfony\Component\Security\Acl\Domain;
       
    13 
       
    14 use Doctrine\Common\Cache\Cache;
       
    15 use Symfony\Component\Security\Acl\Model\AclCacheInterface;
       
    16 use Symfony\Component\Security\Acl\Model\AclInterface;
       
    17 use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
       
    18 use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface;
       
    19 
       
    20 /**
       
    21  * This class is a wrapper around the actual cache implementation.
       
    22  *
       
    23  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
       
    24  */
       
    25 class DoctrineAclCache implements AclCacheInterface
       
    26 {
       
    27     const PREFIX = 'sf2_acl_';
       
    28 
       
    29     private $cache;
       
    30     private $prefix;
       
    31     private $permissionGrantingStrategy;
       
    32 
       
    33     /**
       
    34      * Constructor
       
    35      *
       
    36      * @param Cache                               $cache
       
    37      * @param PermissionGrantingStrategyInterface $permissionGrantingStrategy
       
    38      * @param string                              $prefix
       
    39      *
       
    40      * @return void
       
    41      */
       
    42     public function __construct(Cache $cache, PermissionGrantingStrategyInterface $permissionGrantingStrategy, $prefix = self::PREFIX)
       
    43     {
       
    44         if (0 === strlen($prefix)) {
       
    45             throw new \InvalidArgumentException('$prefix cannot be empty.');
       
    46         }
       
    47 
       
    48         $this->cache = $cache;
       
    49         $this->permissionGrantingStrategy = $permissionGrantingStrategy;
       
    50         $this->prefix = $prefix;
       
    51     }
       
    52 
       
    53     /**
       
    54      * {@inheritDoc}
       
    55      */
       
    56     public function clearCache()
       
    57     {
       
    58         $this->cache->deleteByPrefix($this->prefix);
       
    59     }
       
    60 
       
    61     /**
       
    62      * {@inheritDoc}
       
    63      */
       
    64     public function evictFromCacheById($aclId)
       
    65     {
       
    66         $lookupKey = $this->getAliasKeyForIdentity($aclId);
       
    67         if (!$this->cache->contains($lookupKey)) {
       
    68             return;
       
    69         }
       
    70 
       
    71         $key = $this->cache->fetch($lookupKey);
       
    72         if ($this->cache->contains($key)) {
       
    73             $this->cache->delete($key);
       
    74         }
       
    75 
       
    76         $this->cache->delete($lookupKey);
       
    77     }
       
    78 
       
    79     /**
       
    80      * {@inheritDoc}
       
    81      */
       
    82     public function evictFromCacheByIdentity(ObjectIdentityInterface $oid)
       
    83     {
       
    84         $key = $this->getDataKeyByIdentity($oid);
       
    85         if (!$this->cache->contains($key)) {
       
    86             return;
       
    87         }
       
    88 
       
    89         $this->cache->delete($key);
       
    90     }
       
    91 
       
    92     /**
       
    93      * {@inheritDoc}
       
    94      */
       
    95     public function getFromCacheById($aclId)
       
    96     {
       
    97         $lookupKey = $this->getAliasKeyForIdentity($aclId);
       
    98         if (!$this->cache->contains($lookupKey)) {
       
    99             return null;
       
   100         }
       
   101 
       
   102         $key = $this->cache->fetch($lookupKey);
       
   103         if (!$this->cache->contains($key)) {
       
   104             $this->cache->delete($lookupKey);
       
   105 
       
   106             return null;
       
   107         }
       
   108 
       
   109         return $this->unserializeAcl($this->cache->fetch($key));
       
   110     }
       
   111 
       
   112     /**
       
   113      * {@inheritDoc}
       
   114      */
       
   115     public function getFromCacheByIdentity(ObjectIdentityInterface $oid)
       
   116     {
       
   117         $key = $this->getDataKeyByIdentity($oid);
       
   118         if (!$this->cache->contains($key)) {
       
   119             return null;
       
   120         }
       
   121 
       
   122         return $this->unserializeAcl($this->cache->fetch($key));
       
   123     }
       
   124 
       
   125     /**
       
   126      * {@inheritDoc}
       
   127      */
       
   128     public function putInCache(AclInterface $acl)
       
   129     {
       
   130         if (null === $acl->getId()) {
       
   131             throw new \InvalidArgumentException('Transient ACLs cannot be cached.');
       
   132         }
       
   133 
       
   134         if (null !== $parentAcl = $acl->getParentAcl()) {
       
   135             $this->putInCache($parentAcl);
       
   136         }
       
   137 
       
   138         $key = $this->getDataKeyByIdentity($acl->getObjectIdentity());
       
   139         $this->cache->save($key, serialize($acl));
       
   140         $this->cache->save($this->getAliasKeyForIdentity($acl->getId()), $key);
       
   141     }
       
   142 
       
   143     /**
       
   144      * Unserializes the ACL.
       
   145      *
       
   146      * @param string $serialized
       
   147      * @return AclInterface
       
   148      */
       
   149     private function unserializeAcl($serialized)
       
   150     {
       
   151         $acl = unserialize($serialized);
       
   152 
       
   153         if (null !== $parentId = $acl->getParentAcl()) {
       
   154             $parentAcl = $this->getFromCacheById($parentId);
       
   155 
       
   156             if (null === $parentAcl) {
       
   157                 return null;
       
   158             }
       
   159 
       
   160             $acl->setParentAcl($parentAcl);
       
   161         }
       
   162 
       
   163         $reflectionProperty = new \ReflectionProperty($acl, 'permissionGrantingStrategy');
       
   164         $reflectionProperty->setAccessible(true);
       
   165         $reflectionProperty->setValue($acl, $this->permissionGrantingStrategy);
       
   166         $reflectionProperty->setAccessible(false);
       
   167 
       
   168         $aceAclProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Entry', 'acl');
       
   169         $aceAclProperty->setAccessible(true);
       
   170 
       
   171         foreach ($acl->getObjectAces() as $ace) {
       
   172             $aceAclProperty->setValue($ace, $acl);
       
   173         }
       
   174         foreach ($acl->getClassAces() as $ace) {
       
   175             $aceAclProperty->setValue($ace, $acl);
       
   176         }
       
   177 
       
   178         $aceClassFieldProperty = new \ReflectionProperty($acl, 'classFieldAces');
       
   179         $aceClassFieldProperty->setAccessible(true);
       
   180         foreach ($aceClassFieldProperty->getValue($acl) as $aces) {
       
   181             foreach ($aces as $ace) {
       
   182                 $aceAclProperty->setValue($ace, $acl);
       
   183             }
       
   184         }
       
   185         $aceClassFieldProperty->setAccessible(false);
       
   186 
       
   187         $aceObjectFieldProperty = new \ReflectionProperty($acl, 'objectFieldAces');
       
   188         $aceObjectFieldProperty->setAccessible(true);
       
   189         foreach ($aceObjectFieldProperty->getValue($acl) as $aces) {
       
   190             foreach ($aces as $ace) {
       
   191                 $aceAclProperty->setValue($ace, $acl);
       
   192             }
       
   193         }
       
   194         $aceObjectFieldProperty->setAccessible(false);
       
   195 
       
   196         $aceAclProperty->setAccessible(false);
       
   197 
       
   198         return $acl;
       
   199     }
       
   200 
       
   201     /**
       
   202      * Returns the key for the object identity
       
   203      *
       
   204      * @param ObjectIdentityInterface $oid
       
   205      * @return string
       
   206      */
       
   207     private function getDataKeyByIdentity(ObjectIdentityInterface $oid)
       
   208     {
       
   209         return $this->prefix.md5($oid->getType()).sha1($oid->getType())
       
   210                .'_'.md5($oid->getIdentifier()).sha1($oid->getIdentifier());
       
   211     }
       
   212 
       
   213     /**
       
   214      * Returns the alias key for the object identity key
       
   215      *
       
   216      * @param string $aclId
       
   217      * @return string
       
   218      */
       
   219     private function getAliasKeyForIdentity($aclId)
       
   220     {
       
   221         return $this->prefix.$aclId;
       
   222     }
       
   223 }