From 06860b629b92b6060465ef6768862e42bffff900 Mon Sep 17 00:00:00 2001 From: Bartek Wajda Date: Tue, 7 Nov 2023 17:05:59 +0100 Subject: [PATCH] IBX-6592: Allowed `Location` to be a part of permission check for Object State assignment --- .../Controller/ObjectStateController.php | 13 +++-- src/bundle/Resources/config/routing.yaml | 2 +- .../admin/content/tab/details.html.twig | 3 +- .../ContentObjectStateUpdateData.php | 53 +++++++------------ .../ContentObjectStateUpdateType.php | 25 +++++---- src/lib/Tab/LocationView/DetailsTab.php | 20 +++---- src/lib/UI/Dataset/ObjectStatesDataset.php | 17 ++---- src/lib/UI/Value/ValueFactory.php | 15 +++--- 8 files changed, 71 insertions(+), 77 deletions(-) diff --git a/src/bundle/Controller/ObjectStateController.php b/src/bundle/Controller/ObjectStateController.php index e816001cb3..b06ebcec8e 100644 --- a/src/bundle/Controller/ObjectStateController.php +++ b/src/bundle/Controller/ObjectStateController.php @@ -307,7 +307,8 @@ public function updateAction(Request $request, ObjectState $objectState): Respon public function updateContentStateAction( Request $request, ContentInfo $contentInfo, - ObjectStateGroup $objectStateGroup + ObjectStateGroup $objectStateGroup, + Location $location ): Response { if (!$this->permissionResolver->hasAccess('state', 'assign')) { $exception = $this->createAccessDeniedException(); @@ -319,7 +320,7 @@ public function updateContentStateAction( $form = $this->formFactory->create( ContentObjectStateUpdateType::class, - new ContentObjectStateUpdateData($contentInfo, $objectStateGroup) + new ContentObjectStateUpdateData($contentInfo, $objectStateGroup, null, $location) ); $form->handleRequest($request); @@ -328,7 +329,13 @@ public function updateContentStateAction( $contentInfo = $data->getContentInfo(); $objectStateGroup = $data->getObjectStateGroup(); $objectState = $data->getObjectState(); - $this->objectStateService->setContentState($contentInfo, $objectStateGroup, $objectState); + $location = $data->getLocation(); + $this->objectStateService->setContentState( + $contentInfo, + $objectStateGroup, + $objectState, + $location + ); $this->notificationHandler->success( /** @Desc("Content item's Object state changed to '%name%'.") */ diff --git a/src/bundle/Resources/config/routing.yaml b/src/bundle/Resources/config/routing.yaml index 682891d70d..b1c22cd69c 100644 --- a/src/bundle/Resources/config/routing.yaml +++ b/src/bundle/Resources/config/routing.yaml @@ -821,7 +821,7 @@ ezplatform.object_state.state.bulk_delete: _controller: 'EzSystems\EzPlatformAdminUiBundle\Controller\ObjectStateController::bulkDeleteAction' ezplatform.object_state.contentstate.update: - path: /state/contentstate/update/{contentInfoId}/group/{objectStateGroupId} + path: /state/contentstate/update/{contentInfoId}/group/{objectStateGroupId}/{locationId} defaults: _controller: 'EzSystems\EzPlatformAdminUiBundle\Controller\ObjectStateController::updateContentStateAction' diff --git a/src/bundle/Resources/views/themes/admin/content/tab/details.html.twig b/src/bundle/Resources/views/themes/admin/content/tab/details.html.twig index 105c515d88..e4a1ce6b4c 100644 --- a/src/bundle/Resources/views/themes/admin/content/tab/details.html.twig +++ b/src/bundle/Resources/views/themes/admin/content/tab/details.html.twig @@ -125,7 +125,8 @@ 'method': 'POST', 'action': path('ezplatform.object_state.contentstate.update', { 'contentInfoId': content_info.id, - 'objectStateGroupId': object_state.objectStateGroup.id + 'objectStateGroupId': object_state.objectStateGroup.id, + 'locationId': location.id, }), 'attr': {'class': 'form-inline ez-form-inline ez-form-inline--align-left'} }) }} diff --git a/src/lib/Form/Data/ObjectState/ContentObjectStateUpdateData.php b/src/lib/Form/Data/ObjectState/ContentObjectStateUpdateData.php index 2ccb84d544..7b8dbbfe9c 100644 --- a/src/lib/Form/Data/ObjectState/ContentObjectStateUpdateData.php +++ b/src/lib/Form/Data/ObjectState/ContentObjectStateUpdateData.php @@ -9,86 +9,73 @@ namespace EzSystems\EzPlatformAdminUi\Form\Data\ObjectState; use eZ\Publish\API\Repository\Values\Content\ContentInfo; +use eZ\Publish\API\Repository\Values\Content\Location; use eZ\Publish\API\Repository\Values\ObjectState\ObjectState; use eZ\Publish\API\Repository\Values\ObjectState\ObjectStateGroup; class ContentObjectStateUpdateData { - /** - * @var \eZ\Publish\API\Repository\Values\Content\ContentInfo - */ + /** @var \eZ\Publish\API\Repository\Values\Content\ContentInfo|null */ private $contentInfo; - /** - * @var \eZ\Publish\API\Repository\Values\ObjectState\ObjectStateGroup - */ + /** @var \eZ\Publish\API\Repository\Values\ObjectState\ObjectStateGroup|null */ private $objectStateGroup; - /** - * @var \eZ\Publish\API\Repository\Values\ObjectState\ObjectState - */ + /** @var \eZ\Publish\API\Repository\Values\ObjectState\ObjectState|null rm -r*/ private $objectState; - /** - * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo|null $contentInfo - * @param \eZ\Publish\API\Repository\Values\ObjectState\ObjectStateGroup|null $objectStateGroup - * @param \eZ\Publish\API\Repository\Values\ObjectState\ObjectState|null $objectState - */ + /** @var \eZ\Publish\API\Repository\Values\Content\Location|null */ + private $location; + public function __construct( ContentInfo $contentInfo = null, ObjectStateGroup $objectStateGroup = null, - ObjectState $objectState = null + ObjectState $objectState = null, + Location $location = null ) { $this->contentInfo = $contentInfo; $this->objectStateGroup = $objectStateGroup; $this->objectState = $objectState; + $this->location = $location; } - /** - * @return \eZ\Publish\API\Repository\Values\Content\ContentInfo - */ public function getContentInfo(): ContentInfo { return $this->contentInfo; } - /** - * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo - */ public function setContentInfo(ContentInfo $contentInfo) { $this->contentInfo = $contentInfo; } - /** - * @return \eZ\Publish\API\Repository\Values\ObjectState\ObjectStateGroup - */ public function getObjectStateGroup(): ObjectStateGroup { return $this->objectStateGroup; } - /** - * @param \eZ\Publish\API\Repository\Values\ObjectState\ObjectStateGroup $objectStateGroup - */ public function setObjectStateGroup(ObjectStateGroup $objectStateGroup) { $this->objectStateGroup = $objectStateGroup; } - /** - * @return \eZ\Publish\API\Repository\Values\ObjectState\ObjectState|null - */ public function getObjectState(): ?ObjectState { return $this->objectState; } - /** - * @param \eZ\Publish\API\Repository\Values\ObjectState\ObjectState $objectState - */ public function setObjectState(ObjectState $objectState) { $this->objectState = $objectState; } + + public function getLocation(): ?Location + { + return $this->location; + } + + public function setLocation(Location $location) + { + $this->location = $location; + } } diff --git a/src/lib/Form/Type/ObjectState/ContentObjectStateUpdateType.php b/src/lib/Form/Type/ObjectState/ContentObjectStateUpdateType.php index f419ae7af1..85470084d2 100644 --- a/src/lib/Form/Type/ObjectState/ContentObjectStateUpdateType.php +++ b/src/lib/Form/Type/ObjectState/ContentObjectStateUpdateType.php @@ -60,20 +60,25 @@ public function buildForm(FormBuilderInterface $builder, array $options) $contentObjectStateUpdateData = $event->getData(); $objectStateGroup = $contentObjectStateUpdateData->getObjectStateGroup(); $contentInfo = $contentObjectStateUpdateData->getContentInfo(); + $location = $contentObjectStateUpdateData->getLocation(); $form = $event->getForm(); $form->add('objectState', ObjectStateChoiceType::class, [ 'label' => false, - 'choice_loader' => new CallbackChoiceLoader(function () use ($objectStateGroup, $contentInfo) { - $contentState = $this->objectStateService->getContentState($contentInfo, $objectStateGroup); - - return array_filter( - $this->objectStateService->loadObjectStates($objectStateGroup), - function (ObjectState $objectState) use ($contentInfo, $contentState) { - return $this->permissionResolver->canUser('state', 'assign', $contentInfo, [$objectState]); - } - ); - }), + 'choice_loader' => new CallbackChoiceLoader( + function () use ($objectStateGroup, $contentInfo, $location) { + return array_filter( + $this->objectStateService->loadObjectStates($objectStateGroup), + function (ObjectState $objectState) use ($contentInfo, $location) { + return $this->permissionResolver->canUser( + 'state', + 'assign', + $contentInfo, + [$location, $objectState], + ); + } + ); + }), ]); }); } diff --git a/src/lib/Tab/LocationView/DetailsTab.php b/src/lib/Tab/LocationView/DetailsTab.php index b439ea0892..cca0d6e878 100644 --- a/src/lib/Tab/LocationView/DetailsTab.php +++ b/src/lib/Tab/LocationView/DetailsTab.php @@ -133,7 +133,7 @@ public function getTemplateParameters(array $contextParameters = []): array ]); $this->supplySectionParameters($viewParameters, $contentInfo, $location); - $this->supplyObjectStateParameters($viewParameters, $contentInfo); + $this->supplyObjectStateParameters($viewParameters, $contentInfo, $location); $this->supplyTranslations($viewParameters, $versionInfo); $this->supplyFormLocationUpdate($viewParameters, $location); $this->supplyCreator($viewParameters, $contentInfo); @@ -185,14 +185,13 @@ private function supplyLastContributor(ArrayObject $parameters, VersionInfo $ver } } - /** - * @param \ArrayObject $parameters - * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo - */ - private function supplyObjectStateParameters(ArrayObject &$parameters, ContentInfo $contentInfo): void - { + private function supplyObjectStateParameters( + ArrayObject &$parameters, + ContentInfo $contentInfo, + Location $location + ): void { $objectStatesDataset = $this->datasetFactory->objectStates(); - $objectStatesDataset->load($contentInfo); + $objectStatesDataset->load($contentInfo, $location); $canAssignObjectState = $this->canUserAssignObjectState(); @@ -206,7 +205,10 @@ private function supplyObjectStateParameters(ArrayObject &$parameters, ContentIn $objectStateUpdateForm = $this->formFactory->create( ContentObjectStateUpdateType::class, new ContentObjectStateUpdateData( - $contentInfo, $objectStateGroup, $objectState + $contentInfo, + $objectStateGroup, + $objectState, + $location, ) )->createView(); diff --git a/src/lib/UI/Dataset/ObjectStatesDataset.php b/src/lib/UI/Dataset/ObjectStatesDataset.php index 941de114b1..31a31f8ed8 100644 --- a/src/lib/UI/Dataset/ObjectStatesDataset.php +++ b/src/lib/UI/Dataset/ObjectStatesDataset.php @@ -10,6 +10,7 @@ use eZ\Publish\API\Repository\ObjectStateService; use eZ\Publish\API\Repository\Values\Content\ContentInfo; +use eZ\Publish\API\Repository\Values\Content\Location; use eZ\Publish\API\Repository\Values\ObjectState\ObjectStateGroup; use EzSystems\EzPlatformAdminUi\UI\Value as UIValue; use EzSystems\EzPlatformAdminUi\UI\Value\ValueFactory; @@ -25,31 +26,21 @@ class ObjectStatesDataset /** @var UIValue\ObjectState\ObjectState[] */ protected $data; - /** - * @param \eZ\Publish\API\Repository\ObjectStateService $objectStateService - * @param \EzSystems\EzPlatformAdminUi\UI\Value\ValueFactory $valueFactory - */ public function __construct(ObjectStateService $objectStateService, ValueFactory $valueFactory) { $this->objectStateService = $objectStateService; $this->valueFactory = $valueFactory; } - - /** - * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo - * - * @return ObjectStatesDataset - */ - public function load(ContentInfo $contentInfo): self + public function load(ContentInfo $contentInfo, Location $location): self { $data = array_map( - function (ObjectStateGroup $objectStateGroup) use ($contentInfo) { + function (ObjectStateGroup $objectStateGroup) use ($contentInfo, $location) { $hasObjectStates = !empty($this->objectStateService->loadObjectStates($objectStateGroup)); if (!$hasObjectStates) { return []; } - return $this->valueFactory->createObjectState($contentInfo, $objectStateGroup); + return $this->valueFactory->createObjectState($contentInfo, $objectStateGroup, $location); }, $this->objectStateService->loadObjectStateGroups() ); diff --git a/src/lib/UI/Value/ValueFactory.php b/src/lib/UI/Value/ValueFactory.php index 3012135ec0..7c5a783272 100644 --- a/src/lib/UI/Value/ValueFactory.php +++ b/src/lib/UI/Value/ValueFactory.php @@ -253,22 +253,23 @@ public function createLocation(Location $location): UIValue\Content\Location } /** - * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo - * @param \eZ\Publish\API\Repository\Values\ObjectState\ObjectStateGroup $objectStateGroup - * - * @return UIValue\ObjectState\ObjectState - * * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException */ public function createObjectState( ContentInfo $contentInfo, - ObjectStateGroup $objectStateGroup + ObjectStateGroup $objectStateGroup, + Location $location ): UIValue\ObjectState\ObjectState { $objectState = $this->objectStateService->getContentState($contentInfo, $objectStateGroup); return new UIValue\ObjectState\ObjectState($objectState, [ - 'userCanAssign' => $this->permissionResolver->canUser('state', 'assign', $contentInfo, [$objectState]), + 'userCanAssign' => $this->permissionResolver->canUser( + 'state', + 'assign', + $contentInfo, + [$location, $objectState], + ), ]); }