/**
     * Apply the ACL constraints to the specified query builder, using the permission definition
     *
     * @param QueryBuilder         $queryBuilder  The query builder
     * @param PermissionDefinition $permissionDef The permission definition
     *
     * @return QueryBuilder
     */
    public function apply(QueryBuilder $queryBuilder, PermissionDefinition $permissionDef)
    {
        $aclConnection = $this->em->getConnection();
        $databasePrefix = is_file($aclConnection->getDatabase()) ? '' : $aclConnection->getDatabase() . '.';
        $rootEntity = $permissionDef->getEntity();
        $linkAlias = $permissionDef->getAlias();
        // Only tables with a single ID PK are currently supported
        $linkField = $this->em->getClassMetadata($rootEntity)->getSingleIdentifierColumnName();
        $rootEntity = '"' . str_replace('\\', '\\\\', $rootEntity) . '"';
        $query = $queryBuilder;
        $builder = new MaskBuilder();
        foreach ($permissionDef->getPermissions() as $permission) {
            $mask = constant(get_class($builder) . '::MASK_' . strtoupper($permission));
            $builder->add($mask);
        }
        $mask = $builder->get();
        /* @var $token TokenInterface */
        $token = $this->tokenStorage->getToken();
        $userRoles = array();
        if (!is_null($token)) {
            $user = $token->getUser();
            $userRoles = $this->roleHierarchy->getReachableRoles($token->getRoles());
        }
        // Security context does not provide anonymous role automatically.
        $uR = array('"IS_AUTHENTICATED_ANONYMOUSLY"');
        /* @var $role RoleInterface */
        foreach ($userRoles as $role) {
            // The reason we ignore this is because by default FOSUserBundle adds ROLE_USER for every user
            if ($role->getRole() !== 'ROLE_USER') {
                $uR[] = '"' . $role->getRole() . '"';
            }
        }
        $uR = array_unique($uR);
        $inString = implode(' OR s.identifier = ', (array) $uR);
        if (is_object($user)) {
            $inString .= ' OR s.identifier = "' . str_replace('\\', '\\\\', get_class($user)) . '-' . $user->getUserName() . '"';
        }
        $joinTableQuery = <<<SELECTQUERY
SELECT DISTINCT o.object_identifier as id FROM {$databasePrefix}acl_object_identities as o
INNER JOIN {$databasePrefix}acl_classes c ON c.id = o.class_id
LEFT JOIN {$databasePrefix}acl_entries e ON (
    e.class_id = o.class_id AND (e.object_identity_id = o.id
    OR {$aclConnection->getDatabasePlatform()->getIsNullExpression('e.object_identity_id')})
)
LEFT JOIN {$databasePrefix}acl_security_identities s ON (
s.id = e.security_identity_id
)
WHERE c.class_type = {$rootEntity}
AND (s.identifier = {$inString})
AND e.mask & {$mask} > 0
SELECTQUERY;
        $query->join($linkAlias, '(' . $joinTableQuery . ')', 'perms_', 'perms_.id = ' . $linkAlias . '.' . $linkField);
        return $query;
    }
 /**
  * Apply the ACL constraints to the specified query builder, using the permission definition
  *
  * @param QueryBuilder         $queryBuilder  The query builder
  * @param PermissionDefinition $permissionDef The permission definition
  *
  * @return Query
  */
 public function apply(QueryBuilder $queryBuilder, PermissionDefinition $permissionDef)
 {
     $whereQueryParts = $queryBuilder->getDQLPart('where');
     if (empty($whereQueryParts)) {
         $queryBuilder->where('1 = 1');
         // this will help in cases where no where query is specified
     }
     $query = $this->cloneQuery($queryBuilder->getQuery());
     $builder = new MaskBuilder();
     foreach ($permissionDef->getPermissions() as $permission) {
         $mask = constant(get_class($builder) . '::MASK_' . strtoupper($permission));
         $builder->add($mask);
     }
     $query->setHint('acl.mask', $builder->get());
     $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Kunstmaan\\AdminBundle\\Helper\\Security\\Acl\\AclWalker');
     $rootEntity = $permissionDef->getEntity();
     $rootAlias = $permissionDef->getAlias();
     // If either alias or entity was not specified - use default from QueryBuilder
     if (empty($rootEntity) || empty($rootAlias)) {
         $rootEntities = $queryBuilder->getRootEntities();
         $rootAliases = $queryBuilder->getRootAliases();
         $rootEntity = $rootEntities[0];
         $rootAlias = $rootAliases[0];
     }
     $query->setHint('acl.root.entity', $rootEntity);
     $query->setHint('acl.extra.query', $this->getPermittedAclIdsSQLForUser($query));
     $classMeta = $this->em->getClassMetadata($rootEntity);
     $entityRootTableName = $this->quoteStrategy->getTableName($classMeta, $this->em->getConnection()->getDatabasePlatform());
     $query->setHint('acl.entityRootTableName', $entityRootTableName);
     $query->setHint('acl.entityRootTableDqlAlias', $rootAlias);
     return $query;
 }
 /**
  * @covers Kunstmaan\AdminBundle\Helper\Security\Acl\Permission\PermissionDefinition::setAlias
  * @covers Kunstmaan\AdminBundle\Helper\Security\Acl\Permission\PermissionDefinition::getAlias
  */
 public function testSetGetAlias()
 {
     $this->object->setAlias('alias');
     $this->assertEquals('alias', $this->object->getAlias());
 }