public function updateUserContext(UserContext $context) { $user = $this->repository->getCurrentUser(); /** @var \eZ\Publish\API\Repository\Values\User\RoleAssignment[] $roleAssignments */ $roleAssignments = $this->repository->sudo(function (Repository $repository) use($user) { return $repository->getRoleService()->getRoleAssignmentsForUser($user, true); }); $roleIds = array(); $limitationValues = array(); /** @var UserRoleAssignment $roleAssignment */ foreach ($roleAssignments as $roleAssignment) { $roleId = $roleAssignment->getRole()->id; $roleIds[] = $roleId; $limitation = $roleAssignment->getRoleLimitation(); // If a limitation is present, store the limitation values by roleId if ($limitation !== null) { $limitationValuesKey = sprintf('%s-%s', $roleId, $limitation->getIdentifier()); $limitationValues[$limitationValuesKey] = array(); foreach ($limitation->limitationValues as $value) { $limitationValues[$limitationValuesKey][] = $value; } } } $context->addParameter('roleIdList', $roleIds); $context->addParameter('roleLimitationList', $limitationValues); }
public function setIdentity(Identity $identity) { $user = $this->repository->getCurrentUser(); $roleAssignments = $this->repository->sudo(function ($repository) use($user) { return $repository->getRoleService()->getRoleAssignmentsForUser($user, true); }); $roleIds = array(); $limitationValues = array(); /** @var UserRoleAssignment $roleAssignment */ foreach ($roleAssignments as $roleAssignment) { $roleIds[] = $roleAssignment->role->id; // If a limitation is present, store the limitation values by roleId if ($roleAssignment->limitation !== null) { $limitationValuesKey = "{$roleAssignment->role->id}-" . $roleAssignment->limitation->getIdentifier(); $limitationValues[$limitationValuesKey] = array(); foreach ($roleAssignment->limitation->limitationValues as $value) { $limitationValues[$limitationValuesKey][] = $value; } } } $identity->setInformation('roleIdList', implode('|', $roleIds)); // Flatten each limitation values to a string and then store it as Identity information $limitationValuesFlattened = array(); foreach ($limitationValues as $roleId => $limitationArray) { $limitationValuesFlattened[] = "{$roleId}:" . implode('|', $limitationArray); } $identity->setInformation('roleLimitationList', implode(',', $limitationValuesFlattened)); }
public function loadLocation(ContentInfo $contentInfo) { if (is_null($contentInfo->mainLocationId)) { throw new NotFoundException('main location of content', $contentInfo->id); } try { return $this->repository->sudo(function (Repository $repository) use($contentInfo) { return $repository->getLocationService()->loadLocation($contentInfo->mainLocationId); }); } catch (Exception $e) { throw new NotFoundException('main location of content', $contentInfo->id); } }
public function userIsSubscriber(User $user) { $roleService = $this->repository->getRoleService(); return $this->repository->sudo(function (Repository $repository) use($user, $roleService) { foreach ($repository->getUserService()->loadUserGroupsOfUser($user) as $group) { foreach ($roleService->getRoleAssignmentsForUserGroup($group) as $role) { if ($this->isSubscriberRole($role->role)) { return true; } } } return false; }); }
/** * Removes a relation of type COMMON from a draft. * * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed edit this version * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the version is not a draft * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if there is no relation of type COMMON for the given destination * * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $sourceVersion * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $destinationContent */ public function deleteRelation(APIVersionInfo $sourceVersion, ContentInfo $destinationContent) { $sourceVersion = $this->loadVersionInfoById($sourceVersion->contentInfo->id, $sourceVersion->versionNo); if ($sourceVersion->status !== APIVersionInfo::STATUS_DRAFT) { throw new BadStateException('$sourceVersion', 'Relations of type common can only be removed from versions of status draft'); } if (!$this->repository->canUser('content', 'edit', $sourceVersion)) { throw new UnauthorizedException('content', 'edit', array('contentId' => $sourceVersion->contentInfo->id)); } $spiRelations = $this->persistenceHandler->contentHandler()->loadRelations($sourceVersion->getContentInfo()->id, $sourceVersion->versionNo, APIRelation::COMMON); if (empty($spiRelations)) { throw new InvalidArgumentException('$sourceVersion', 'There are no relations of type COMMON for the given destination'); } // there should be only one relation of type COMMON for each destination, // but in case there were ever more then one, we will remove them all // @todo: alternatively, throw BadStateException? $this->repository->beginTransaction(); try { foreach ($spiRelations as $spiRelation) { if ($spiRelation->destinationContentId == $destinationContent->id) { $this->persistenceHandler->contentHandler()->removeRelation($spiRelation->id, APIRelation::COMMON); } } $this->repository->commit(); } catch (Exception $e) { $this->repository->rollback(); throw $e; } }
/** * Loads a location by its locationId, regardless to user limitations since the router is invoked BEFORE security (no user authenticated yet). * Not to be used for link generation. * * @param int $locationId * * @return \eZ\Publish\Core\Repository\Values\Content\Location */ public function loadLocation($locationId) { return $this->repository->sudo(function (Repository $repository) use($locationId) { /* @var $repository \eZ\Publish\Core\Repository\Repository */ return $repository->getLocationService()->loadLocation($locationId); }); }
/** * Deletes $location and all its descendants. * * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user is not allowed to delete this location or a descendant * * @param \eZ\Publish\API\Repository\Values\Content\Location $location */ public function deleteLocation(APILocation $location) { $location = $this->loadLocation($location->id); if (!$this->repository->canUser('content', 'manage_locations', $location->getContentInfo())) { throw new UnauthorizedException('content', 'manage_locations'); } if (!$this->repository->canUser('content', 'remove', $location->getContentInfo(), $location)) { throw new UnauthorizedException('content', 'remove'); } /** Check remove access to descendants * @var boolean|\eZ\Publish\API\Repository\Values\Content\Query\Criterion $contentReadCriterion */ $contentReadCriterion = $this->permissionsCriterionHandler->getPermissionsCriterion('content', 'remove'); if ($contentReadCriterion === false) { throw new UnauthorizedException('content', 'remove'); } else { if ($contentReadCriterion !== true) { // Query if there are any content in subtree current user don't have access to $query = new Query(array('limit' => 0, 'filter' => new CriterionLogicalAnd(array(new CriterionSubtree($location->pathString), new CriterionLogicalNot($contentReadCriterion))))); $result = $this->repository->getSearchService()->findContent($query, array(), false); if ($result->totalCount > 0) { throw new UnauthorizedException('content', 'remove'); } } } $this->repository->beginTransaction(); try { $this->persistenceHandler->locationHandler()->removeSubtree($location->id); $this->persistenceHandler->urlAliasHandler()->locationDeleted($location->id); $this->repository->commit(); } catch (Exception $e) { $this->repository->rollback(); throw $e; } }
/** * Performs a query for a single content object * * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if the object was not found by the query or due to permissions * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if criterion is not valid * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if there is more than one result matching the criterions * * @todo define structs for the field filters * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $filter * @param array $fieldFilters - a map of filters for the returned fields. * Currently supports: <code>array("languages" => array(<language1>,..), "useAlwaysAvailable" => bool)</code> * useAlwaysAvailable defaults to true to avoid exceptions on missing translations. * @param boolean $filterOnUserPermissions if true only the objects which is the user allowed to read are returned. * * @return \eZ\Publish\API\Repository\Values\Content\Content */ public function findSingle(Criterion $filter, array $fieldFilters = array(), $filterOnUserPermissions = true) { $this->validateContentCriteria(array($filter), "\$filter"); if ($filterOnUserPermissions && !$this->permissionsCriterionHandler->addPermissionsCriterion($filter)) { throw new NotFoundException('Content', '*'); } $contentInfo = $this->searchHandler->findSingle($filter, $fieldFilters); return $this->repository->getContentService()->loadContent($contentInfo->id, !empty($fieldFilters['languages']) ? $fieldFilters['languages'] : null, null, isset($fieldFilters['useAlwaysAvailable']) ? $fieldFilters['useAlwaysAvailable'] : true); }
public function onContentCacheClear(ContentCacheClearEvent $event) { $contentInfo = $event->getContentInfo(); $versionInfo = $this->contentService->loadVersionInfo($contentInfo); foreach ($this->contentService->loadRelations($versionInfo) as $relation) { foreach ($this->locationService->loadLocations($relation->getDestinationContentInfo()) as $relatedLocation) { $event->addLocationToClear($relatedLocation); } } // Using sudo since loading reverse relations is conditioned to content/reverserelatedlist permission and we don't need this check here. /** @var \eZ\Publish\API\Repository\Values\Content\Relation[] $reverseRelations */ $reverseRelations = $this->repository->sudo(function () use($contentInfo) { return $this->contentService->loadReverseRelations($contentInfo); }); foreach ($reverseRelations as $reverseRelation) { foreach ($this->locationService->loadLocations($reverseRelation->getSourceContentInfo()) as $relatedLocation) { $event->addLocationToClear($relatedLocation); } } }
/** * Checks embed permissions for the given Location $id and returns the Location. * * @throws \Symfony\Component\Security\Core\Exception\AccessDeniedException * * @param int|string $id * * @return \eZ\Publish\API\Repository\Values\Content\Location */ protected function checkLocation($id) { /** @var \eZ\Publish\API\Repository\Values\Content\Location $location */ $location = $this->repository->sudo(function (Repository $repository) use($id) { return $repository->getLocationService()->loadLocation($id); }); // Check both 'content/read' and 'content/view_embed'. if (!$this->authorizationChecker->isGranted(new AuthorizationAttribute('content', 'read', array('valueObject' => $location->contentInfo, 'targets' => $location))) && !$this->authorizationChecker->isGranted(new AuthorizationAttribute('content', 'view_embed', array('valueObject' => $location->contentInfo, 'targets' => $location)))) { throw new AccessDeniedException(); } return $location; }
/** * Validates sort clauses of a given $query. * * For the moment this validates only Field sort clauses. * Valid Field sort clause provides $languageCode if targeted field is translatable, * and the same in reverse - it does not provide $languageCode for non-translatable field. * * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If sort clauses are not valid * * @param \eZ\Publish\API\Repository\Values\Content\Query $query * * @return void */ protected function validateSortClauses(Query $query) { foreach ($query->sortClauses as $key => $sortClause) { if (!$sortClause instanceof SortClause\Field && !$sortClause instanceof SortClause\MapLocationDistance) { continue; } /** @var \eZ\Publish\API\Repository\Values\Content\Query\SortClause\Target\FieldTarget|\eZ\Publish\API\Repository\Values\Content\Query\SortClause\Target\MapLocationTarget $fieldTarget */ $fieldTarget = $sortClause->targetData; $contentType = $this->repository->getContentTypeService()->loadContentTypeByIdentifier($fieldTarget->typeIdentifier); if ($contentType->getFieldDefinition($fieldTarget->fieldIdentifier)->isTranslatable) { if ($fieldTarget->languageCode === null) { throw new InvalidArgumentException("\$query->sortClauses[{$key}]", "No language is specified for translatable field"); } } else { if ($fieldTarget->languageCode !== null) { throw new InvalidArgumentException("\$query->sortClauses[{$key}]", "Language is specified for non-translatable field, null should be used instead"); } } } }
protected function fetchSingleAnyDepthChildrenContent(Location $location, $contentTypeIdentifierList = null, $sortClauseList = null, $additionalCriterionList = array()) { $query = $this->getAnyDepthChildrenLocationQuery($location, $contentTypeIdentifierList, 0, $sortClauseList, $additionalCriterionList, 1); return $this->fetchSingleContentFromSearchResult($this->repository->getSearchService()->findLocations($query)); }
/** * Setup test */ protected function setUp() { parent::setUp(); $this->repository = static::getRepository(); $this->repository->setCurrentUser($this->getStubbedUser(14)); }