Skip to content

Commit

Permalink
Merge pull request #1706 from ezsystems/fix-EZP-25280-parent-depth-co…
Browse files Browse the repository at this point in the history
…ntent-create-6.4

Fix EZP-25280: ParentDepth Limitation fails on content creation
  • Loading branch information
pspanja authored Jul 1, 2016
2 parents d5e19b1 + 7ae302b commit d9bf9e6
Show file tree
Hide file tree
Showing 4 changed files with 558 additions and 11 deletions.
2 changes: 1 addition & 1 deletion bin/.travis/prepare_unittest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ COMPOSER_UPDATE=""
# solr package search API integration tests
if [ "$TEST_CONFIG" = "phpunit-integration-legacy-solr.xml" ] ; then
echo "> Require ezsystems/ezplatform-solr-search-engine:dev-master"
composer require --no-update ezsystems/ezplatform-solr-search-engine:dev-master
composer require --no-update ezsystems/ezplatform-solr-search-engine:^1.0.0@dev
COMPOSER_UPDATE="true"
fi

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ class ParentDepthLimitationTest extends BaseLimitationTest
*
* @see \eZ\Publish\API\Repository\Values\User\Limitation\ContentTypeLimitation
* @see \eZ\Publish\API\Repository\Values\User\Limitation\ParentDepthLimitation
*
* @expectedException \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
*/
public function testParentDepthLimitationAllow()
public function testParentDepthLimitationForbid()
{
$repository = $this->getRepository();

Expand All @@ -45,7 +47,7 @@ public function testParentDepthLimitationAllow()
$policyCreate = $roleService->newPolicyCreateStruct('content', 'create');
$policyCreate->addLimitation(
new ParentDepthLimitation(
array('limitationValues' => array(2))
array('limitationValues' => array(3))
)
);
$policyCreate->addLimitation(
Expand Down Expand Up @@ -74,9 +76,8 @@ public function testParentDepthLimitationAllow()
*
* @see \eZ\Publish\API\Repository\Values\User\Limitation\ContentTypeLimitation
* @see \eZ\Publish\API\Repository\Values\User\Limitation\ParentDepthLimitation
* @expectedException \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
*/
public function testParentDepthLimitationForbid()
public function testParentDepthLimitationAllow()
{
$repository = $this->getRepository();

Expand All @@ -91,7 +92,7 @@ public function testParentDepthLimitationForbid()
$policyCreate = $roleService->newPolicyCreateStruct('content', 'create');
$policyCreate->addLimitation(
new ParentDepthLimitation(
array('limitationValues' => array(1, 3, 4))
array('limitationValues' => array(1, 2, 3, 4))
)
);
$policyCreate->addLimitation(
Expand All @@ -109,4 +110,50 @@ public function testParentDepthLimitationForbid()
$this->createWikiPageDraft();
/* END: Use Case */
}

/**
* Tests a combination of ParentDepthLimitation and ContentTypeLimitation.
*
* @depends testParentDepthLimitationAllow
*
* @see \eZ\Publish\API\Repository\Values\User\Limitation\ContentTypeLimitation
* @see \eZ\Publish\API\Repository\Values\User\Limitation\ParentDepthLimitation
*/
public function testParentDepthLimitationAllowPublish()
{
$repository = $this->getRepository();

$contentTypeId = $this->generateId('contentType', 22);
/* BEGIN: Use Case */
$user = $this->createUserVersion1();

$roleService = $repository->getRoleService();

$role = $roleService->loadRoleByIdentifier('Editor');

$policyCreate = $roleService->newPolicyCreateStruct('content', 'create');
$policyCreate->addLimitation(
new ParentDepthLimitation(
array('limitationValues' => array(1, 2, 3, 4))
)
);
$policyCreate->addLimitation(
new ContentTypeLimitation(
array('limitationValues' => array($contentTypeId))
)
);

$role = $roleService->addPolicy($role, $policyCreate);

$roleService->assignRoleToUser($role, $user);

$repository->setCurrentUser($user);

$draft = $this->createWikiPageDraft();

$contentService = $repository->getContentService();

$content = $contentService->publishVersion($draft->versionInfo);
/* END: Use Case */
}
}
75 changes: 70 additions & 5 deletions eZ/Publish/Core/Limitation/ParentDepthLimitationType.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@

use eZ\Publish\API\Repository\Values\ValueObject;
use eZ\Publish\API\Repository\Values\User\UserReference as APIUserReference;
use eZ\Publish\API\Repository\Values\Content\Content;
use eZ\Publish\API\Repository\Values\Content\ContentCreateStruct;
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
use eZ\Publish\API\Repository\Values\Content\Location;
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
use eZ\Publish\API\Repository\Values\Content\VersionInfo;
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException;
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentType;
use eZ\Publish\API\Repository\Values\User\Limitation\ParentDepthLimitation as APIParentDepthLimitation;
Expand Down Expand Up @@ -102,23 +106,84 @@ public function evaluate(APILimitationValue $value, APIUserReference $currentUse
throw new InvalidArgumentException('$value', 'Must be of type: APIParentDepthLimitation');
}

// Parent Limitations are usually used by content/create where target is specified, so we return false if not provided.
if ($object instanceof ContentCreateStruct) {
return $this->evaluateForContentCreateStruct($value, $targets);
} elseif ($object instanceof Content) {
$object = $object->getVersionInfo()->getContentInfo();
} elseif ($object instanceof VersionInfo) {
$object = $object->getContentInfo();
} elseif (!$object instanceof ContentInfo) {
throw new InvalidArgumentException(
'$object',
'Must be of type: ContentCreateStruct, Content, VersionInfo or ContentInfo'
);
}

// Load locations if no specific placement was provided
if (empty($targets)) {
if ($object->published) {
$targets = $this->persistence->locationHandler()->loadLocationsByContent($object->id);
} else {
// @todo Need support for draft locations to to work correctly
$targets = $this->persistence->locationHandler()->loadParentLocationsForDraftContent($object->id);
}
}

// Parent Limitations are usually used by content/create where target is specified,
// so we return false if not provided.
if (empty($targets)) {
return false;
}

foreach ($targets as $target) {
if ($target instanceof LocationCreateStruct) {
$depth = $this->persistence->locationHandler()->load($target->parentLocationId)->depth;
} elseif ($target instanceof Location || $target instanceof SPILocation) {
if ($target instanceof Location || $target instanceof SPILocation) {
$depth = $target->depth;
} else {
throw new InvalidArgumentException(
'$targets',
'Must contain objects of type: Location or LocationCreateStruct'
'Must contain objects of type: Location'
);
}

// All placements must match
if (!in_array($depth, $value->limitationValues)) {
return false;
}
}

return true;
}

/**
* Evaluate permissions for ContentCreateStruct against LocationCreateStruct placements.
*
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If $targets does not contain
* objects of type LocationCreateStruct
*
* @param \eZ\Publish\API\Repository\Values\User\Limitation $value
* @param array|null $targets
*
* @return bool
*/
protected function evaluateForContentCreateStruct(APILimitationValue $value, array $targets = null)
{
// If targets is empty/null return false as user does not have access
// to content w/o location with this limitation
if (empty($targets)) {
return false;
}

foreach ($targets as $target) {
if (!$target instanceof LocationCreateStruct) {
throw new InvalidArgumentException(
'$targets',
'If $object is ContentCreateStruct must contain objects of type: LocationCreateStruct'
);
}

$depth = $this->persistence->locationHandler()->load($target->parentLocationId)->depth;

// All placements must match
if (!in_array($depth, $value->limitationValues)) {
return false;
}
Expand Down
Loading

0 comments on commit d9bf9e6

Please # to comment.