/** * Get a new criterion to filter a SQL query by ACL rules * * @param Criteria $criteria * @param mixed $root - root object for list * @return Criterion */ public static function getFilterCriterion($criteria, $root, $action) { $user = sfContext::getInstance()->user; $rootClass = get_class($root); if ('createTerm' != $action) { $permissions = self::getUserPermissionsByAction($user, $rootClass, $action); } else { $permissions = self::getUserPermissionsByAction($user, 'QubitTerm', 'create'); } // Build access control list $allows = $bans = $ids = array(); $forceBan = false; if (0 < count($permissions)) { foreach ($permissions as $permission) { switch ($action) { case 'createTerm': if (null === ($id = $permission->getConstants(array('name' => 'taxonomyId')))) { $ids[] = QubitTaxonomy::ROOT_ID; } break; case 'viewDraft': if (null !== ($repoId = $permission->getConstants(array('name' => 'repositoryId')))) { $criteria2 = new Criteria(); $criteria2->add(QubitInformationObject::REPOSITORY_ID, $repoId); if (0 < count($results = QubitInformationObject::get($criteria2))) { foreach ($results as $item) { $ids[] = $item->id; } // Special case because isAllowed() on ROOT will return true if // user has grant permission on ANY repository. This will force // showing ONLY resources in allowed repositories $forceBan = true; } } break; default: $ids[] = $permission->objectId; } } foreach ($ids as $id) { if (!isset($resourceAccess[$id])) { $resource = call_user_func(array($rootClass, 'getById'), $id); $resourceAccess[$id] = self::isAllowed($user, $resource, $action); if ($resourceAccess[$id]) { $allows[] = $id; } else { $bans[] = $id; } } } } // Special cases - avoid adding unnecessary criteria if (0 == count($allows) && !QubitAcl::isAllowed($user, $root, $action)) { return false; // No allows, always false } else { if (!$forceBan && 0 == count($bans) && QubitAcl::isAllowed($user, $root, $action)) { return true; // No bans, always true } } // If more allows then bans, then add list of allowed resources $criterion = null; if (count($allows) >= count($bans)) { while ($resourceId = array_shift($allows)) { $resource = call_user_func(array($rootClass, 'getById'), $resourceId); // If object has no children include it by id if (1 == $resource->rgt - $resource->lft) { $subCriterion = $criteria->getNewCriterion(constant("{$rootClass}::ID"), $resourceId); } else { $subCriterion = $criteria->getNewCriterion(constant("{$rootClass}::LFT"), $resource->lft, Criteria::GREATER_EQUAL); $subCriterion2 = $criteria->getNewCriterion(constant("{$rootClass}::RGT"), $resource->rgt, Criteria::LESS_EQUAL); $subCriterion->addAnd($subCriterion2); } if (isset($criterion)) { $criterion->addOr($subCriterion); } else { $criterion = $subCriterion; } } } else { while ($resourceId = array_shift($bans)) { $resource = call_user_func(array($rootClass, 'getById'), $resourceId); // If object has no children, remove it by id if (1 == $resource->rgt - $resource->lft) { $subCriterion = $criteria->getNewCriterion(constant("{$rootClass}::ID"), $resourceId, Criteria::NOT_EQUAL); } else { $subCriterion = $criteria->getNewCriterion(constant("{$rootClass}::LFT"), $resource->lft, Criteria::LESS_THAN); $subCriterion2 = $criteria->getNewCriterion(constant("{$rootClass}::RGT"), $resource->rgt, Criteria::GREATER_THAN); $subCriterion->addOr($subCriterion2); } if (isset($criterion)) { $criterion->addAnd($subCriterion); } else { $criterion = $subCriterion; } } } return $criterion; }