vendor/symfony/src/Symfony/Component/Security/Acl/Dbal/AclProvider.php
author ymh <ymh.work@gmail.com>
Sat, 24 Sep 2011 15:40:41 +0200
changeset 0 7f95f8617b0b
permissions -rwxr-xr-x
first commit
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
<?php
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
/*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
 * This file is part of the Symfony package.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
 * (c) Fabien Potencier <fabien@symfony.com>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
 * For the full copyright and license information, please view the LICENSE
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
 * file that was distributed with this source code.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
namespace Symfony\Component\Security\Acl\Dbal;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
use Doctrine\DBAL\Driver\Connection;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
use Doctrine\DBAL\Driver\Statement;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
use Symfony\Component\Security\Acl\Model\AclInterface;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
use Symfony\Component\Security\Acl\Domain\Acl;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
use Symfony\Component\Security\Acl\Domain\Entry;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
use Symfony\Component\Security\Acl\Domain\FieldEntry;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
use Symfony\Component\Security\Acl\Exception\AclNotFoundException;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
use Symfony\Component\Security\Acl\Exception\NotAllAclsFoundException;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
use Symfony\Component\Security\Acl\Model\AclCacheInterface;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
use Symfony\Component\Security\Acl\Model\AclProviderInterface;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
/**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
 * An ACL provider implementation.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
 * This provider assumes that all ACLs share the same PermissionGrantingStrategy.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
class AclProvider implements AclProviderInterface
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
{
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
    const MAX_BATCH_SIZE = 30;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
    protected $cache;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
    protected $connection;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
    protected $loadedAces;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
    protected $loadedAcls;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
    protected $options;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
    private $permissionGrantingStrategy;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
     * Constructor.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
     * @param Connection                          $connection
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
     * @param PermissionGrantingStrategyInterface $permissionGrantingStrategy
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
     * @param array                               $options
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
     * @param AclCacheInterface                   $cache
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
    public function __construct(Connection $connection, PermissionGrantingStrategyInterface $permissionGrantingStrategy, array $options, AclCacheInterface $cache = null)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
        $this->cache = $cache;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
        $this->connection = $connection;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
        $this->loadedAces = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
        $this->loadedAcls = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
        $this->options = $options;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
        $this->permissionGrantingStrategy = $permissionGrantingStrategy;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
     * {@inheritDoc}
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
    public function findChildren(ObjectIdentityInterface $parentOid, $directChildrenOnly = false)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
        $sql = $this->getFindChildrenSql($parentOid, $directChildrenOnly);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
        $children = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
        foreach ($this->connection->executeQuery($sql)->fetchAll() as $data) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
            $children[] = new ObjectIdentity($data['object_identifier'], $data['class_type']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
        return $children;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
     * {@inheritDoc}
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
    public function findAcl(ObjectIdentityInterface $oid, array $sids = array())
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
        return $this->findAcls(array($oid), $sids)->offsetGet($oid);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
     * {@inheritDoc}
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
    public function findAcls(array $oids, array $sids = array())
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
        $result = new \SplObjectStorage();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
        $currentBatch = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
        $oidLookup = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
        for ($i=0,$c=count($oids); $i<$c; $i++) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
            $oid = $oids[$i];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
            $oidLookupKey = $oid->getIdentifier().$oid->getType();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
            $oidLookup[$oidLookupKey] = $oid;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
            $aclFound = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
            // check if result already contains an ACL
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
            if ($result->contains($oid)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
                $aclFound = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
            // check if this ACL has already been hydrated
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
            if (!$aclFound && isset($this->loadedAcls[$oid->getType()][$oid->getIdentifier()])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
                $acl = $this->loadedAcls[$oid->getType()][$oid->getIdentifier()];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
                if (!$acl->isSidLoaded($sids)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
                    // FIXME: we need to load ACEs for the missing SIDs. This is never
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
                    //        reached by the default implementation, since we do not
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
                    //        filter by SID
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
                    throw new \RuntimeException('This is not supported by the default implementation.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
                    $result->attach($oid, $acl);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
                    $aclFound = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
            // check if we can locate the ACL in the cache
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
            if (!$aclFound && null !== $this->cache) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
                $acl = $this->cache->getFromCacheByIdentity($oid);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
                if (null !== $acl) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
                    if ($acl->isSidLoaded($sids)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
                        // check if any of the parents has been loaded since we need to
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
                        // ensure that there is only ever one ACL per object identity
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
                        $parentAcl = $acl->getParentAcl();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
                        while (null !== $parentAcl) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
                            $parentOid = $parentAcl->getObjectIdentity();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
                            if (isset($this->loadedAcls[$parentOid->getType()][$parentOid->getIdentifier()])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
                                $acl->setParentAcl($this->loadedAcls[$parentOid->getType()][$parentOid->getIdentifier()]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
                                break;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
                            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
                                $this->loadedAcls[$parentOid->getType()][$parentOid->getIdentifier()] = $parentAcl;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   141
                                $this->updateAceIdentityMap($parentAcl);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
                            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
                            $parentAcl = $parentAcl->getParentAcl();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
                        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
                        $this->loadedAcls[$oid->getType()][$oid->getIdentifier()] = $acl;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
                        $this->updateAceIdentityMap($acl);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
                        $result->attach($oid, $acl);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
                        $aclFound = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
                    } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
                        $this->cache->evictFromCacheByIdentity($oid);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   153
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   154
                        foreach ($this->findChildren($oid) as $childOid) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   155
                            $this->cache->evictFromCacheByIdentity($childOid);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   156
                        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   157
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   158
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   159
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   160
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   161
            // looks like we have to load the ACL from the database
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   162
            if (!$aclFound) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   163
                $currentBatch[] = $oid;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   164
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   165
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   166
            // Is it time to load the current batch?
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   167
            if ((self::MAX_BATCH_SIZE === count($currentBatch) || ($i + 1) === $c) && count($currentBatch) > 0) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   168
                $loadedBatch = $this->lookupObjectIdentities($currentBatch, $sids, $oidLookup);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   169
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   170
                foreach ($loadedBatch as $loadedOid) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   171
                    $loadedAcl = $loadedBatch->offsetGet($loadedOid);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   172
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   173
                    if (null !== $this->cache) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   174
                        $this->cache->putInCache($loadedAcl);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   175
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   176
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   177
                    if (isset($oidLookup[$loadedOid->getIdentifier().$loadedOid->getType()])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   178
                        $result->attach($loadedOid, $loadedAcl);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   179
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   180
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   181
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   182
                $currentBatch = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   183
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   184
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   185
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   186
        // check that we got ACLs for all the identities
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   187
        foreach ($oids as $oid) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   188
            if (!$result->contains($oid)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   189
                if (1 === count($oids)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   190
                    throw new AclNotFoundException(sprintf('No ACL found for %s.', $oid));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   191
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   192
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   193
                $partialResultException = new NotAllAclsFoundException('The provider could not find ACLs for all object identities.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   194
                $partialResultException->setPartialResult($result);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   195
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   196
                throw $partialResultException;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   197
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   198
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   199
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   200
        return $result;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   201
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   202
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   203
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   204
     * Constructs the query used for looking up object identities and associated
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   205
     * ACEs, and security identities.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   206
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   207
     * @param array $ancestorIds
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   208
     * @return string
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   209
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   210
    protected function getLookupSql(array $ancestorIds)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   211
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   212
        // FIXME: add support for filtering by sids (right now we select all sids)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   213
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   214
        $sql = <<<SELECTCLAUSE
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   215
            SELECT
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   216
                o.id as acl_id,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   217
                o.object_identifier,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   218
                o.parent_object_identity_id,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   219
                o.entries_inheriting,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   220
                c.class_type,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   221
                e.id as ace_id,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   222
                e.object_identity_id,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   223
                e.field_name,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   224
                e.ace_order,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   225
                e.mask,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   226
                e.granting,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   227
                e.granting_strategy,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   228
                e.audit_success,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   229
                e.audit_failure,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   230
                s.username,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   231
                s.identifier as security_identifier
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   232
            FROM
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   233
                {$this->options['oid_table_name']} o
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   234
            INNER JOIN {$this->options['class_table_name']} c ON c.id = o.class_id
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   235
            LEFT JOIN {$this->options['entry_table_name']} e ON (
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   236
                e.class_id = o.class_id AND (e.object_identity_id = o.id OR {$this->connection->getDatabasePlatform()->getIsNullExpression('e.object_identity_id')})
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   237
            )
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   238
            LEFT JOIN {$this->options['sid_table_name']} s ON (
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   239
                s.id = e.security_identity_id
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   240
            )
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   241
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   242
            WHERE (o.id =
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   243
SELECTCLAUSE;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   244
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   245
        $sql .= implode(' OR o.id = ', $ancestorIds).')';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   246
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   247
        return $sql;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   248
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   249
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   250
    protected function getAncestorLookupSql(array $batch)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   251
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   252
        $sql = <<<SELECTCLAUSE
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   253
            SELECT a.ancestor_id
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   254
            FROM
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   255
                {$this->options['oid_table_name']} o
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   256
            INNER JOIN {$this->options['class_table_name']} c ON c.id = o.class_id
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   257
            INNER JOIN {$this->options['oid_ancestors_table_name']} a ON a.object_identity_id = o.id
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   258
               WHERE (
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   259
SELECTCLAUSE;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   260
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   261
        $where = '(o.object_identifier = %s AND c.class_type = %s)';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   262
        for ($i=0,$c=count($batch); $i<$c; $i++) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   263
            $sql .= sprintf(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   264
                $where,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   265
                $this->connection->quote($batch[$i]->getIdentifier()),
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   266
                $this->connection->quote($batch[$i]->getType())
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   267
            );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   268
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   269
            if ($i+1 < $c) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   270
                $sql .= ' OR ';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   271
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   272
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   273
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   274
        $sql .= ')';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   275
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   276
        return $sql;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   277
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   278
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   279
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   280
     * Constructs the SQL for retrieving child object identities for the given
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   281
     * object identities.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   282
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   283
     * @param ObjectIdentityInterface $oid
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   284
     * @param Boolean                 $directChildrenOnly
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   285
     * @return string
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   286
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   287
    protected function getFindChildrenSql(ObjectIdentityInterface $oid, $directChildrenOnly)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   288
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   289
        if (false === $directChildrenOnly) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   290
            $query = <<<FINDCHILDREN
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   291
                SELECT o.object_identifier, c.class_type
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   292
                FROM
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   293
                    {$this->options['oid_table_name']} as o
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   294
                INNER JOIN {$this->options['class_table_name']} as c ON c.id = o.class_id
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   295
                INNER JOIN {$this->options['oid_ancestors_table_name']} as a ON a.object_identity_id = o.id
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   296
                WHERE
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   297
                    a.ancestor_id = %d AND a.object_identity_id != a.ancestor_id
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   298
FINDCHILDREN;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   299
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   300
            $query = <<<FINDCHILDREN
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   301
                SELECT o.object_identifier, c.class_type
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   302
                FROM {$this->options['oid_table_name']} as o
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   303
                INNER JOIN {$this->options['class_table_name']} as c ON c.id = o.class_id
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   304
                WHERE o.parent_object_identity_id = %d
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   305
FINDCHILDREN;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   306
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   307
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   308
        return sprintf($query, $this->retrieveObjectIdentityPrimaryKey($oid));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   309
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   310
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   311
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   312
     * Constructs the SQL for retrieving the primary key of the given object
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   313
     * identity.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   314
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   315
     * @param ObjectIdentityInterface $oid
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   316
     * @return string
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   317
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   318
    protected function getSelectObjectIdentityIdSql(ObjectIdentityInterface $oid)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   319
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   320
        $query = <<<QUERY
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   321
            SELECT o.id
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   322
            FROM %s o
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   323
            INNER JOIN %s c ON c.id = o.class_id
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   324
            WHERE o.object_identifier = %s AND c.class_type = %s
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   325
QUERY;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   326
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   327
        return sprintf(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   328
            $query,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   329
            $this->options['oid_table_name'],
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   330
            $this->options['class_table_name'],
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   331
            $this->connection->quote($oid->getIdentifier()),
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   332
            $this->connection->quote($oid->getType())
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   333
        );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   334
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   335
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   336
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   337
     * Returns the primary key of the passed object identity.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   338
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   339
     * @param ObjectIdentityInterface $oid
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   340
     * @return integer
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   341
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   342
    protected final function retrieveObjectIdentityPrimaryKey(ObjectIdentityInterface $oid)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   343
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   344
        return $this->connection->executeQuery($this->getSelectObjectIdentityIdSql($oid))->fetchColumn();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   345
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   346
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   347
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   348
     * This method is called when an ACL instance is retrieved from the cache.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   349
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   350
     * @param AclInterface $acl
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   351
     * @return void
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   352
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   353
    private function updateAceIdentityMap(AclInterface $acl)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   354
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   355
        foreach (array('classAces', 'classFieldAces', 'objectAces', 'objectFieldAces') as $property) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   356
            $reflection = new \ReflectionProperty($acl, $property);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   357
            $reflection->setAccessible(true);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   358
            $value = $reflection->getValue($acl);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   359
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   360
            if ('classAces' === $property || 'objectAces' === $property) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   361
                $this->doUpdateAceIdentityMap($value);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   362
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   363
                foreach ($value as $field => $aces) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   364
                    $this->doUpdateAceIdentityMap($value[$field]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   365
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   366
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   367
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   368
            $reflection->setValue($acl, $value);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   369
            $reflection->setAccessible(false);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   370
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   371
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   372
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   373
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   374
     * Retrieves all the ids which need to be queried from the database
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   375
     * including the ids of parent ACLs.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   376
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   377
     * @param array $batch
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   378
     * @return array
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   379
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   380
    private function getAncestorIds(array $batch)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   381
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   382
        $sql = $this->getAncestorLookupSql($batch);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   383
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   384
        $ancestorIds = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   385
        foreach ($this->connection->executeQuery($sql)->fetchAll() as $data) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   386
            // FIXME: skip ancestors which are cached
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   387
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   388
            $ancestorIds[] = $data['ancestor_id'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   389
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   390
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   391
        return $ancestorIds;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   392
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   393
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   394
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   395
     * Does either overwrite the passed ACE, or saves it in the global identity
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   396
     * map to ensure every ACE only gets instantiated once.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   397
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   398
     * @param array $aces
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   399
     * @return void
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   400
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   401
    private function doUpdateAceIdentityMap(array &$aces)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   402
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   403
        foreach ($aces as $index => $ace) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   404
            if (isset($this->loadedAces[$ace->getId()])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   405
                $aces[$index] = $this->loadedAces[$ace->getId()];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   406
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   407
                $this->loadedAces[$ace->getId()] = $ace;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   408
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   409
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   410
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   411
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   412
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   413
     * This method is called for object identities which could not be retrieved
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   414
     * from the cache, and for which thus a database query is required.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   415
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   416
     * @param array $batch
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   417
     * @param array $sids
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   418
     * @param array $oidLookup
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   419
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   420
     * @return \SplObjectStorage mapping object identities to ACL instances
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   421
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   422
    private function lookupObjectIdentities(array $batch, array $sids, array $oidLookup)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   423
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   424
        $ancestorIds = $this->getAncestorIds($batch);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   425
        if (!$ancestorIds) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   426
            throw new AclNotFoundException('There is no ACL for the given object identity.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   427
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   428
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   429
        $sql = $this->getLookupSql($ancestorIds);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   430
        $stmt = $this->connection->executeQuery($sql);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   431
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   432
        return $this->hydrateObjectIdentities($stmt, $oidLookup, $sids);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   433
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   434
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   435
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   436
     * This method is called to hydrate ACLs and ACEs.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   437
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   438
     * This method was designed for performance; thus, a lot of code has been
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   439
     * inlined at the cost of readability, and maintainability.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   440
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   441
     * Keep in mind that changes to this method might severely reduce the
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   442
     * performance of the entire ACL system.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   443
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   444
     * @param Statement $stmt
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   445
     * @param array     $oidLookup
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   446
     * @param array     $sids
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   447
     * @throws \RuntimeException
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   448
     * @return \SplObjectStorage
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   449
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   450
    private function hydrateObjectIdentities(Statement $stmt, array $oidLookup, array $sids) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   451
        $parentIdToFill = new \SplObjectStorage();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   452
        $acls = $aces = $emptyArray = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   453
        $oidCache = $oidLookup;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   454
        $result = new \SplObjectStorage();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   455
        $loadedAces =& $this->loadedAces;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   456
        $loadedAcls =& $this->loadedAcls;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   457
        $permissionGrantingStrategy = $this->permissionGrantingStrategy;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   458
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   459
        // we need these to set protected properties on hydrated objects
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   460
        $aclReflection = new \ReflectionClass('Symfony\Component\Security\Acl\Domain\Acl');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   461
        $aclClassAcesProperty = $aclReflection->getProperty('classAces');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   462
        $aclClassAcesProperty->setAccessible(true);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   463
        $aclClassFieldAcesProperty = $aclReflection->getProperty('classFieldAces');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   464
        $aclClassFieldAcesProperty->setAccessible(true);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   465
        $aclObjectAcesProperty = $aclReflection->getProperty('objectAces');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   466
        $aclObjectAcesProperty->setAccessible(true);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   467
        $aclObjectFieldAcesProperty = $aclReflection->getProperty('objectFieldAces');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   468
        $aclObjectFieldAcesProperty->setAccessible(true);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   469
        $aclParentAclProperty = $aclReflection->getProperty('parentAcl');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   470
        $aclParentAclProperty->setAccessible(true);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   471
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   472
        // fetchAll() consumes more memory than consecutive calls to fetch(),
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   473
        // but it is faster
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   474
        foreach ($stmt->fetchAll(\PDO::FETCH_NUM) as $data) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   475
            list($aclId,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   476
                 $objectIdentifier,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   477
                 $parentObjectIdentityId,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   478
                 $entriesInheriting,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   479
                 $classType,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   480
                 $aceId,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   481
                 $objectIdentityId,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   482
                 $fieldName,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   483
                 $aceOrder,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   484
                 $mask,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   485
                 $granting,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   486
                 $grantingStrategy,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   487
                 $auditSuccess,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   488
                 $auditFailure,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   489
                 $username,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   490
                 $securityIdentifier) = $data;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   491
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   492
            // has the ACL been hydrated during this hydration cycle?
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   493
            if (isset($acls[$aclId])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   494
                $acl = $acls[$aclId];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   495
            // has the ACL been hydrated during any previous cycle, or was possibly loaded
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   496
            // from cache?
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   497
            } else if (isset($loadedAcls[$classType][$objectIdentifier])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   498
                $acl = $loadedAcls[$classType][$objectIdentifier];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   499
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   500
                // keep reference in local array (saves us some hash calculations)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   501
                $acls[$aclId] = $acl;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   502
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   503
                // attach ACL to the result set; even though we do not enforce that every
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   504
                // object identity has only one instance, we must make sure to maintain
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   505
                // referential equality with the oids passed to findAcls()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   506
                if (!isset($oidCache[$objectIdentifier.$classType])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   507
                    $oidCache[$objectIdentifier.$classType] = $acl->getObjectIdentity();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   508
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   509
                $result->attach($oidCache[$objectIdentifier.$classType], $acl);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   510
            // so, this hasn't been hydrated yet
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   511
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   512
                // create object identity if we haven't done so yet
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   513
                $oidLookupKey = $objectIdentifier.$classType;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   514
                if (!isset($oidCache[$oidLookupKey])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   515
                    $oidCache[$oidLookupKey] = new ObjectIdentity($objectIdentifier, $classType);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   516
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   517
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   518
                $acl = new Acl((integer) $aclId, $oidCache[$oidLookupKey], $permissionGrantingStrategy, $emptyArray, !!$entriesInheriting);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   519
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   520
                // keep a local, and global reference to this ACL
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   521
                $loadedAcls[$classType][$objectIdentifier] = $acl;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   522
                $acls[$aclId] = $acl;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   523
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   524
                // try to fill in parent ACL, or defer until all ACLs have been hydrated
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   525
                if (null !== $parentObjectIdentityId) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   526
                    if (isset($acls[$parentObjectIdentityId])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   527
                        $aclParentAclProperty->setValue($acl, $acls[$parentObjectIdentityId]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   528
                    } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   529
                        $parentIdToFill->attach($acl, $parentObjectIdentityId);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   530
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   531
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   532
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   533
                $result->attach($oidCache[$oidLookupKey], $acl);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   534
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   535
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   536
            // check if this row contains an ACE record
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   537
            if (null !== $aceId) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   538
                // have we already hydrated ACEs for this ACL?
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   539
                if (!isset($aces[$aclId])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   540
                    $aces[$aclId] = array($emptyArray, $emptyArray, $emptyArray, $emptyArray);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   541
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   542
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   543
                // has this ACE already been hydrated during a previous cycle, or
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   544
                // possible been loaded from cache?
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   545
                // It is important to only ever have one ACE instance per actual row since
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   546
                // some ACEs are shared between ACL instances
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   547
                if (!isset($loadedAces[$aceId])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   548
                    if (!isset($sids[$key = ($username?'1':'0').$securityIdentifier])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   549
                        if ($username) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   550
                            $sids[$key] = new UserSecurityIdentity(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   551
                                substr($securityIdentifier, 1 + $pos = strpos($securityIdentifier, '-')),
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   552
                                substr($securityIdentifier, 0, $pos)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   553
                            );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   554
                        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   555
                            $sids[$key] = new RoleSecurityIdentity($securityIdentifier);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   556
                        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   557
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   558
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   559
                    if (null === $fieldName) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   560
                        $loadedAces[$aceId] = new Entry((integer) $aceId, $acl, $sids[$key], $grantingStrategy, (integer) $mask, !!$granting, !!$auditFailure, !!$auditSuccess);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   561
                    } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   562
                        $loadedAces[$aceId] = new FieldEntry((integer) $aceId, $acl, $fieldName, $sids[$key], $grantingStrategy, (integer) $mask, !!$granting, !!$auditFailure, !!$auditSuccess);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   563
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   564
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   565
                $ace = $loadedAces[$aceId];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   566
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   567
                // assign ACE to the correct property
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   568
                if (null === $objectIdentityId) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   569
                    if (null === $fieldName) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   570
                        $aces[$aclId][0][$aceOrder] = $ace;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   571
                    } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   572
                        $aces[$aclId][1][$fieldName][$aceOrder] = $ace;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   573
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   574
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   575
                    if (null === $fieldName) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   576
                        $aces[$aclId][2][$aceOrder] = $ace;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   577
                    } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   578
                        $aces[$aclId][3][$fieldName][$aceOrder] = $ace;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   579
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   580
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   581
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   582
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   583
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   584
        // We do not sort on database level since we only want certain subsets to be sorted,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   585
        // and we are going to read the entire result set anyway.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   586
        // Sorting on DB level increases query time by an order of magnitude while it is
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   587
        // almost negligible when we use PHPs array sort functions.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   588
        foreach ($aces as $aclId => $aceData) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   589
            $acl = $acls[$aclId];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   590
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   591
            ksort($aceData[0]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   592
            $aclClassAcesProperty->setValue($acl, $aceData[0]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   593
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   594
            foreach (array_keys($aceData[1]) as $fieldName) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   595
                ksort($aceData[1][$fieldName]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   596
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   597
            $aclClassFieldAcesProperty->setValue($acl, $aceData[1]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   598
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   599
            ksort($aceData[2]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   600
            $aclObjectAcesProperty->setValue($acl, $aceData[2]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   601
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   602
            foreach (array_keys($aceData[3]) as $fieldName) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   603
                ksort($aceData[3][$fieldName]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   604
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   605
            $aclObjectFieldAcesProperty->setValue($acl, $aceData[3]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   606
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   607
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   608
        // fill-in parent ACLs where this hasn't been done yet cause the parent ACL was not
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   609
        // yet available
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   610
        $processed = 0;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   611
        foreach ($parentIdToFill as $acl) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   612
            $parentId = $parentIdToFill->offsetGet($acl);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   613
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   614
            // let's see if we have already hydrated this
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   615
            if (isset($acls[$parentId])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   616
                $aclParentAclProperty->setValue($acl, $acls[$parentId]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   617
                $processed += 1;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   618
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   619
                continue;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   620
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   621
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   622
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   623
        // reset reflection changes
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   624
        $aclClassAcesProperty->setAccessible(false);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   625
        $aclClassFieldAcesProperty->setAccessible(false);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   626
        $aclObjectAcesProperty->setAccessible(false);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   627
        $aclObjectFieldAcesProperty->setAccessible(false);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   628
        $aclParentAclProperty->setAccessible(false);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   629
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   630
        // this should never be true if the database integrity hasn't been compromised
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   631
        if ($processed < count($parentIdToFill)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   632
            throw new \RuntimeException('Not all parent ids were populated. This implies an integrity problem.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   633
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   634
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   635
        return $result;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   636
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   637
}