protected function modifyCondition(&$condition) { if (!$condition) { $condition = new Condition(null, $this->jarves); } $languages = $this->jarves->getSystemConfig()->getLanguages(); $languages = preg_replace('/\\W+/', ',', $languages); $languages = explode(',', $languages); foreach ($languages as $lang) { $condition->addOr(['code', '=', $lang]); } }
public function testConditionToSql() { $condition = new Condition(); $condition2 = new Condition(); $condition2->addAnd(['title', '=', 'TestNode tree']); $condition->addAnd($condition2); $condition->addOr(['1', '=', '1']); $params = []; $sql = $this->getConditionOperator()->standardConditionToSql($condition, $params, 'jarves/node'); $expectedArray = [[['title', '=', 'TestNode tree']], 'OR', ['1', '=', '1']]; $this->assertEquals($expectedArray, $condition->toArray()); $this->assertEquals([':p1' => 'TestNode tree'], $params); $this->assertEquals(' system_node.title = :p1 OR 1= 1', $sql); }
/** * Propel uses for his nested-set objects `lft` and `rgt` fields. * So we include with this condition all entries 'inside' the entry * defined through $condition. * * @param Condition $condition * @return Condition */ public function getNestedSubCondition(Condition $condition) { $result = new Condition(null, $this->jarves); $sub = new ConditionSubSelect(null, $this->jarves); $sub->select('sub.lft'); $sub->addSelfJoin('sub', 'sub.lft BETWEEN %table%.lft+1 AND %table%.rgt-1'); $sub->setRules($condition->getRules()); $subCondition = new Condition(); $subCondition->addAnd(['lft', 'IN', $sub]); $result->addAnd($subCondition); return $result; }
/** * @param ACLRequest $aclRequest * * @return bool */ public function check(ACLRequest $aclRequest) { $objectKey = Objects::normalizeObjectKey($aclRequest->getObjectKey()); $targetType = $aclRequest->getTargetType(); $targetId = $aclRequest->getTargetId(); $pk = $aclRequest->getPrimaryKey(); $field = $aclRequest->getField(); $pk = $this->objects->normalizePkString($objectKey, $pk); if (ACL::TARGET_TYPE_USER === $targetType && null === $targetId) { //0 means guest $targetId = $this->pageStack->getUser() ? $this->pageStack->getUser()->getId() : 0; } $user = $this->pageStack->getUser(); if ($user) { $groupIds = $user->getGroupIds(); if (false !== strpos(',' . $groupIds . ',', ',1,')) { //user is in the admin group, so he has always access. return true; } } if (ACL::TARGET_TYPE_USER === $targetType && 1 === $targetId) { //user admin has always access return true; } if (ACL::TARGET_TYPE_GROUP === $targetType && 1 === $targetId) { //group admin has always access return true; } if (0 === $targetId) { //guests do always have no access return false; } if (ACL::TARGET_TYPE_GROUP === $targetType && !$targetId) { throw new \InvalidArgumentException('For type TARGET_TYPE_GROUP a targetId is required.'); } $cacheKey = null; if ($pk && $this->getCaching()) { $pkString = $this->objects->getObjectUrlId($objectKey, $pk); $cacheKey = md5($targetType . '.' . $targetId . '.' . $objectKey . '/' . $pkString . '/' . json_encode($field)); $cached = $this->cacher->getDistributedCache('core/acl/' . $cacheKey); if (null !== $cached) { return $cached; } } $rules = self::getRules($objectKey, $aclRequest->getMode(), $targetType, $targetId); if (count($rules) === 0) { //no rules found, so we have no access return false; } $access = null; $currentObjectPk = $pk; $definition = $this->objects->getDefinition($objectKey); $not_found = true; //starts directly as if we were in the parent checking. $parent_acl = $aclRequest->isAsParent(); $fCount = null; $fKey = null; $fValue = null; $fIsArray = is_array($field); if ($fIsArray) { $fCount = count($field); $fKey = key($field); $fValue = current($field); if (is_int($fKey)) { $fKey = $fValue; $fValue = null; } } $depth = 0; $match = false; $originObjectItemPk = $currentObjectPk; while ($not_found) { $currentObjectPkString = null; if ($currentObjectPk) { $currentObjectPkString = $this->objects->getObjectUrlId($objectKey, $currentObjectPk); } $depth++; if ($depth > 50) { $not_found = false; break; } foreach ($rules as $aclRule) { if ($parent_acl && !$aclRule['sub']) { //as soon we enter the parent_acl mode we only take acl rules into consideration //that are also valid for children (sub=true) continue; } $match = false; /* * CUSTOM CONSTRAINT */ if ($aclRule['constraint_type'] === ACL::CONSTRAINT_CONDITION) { $objectItem = null; if ($originObjectItemPk === $currentObjectPk && null !== $aclRequest->getPrimaryObjectItem()) { $objectItem = $aclRequest->getPrimaryObjectItem(); } else { if ($originObjectItemPk) { $objectItem = $this->objects->get($objectKey, $currentObjectPk); } } if ($objectItem && $this->conditionOperator->satisfy($aclRule['constraint_code'], $objectItem, $objectKey)) { $match = true; } /* * EXACT */ } else { if ($aclRule['constraint_type'] === ACL::CONSTRAINT_EXACT) { if ($currentObjectPk && $aclRule['constraint_code'] === $currentObjectPkString) { $match = true; } /** * ALL */ } else { $match = true; } } if (!$match && $aclRule['sub'] && $currentObjectPk) { // we need to check if a parent matches this $acl as we have sub=true $parentItem = $this->objects->normalizePkString($objectKey, $currentObjectPk); $parentCondition = Condition::create($aclRule['constraint_code']); $parentOptions['fields'] = $this->conditionOperator->extractFields($parentCondition); while ($parentItem = $this->objects->getParent($objectKey, $this->objects->getObjectPk($objectKey, $parentItem), $parentOptions)) { if ($aclRule['constraint_type'] === ACL::CONSTRAINT_CONDITION && $this->conditionOperator->satisfy($parentCondition, $parentItem)) { $match = true; break; } else { if ($aclRule['constraint_type'] === ACL::CONSTRAINT_EXACT && $aclRule['constraint_code'] === $this->objects->getObjectUrlId($objectKey, $parentItem)) { $match = true; break; } } } } if ($match) { //match, check all $field $field2Key = $field; if ($field) { if ($fIsArray && $fCount === 1) { if (is_string($fKey) && is_array($aclRule['fields'][$fKey])) { //this field has limits if (($field2Acl = $aclRule['fields'][$fKey]) !== null) { if (is_array($field2Acl[0])) { //complex field rule, $field2Acl = ([{access: no, condition: [['id', '>', 2], ..]}, {}, ..]) foreach ($field2Acl as $fRule) { $satisfy = false; if (($f = $definition->getField($fKey)) && $f->getType() === 'object') { $uri = $f->getObject() . '/' . $fValue; $uriObject = $this->objects->getFromUrl($uri); $satisfy = $this->conditionOperator->satisfy($fRule['condition'], $uriObject); } else { if (null !== $fValue) { $satisfy = $this->conditionOperator->satisfy($fRule['condition'], $field); } } if ($satisfy) { return $fRule['access'] === 1 ? true : false; } } //if no field rules fits, we consider the whole rule if ($aclRule['access'] !== 2) { return $aclRule['access'] === 1 ? true : false; } } else { //simple field rule $field2Acl = ({"value1": yes, "value2": no} if ($field2Acl[$fKey] !== null) { return $field2Acl[$fKey] === 1 ? true : false; } else { //current($field) is not exactly defined in $field2Acl, so we set $access to $acl['access'] // //if access = 2 then wo do not know it, cause 2 means 'inherited', so maybe //a other rule has more detailed rule if ($aclRule['access'] !== 2) { $access = $aclRule['access'] === 1 ? true : false; break; } } } } } else { //this field has only true or false $field2Key = $fKey; } } if (!is_array($field2Key)) { if ($aclRule['fields'] && ($field2Acl = $aclRule['fields'][$field2Key]) !== null && !is_array($aclRule['fields'][$field2Key])) { $access = $field2Acl === 1 ? true : false; break; } else { //$field is not exactly defined, so we set $access to $acl['access'] //and maybe a rule with the same code has the field defined // if access = 2 then this rule is only for exactly define fields if ($aclRule['access'] !== 2) { $access = $aclRule['access'] === 1 ? true : false; break; } } } } else { $access = $aclRule['access'] === 1 ? true : false; break; } } } //foreach if (null === $access && $definition->isNested() && $pk) { //$access has not defined yet (no rule matched yet). Check if nested and $pk is given //load its root and check again if (null === ($currentObjectPk = $this->objects->getParentPk($objectKey, $currentObjectPk))) { $access = $aclRequest->isRootHasAccess() ? true : $access; break; } $parent_acl = true; } else { break; } } $access = (bool) $access; if ($pk && $this->getCaching()) { $this->cacher->setDistributedCache('core/acl/' . $cacheKey, $access); } return $access; }
/** * @param Condition|array $condition * * @return array */ private function normalizeToArray($condition) { if (!$condition) { return []; } if ($condition instanceof Condition) { return $condition->getRules(); } else { if (!is_array($condition[0]) && !$condition[0] instanceof Condition) { $condition = [$condition]; } return $condition; } }
/** * {@inheritDoc} */ public function getBranch($pk = null, Condition $condition = null, $depth = 1, $scope = null, $options = null) { if ($pk) { $path = $this->getPathFromPK($pk); } else { $path = '/'; } if ($depth === null) { $depth = 1; } try { $files = $this->webFilesystem->getFiles($path); } catch (NotADirectoryException $e) { return null; } $c = 0; // $offset = $options['offset']; // $limit = $options['limit']; $result = array(); $blacklistedFiles = array(); $showHiddenFiles = false; //todo foreach ($files as $file) { $file = $file->toArray(); if (isset($blacklistedFiles[$file['path']]) | (!$showHiddenFiles && substr($file['name'], 0, 1) == '.')) { continue; } if ($condition && $condition->hasRules() && !$condition->satisfy($file, 'jarves/file')) { continue; } $file['writeAccess'] = $this->acl->isUpdatable('jarves/file', array('path' => $file['path'])); $c++; // if ($offset && $offset >= $c) { // continue; // } // if ($limit && $limit < $c) { // break; // } if ($depth > 0) { $children = array(); if ($file['type'] == 'dir') { try { $children = self::getBranch(array('path' => $file['path']), $condition, $depth - 1); } catch (FileNotFoundException $e) { $children = null; } } $file['_childrenCount'] = count($children); if ($depth > 1 && $file['type'] == 'dir') { $file['_children'] = $children; } } $result[] = $file; } return $result; }
/** * {@inheritDoc} */ public function getBranch($pk = null, Condition $condition = null, $depth = 1, $scope = null, $options = null) { $result = null; $path = $pk['path']; if ($depth === null) { $depth = 1; } if ($path) { $path = '@' . trim($path, '/@'); $path = str_replace(':', '/', $path); } $c = 0; $offset = $options['offset']; $limit = $options['limit']; $result = array(); if (!$path) { $result = array(); $bundles = array_keys($this->jarves->getBundles()); foreach ($bundles as $bundleName) { $directory = $this->jarves->resolvePath('@' . $bundleName, 'Resources/views', true); if (!$this->localFilesystem->has($directory)) { continue; } $file = $this->localFilesystem->getFile($directory); if (!$file) { $result[] = $directory; continue; } $file = $file->toArray(); $file['name'] = $bundleName; $file['path'] = $bundleName; if ($offset && $offset > $c) { continue; } if ($limit && $limit < $c) { continue; } if ($condition && $condition->hasRules() && !$this->conditionOperator->satisfy($condition, $file)) { $result[] = $directory; continue; } $c++; if ($depth > 0) { $children = self::getBranch(array('path' => $bundleName), $condition, $depth - 1); $file['_childrenCount'] = count($children); if ($depth > 1 && $file['type'] == 'dir') { $file['_children'] = $children; } } } } else { if (!($bundleName = $this->jarves->getBundleFromPath($path))) { return []; } $directory = $this->jarves->resolvePath($path, 'Resources/views', true) . '/'; if (!$this->localFilesystem->has($directory)) { return []; } $files = $this->localFilesystem->getFiles($directory); foreach ($files as $file) { $item = $file->toArray(); if ($condition && $condition->hasRules() && !$this->conditionOperator->satisfy($condition, $item, 'jarves/file')) { continue; } $c++; if ($offset && $offset >= $c) { continue; } if ($limit && $limit < $c) { continue; } $item = array('name' => $this->buildPath($path . '/' . Tools::getRelativePath($item['path'], $directory)), 'path' => $this->buildPath($path . '/' . Tools::getRelativePath($item['path'], $directory))); if ($file->isDir()) { $children = self::getBranch(array('path' => $item['path']), $condition, $depth - 1); foreach ($children as $child) { // $child['name'] = $item['name'] . '/' . $child['name']; $result[] = $child; } } if ($file->isFile()) { $result[] = $item; } } } return $result; }
public function testExtractFields() { $condition = Condition::create(['title', '=', 'test title']); $fields = $this->getConditionOperator()->extractFields($condition); $this->assertEquals(['title'], $fields); }
/** * @param Condition|array $filter * @param string $query * @return int */ public function getCount($filter, $query = '') { $storageController = $this->objects->getStorageController($this->getObject()); $condition = new Condition(null, $this->jarves); if ($filter && is_array($filter)) { $this->conditionOperator->applyRulesFromPk($condition, $filter, $this->getObject()); } else { if ($filter instanceof Condition) { $condition = $filter; } else { $condition = new Condition(null, $this->jarves); } } if ($limit = $this->getObjectDefinition()->getLimitDataSets()) { $condition->mergeAnd($limit); } if ($this->getPermissionCheck() && ($aclCondition = $this->acl->getListingCondition($this->getObject()))) { $condition->mergeAndBegin($aclCondition); } if ($query) { if ($queryCondition = $this->getQueryCondition($query, $this->getItemsSelection())) { $condition->mergeAnd($queryCondition); } } return $storageController->getCount($condition); }
/** * @param Condition|array $condition * @param array $objectItem * @param string $objectKey * * @return bool|null */ public function satisfy($condition, $objectItem, $objectKey = null) { if (is_array($condition)) { $condition = Condition::create($condition, $this->jarves); } $complied = null; $lastOperator = 'and'; $rules = $condition->getRules(); if (!$rules) { return null; } /* * [ * ['id', '=', 5], * 'or', * ['id', '=', 6] * ] * * [ * Condition, * 'and', * [Condition] * ] * * */ foreach ($rules as $conditionRule) { if (is_string($conditionRule)) { $lastOperator = strtolower($conditionRule); continue; } $res = false; if (is_array($conditionRule) && is_string($conditionRule[0]) && is_string($conditionRule[1])) { $res = $this->checkRule($objectItem, $conditionRule, $objectKey); } else { if ($conditionRule instanceof Condition) { $res = $this->satisfy($conditionRule, $objectItem, $objectKey); } else { if (is_array($conditionRule)) { //group $res = $this->satisfy(Condition::create($conditionRule, $this->jarves), $objectItem, $objectKey); } } } if (is_null($complied)) { $complied = $res; } else { if ($lastOperator == 'and') { $complied = $complied && $res; } if ($lastOperator == 'and not') { $complied = $complied && !$res; } if ($lastOperator == 'or') { $complied = $complied || $res; } } } return $complied === null ? true : ($complied ? true : false); }