Exponential 5.x Kernel 7.5.40 Exponential New Stack (Symfony-based) Kernel — PHP Class Reference

ObjectStateLimitationType.php
Go to the documentation of this file.
1 <?php
2
7 namespace eZ\Publish\Core\Limitation;
8
9 use eZ\Publish\API\Repository\Exceptions\NotFoundException as APINotFoundException;
10 use eZ\Publish\API\Repository\Exceptions\NotImplementedException;
11 use eZ\Publish\API\Repository\Values\ValueObject;
12 use eZ\Publish\API\Repository\Values\User\UserReference as APIUserReference;
13 use eZ\Publish\API\Repository\Values\Content\Content;
14 use eZ\Publish\API\Repository\Values\Content\ContentInfo;
15 use eZ\Publish\API\Repository\Values\Content\ContentCreateStruct;
16 use eZ\Publish\API\Repository\Values\Content\VersionInfo;
17 use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException;
18 use eZ\Publish\Core\Base\Exceptions\InvalidArgumentType;
19 use eZ\Publish\Core\Base\Exceptions\BadStateException;
20 use eZ\Publish\API\Repository\Values\User\Limitation\ObjectStateLimitation as APIObjectStateLimitation;
21 use eZ\Publish\API\Repository\Values\User\Limitation as APILimitationValue;
22 use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
23 use eZ\Publish\SPI\Limitation\Type as SPILimitationTypeInterface;
24 use eZ\Publish\Core\FieldType\ValidationError;
25 use eZ\Publish\SPI\Persistence\Content\ObjectState\Group;
26 use eZ\Publish\SPI\Persistence\Content\ObjectState\Handler;
27 use RuntimeException;
28
32 class ObjectStateLimitationType extends AbstractPersistenceLimitationType implements SPILimitationTypeInterface
33 {
43 public function acceptValue(APILimitationValue $limitationValue)
44 {
45 if (!$limitationValue instanceof APIObjectStateLimitation) {
46 throw new InvalidArgumentType('$limitationValue', 'APIObjectStateLimitation', $limitationValue);
47 }
48
49 if (!is_array($limitationValue->limitationValues)) {
50 throw new InvalidArgumentType('$limitationValue->limitationValues', 'array', $limitationValue->limitationValues);
51 }
52
53 foreach ($limitationValue->limitationValues as $key => $id) {
54 if (!is_string($id) && !is_int($id)) {
55 throw new InvalidArgumentType("\$limitationValue->limitationValues[{$key}]", 'int|string', $id);
56 }
57 }
58 }
59
69 public function validate(APILimitationValue $limitationValue)
70 {
71 $validationErrors = [];
72 foreach ($limitationValue->limitationValues as $key => $id) {
73 try {
74 $this->persistence->objectStateHandler()->load($id);
75 } catch (APINotFoundException $e) {
76 $validationErrors[] = new ValidationError(
77 "limitationValues[%key%] => '%value%' does not exist in the backend",
78 null,
79 [
80 'value' => $id,
81 'key' => $key,
82 ]
83 );
84 }
85 }
86
87 return $validationErrors;
88 }
89
97 public function buildValue(array $limitationValues)
98 {
99 return new APIObjectStateLimitation(['limitationValues' => $limitationValues]);
100 }
101
117 public function evaluate(APILimitationValue $value, APIUserReference $currentUser, ValueObject $object, array $targets = null): bool
118 {
119 if (!$value instanceof APIObjectStateLimitation) {
120 throw new InvalidArgumentException('$value', 'Must be of type: APIObjectStateLimitation');
121 }
122
123 if (empty($value->limitationValues)) {
124 return false;
125 }
126 $limitationValues = array_map('intval', $value->limitationValues);
127
128 $objectStateHandler = $this->persistence->objectStateHandler();
129 if (!$object instanceof ContentCreateStruct) {
130 $contentInfo = $this->getContentInfo($object);
131 // Skip evaluating for RootLocation
132 if (1 === $contentInfo->mainLocationId) {
133 return true;
134 }
135
136 $objectStateIdsToVerify = $this->getObjectStateIdsToVerify(
137 $objectStateHandler,
138 $contentInfo,
139 $limitationValues
140 );
141 } else {
142 @trigger_error(
143 'Passing ContentCreateStruct to ObjectStateLimitationType is deprecated ' .
144 ' and will throw an error in Ibexa 5.0',
145 E_USER_DEPRECATED
146 );
147
148 $objectStateIdsToVerify = $this->getObjectStateIdsForContentCreate(
149 $objectStateHandler,
150 $limitationValues
151 );
152 }
153
154 return $this->areObjectStatesMatchingTheLimitation($objectStateIdsToVerify, $limitationValues);
155 }
156
165 private function isStateGroupUsedForLimitation($stateGroupId, array $limitationValues)
166 {
167 $objectStateHandler = $this->persistence->objectStateHandler();
168 $states = $objectStateHandler->loadObjectStates($stateGroupId);
169
170 foreach ($states as $state) {
171 // check using loose types as limitation values are strings and id's can be int
172 if (in_array($state->id, $limitationValues)) {
173 return true;
174 }
175 }
176
177 return false;
178 }
179
188 private function areObjectStatesMatchingTheLimitation(
189 array $objectStateIds,
190 array $limitationValues
191 ): bool {
192 foreach ($objectStateIds as $objectStateId) {
193 if (!in_array($objectStateId, $limitationValues, true)) {
194 return false;
195 }
196 }
197
198 return true;
199 }
200
209 public function getCriterion(APILimitationValue $value, APIUserReference $currentUser)
210 {
211 if (empty($value->limitationValues)) {
212 // no limitation values
213 throw new RuntimeException('$value->limitationValues is empty, it should not have been stored in the first place');
214 }
215
216 if (!isset($value->limitationValues[1])) {
217 // 1 limitation value: EQ operation
218 return new Criterion\ObjectStateId($value->limitationValues[0]);
219 }
220
221 $groupedLimitationValues = $this->groupLimitationValues($value->limitationValues);
222
223 if (count($groupedLimitationValues) === 1) {
224 // one group, several limitation values: IN operation
225 return new Criterion\ObjectStateId($groupedLimitationValues[0]);
226 }
227
228 // limitations from different groups require logical AND between them
229 $criterions = [];
230 foreach ($groupedLimitationValues as $limitationGroup) {
231 $criterions[] = new Criterion\ObjectStateId($limitationGroup);
232 }
233
234 return new Criterion\LogicalAnd($criterions);
235 }
236
244 private function groupLimitationValues(array $limitationValues)
245 {
246 $objectStateHandler = $this->persistence->objectStateHandler();
247 $stateGroups = $objectStateHandler->loadAllGroups();
248 $groupedLimitationValues = [];
249 foreach ($stateGroups as $stateGroup) {
250 $states = $objectStateHandler->loadObjectStates($stateGroup->id);
251 $stateIds = array_map(function ($state) {
252 return $state->id;
253 }, $states);
254 $limitationValuesGroup = array_intersect($stateIds, $limitationValues);
255 if (!empty($limitationValuesGroup)) {
256 $groupedLimitationValues[] = array_values($limitationValuesGroup);
257 }
258 }
259
260 return $groupedLimitationValues;
261 }
262
266 public function valueSchema()
267 {
268 throw new NotImplementedException(__METHOD__);
269 }
270
274 private function getContentInfo(ValueObject $object): ContentInfo
275 {
276 if ($object instanceof Content) {
277 $object = $object->getVersionInfo()->getContentInfo();
278 } elseif ($object instanceof VersionInfo) {
279 $object = $object->getContentInfo();
280 } elseif (!$object instanceof ContentInfo) {
281 throw new InvalidArgumentException(
282 '$object',
283 'Must be of type: Content, VersionInfo, ContentInfo, or ContentCreateStruct'
284 );
285 }
286
287 return $object;
288 }
289
297 private function getObjectStateIdsForContentCreate(
298 Handler $objectStateHandler,
299 array $limitationValues
300 ): array {
301 $objectStateIdsToVerify = [];
302 $stateGroups = $objectStateHandler->loadAllGroups();
303 foreach ($stateGroups as $stateGroup) {
304 $states = $objectStateHandler->loadObjectStates($stateGroup->id);
305 if (empty($states)) {
306 continue;
307 }
308
309 $defaultStateId = $this->getDefaultStateId($states, $stateGroup);
310
311 foreach ($states as $state) {
312 // check using loose types as limitation values are strings and id's can be int
313 if (in_array($state->id, $limitationValues, true)) {
314 $objectStateIdsToVerify[] = $defaultStateId;
315 }
316 }
317 }
318
319 return $objectStateIdsToVerify;
320 }
321
327 private function getDefaultStateId(array $states, Group $stateGroup): int
328 {
329 $defaultStateId = null;
330 $defaultStatePriority = -1;
331 foreach ($states as $state) {
332 if ($state->priority > $defaultStatePriority) {
333 $defaultStateId = $state->id;
334 $defaultStatePriority = $state->priority;
335 }
336 }
337
338 if ($defaultStateId === null) {
339 throw new BadStateException(
340 '$defaultStateId',
341 "Could not find a default state for object state group {$stateGroup->id}"
342 );
343 }
344
345 return $defaultStateId;
346 }
347
348 private function getObjectStateIdsToVerify(
349 Handler $objectStateHandler,
350 ContentInfo $object,
351 array $limitationValues
352 ): array {
353 $objectStateIdsToVerify = [];
354 $stateGroups = $objectStateHandler->loadAllGroups();
355 foreach ($stateGroups as $stateGroup) {
356 if ($this->isStateGroupUsedForLimitation($stateGroup->id, $limitationValues)) {
357 $objectStateIdsToVerify[] = $objectStateHandler->getContentState(
358 $object->id,
359 $stateGroup->id
360 )->id;
361 }
362 }
363
364 return $objectStateIdsToVerify;
365 }
366 }
eZ\Publish\API\Repository\Exceptions\NotFoundException
This Exception is thrown if an object referenced by an id or identifier could not be found in the rep...
Definition: API/Repository/Exceptions/NotFoundException.php:16
eZ\Publish\API\Repository\Exceptions\NotImplementedException
This Exception is thrown if a feature has not been implemented intentionally.
Definition: API/Repository/Exceptions/NotImplementedException.php:15
eZ\Publish\API\Repository\Values\Content\ContentCreateStruct
Definition: API/Repository/Values/Content/ContentCreateStruct.php:15
eZ\Publish\API\Repository\Values\Content\ContentInfo
Definition: API/Repository/Values/Content/ContentInfo.php:31
eZ\Publish\API\Repository\Values\Content\Content
Definition: Publish/API/Repository/Values/Content/Content.php:21
eZ\Publish\API\Repository\Values\Content\VersionInfo
Definition: API/Repository/Values/Content/VersionInfo.php:27
eZ\Publish\API\Repository\Values\User\Limitation\ObjectStateLimitation
Class ObjectStateLimitation.
Definition: ObjectStateLimitation.php:19
eZ\Publish\API\Repository\Values\ValueObject
Definition: API/Repository/Values/ValueObject.php:21
eZ\Publish\Core\Base\Exceptions\BadStateException
BadState Exception implementation.
Definition: Core/Base/Exceptions/BadStateException.php:20
eZ\Publish\Core\Base\Exceptions\InvalidArgumentException
Invalid Argument Type Exception implementation.
Definition: Core/Base/Exceptions/InvalidArgumentException.php:20
eZ\Publish\Core\Base\Exceptions\InvalidArgumentType
Invalid Argument Type Exception implementation.
Definition: InvalidArgumentType.php:17
eZ\Publish\Core\FieldType\ValidationError
Class for validation errors.
Definition: Core/FieldType/ValidationError.php:17
eZ\Publish\Core\Limitation\AbstractPersistenceLimitationType
LocationLimitation is a Content limitation.
Definition: AbstractPersistenceLimitationType.php:15
eZ\Publish\Core\Limitation\ObjectStateLimitationType
ObjectStateLimitation is a Content limitation.
Definition: ObjectStateLimitationType.php:33
eZ\Publish\Core\Limitation\ObjectStateLimitationType\getContentInfo
getContentInfo(ValueObject $object)
Definition: ObjectStateLimitationType.php:274
eZ\Publish\Core\Limitation\ObjectStateLimitationType\groupLimitationValues
groupLimitationValues(array $limitationValues)
Groups limitation values by the State Group.
Definition: ObjectStateLimitationType.php:244
eZ\Publish\Core\Limitation\ObjectStateLimitationType\valueSchema
valueSchema()
Definition: ObjectStateLimitationType.php:266
eZ\Publish\Core\Limitation\ObjectStateLimitationType\acceptValue
acceptValue(APILimitationValue $limitationValue)
Accepts a Limitation value and checks for structural validity.
Definition: ObjectStateLimitationType.php:43
eZ\Publish\Core\Limitation\ObjectStateLimitationType\validate
validate(APILimitationValue $limitationValue)
Makes sure LimitationValue->limitationValues is valid according to valueSchema().
Definition: ObjectStateLimitationType.php:69
eZ\Publish\Core\Limitation\ObjectStateLimitationType\getCriterion
getCriterion(APILimitationValue $value, APIUserReference $currentUser)
Returns Criterion for use in find() query.
Definition: ObjectStateLimitationType.php:209
eZ\Publish\Core\Limitation\ObjectStateLimitationType\isStateGroupUsedForLimitation
isStateGroupUsedForLimitation($stateGroupId, array $limitationValues)
Checks if the State Group contains at least one State that is used by Limitation.
Definition: ObjectStateLimitationType.php:165
eZ\Publish\Core\Limitation\ObjectStateLimitationType\getDefaultStateId
getDefaultStateId(array $states, Group $stateGroup)
Definition: ObjectStateLimitationType.php:327
eZ\Publish\Core\Limitation\ObjectStateLimitationType\getObjectStateIdsForContentCreate
getObjectStateIdsForContentCreate(Handler $objectStateHandler, array $limitationValues)
Definition: ObjectStateLimitationType.php:297
eZ\Publish\Core\Limitation\ObjectStateLimitationType\buildValue
buildValue(array $limitationValues)
Create the Limitation Value.
Definition: ObjectStateLimitationType.php:97
eZ\Publish\Core\Limitation\ObjectStateLimitationType\evaluate
evaluate(APILimitationValue $value, APIUserReference $currentUser, ValueObject $object, array $targets=null)
Evaluate permission against content & target(placement/parent/assignment).
Definition: ObjectStateLimitationType.php:117
eZ\Publish\Core\Limitation\ObjectStateLimitationType\areObjectStatesMatchingTheLimitation
areObjectStatesMatchingTheLimitation(array $objectStateIds, array $limitationValues)
Verifies if all the Object States are matching the Limitation Values.
Definition: ObjectStateLimitationType.php:188
eZ\Publish\Core\Limitation\ObjectStateLimitationType\getObjectStateIdsToVerify
getObjectStateIdsToVerify(Handler $objectStateHandler, ContentInfo $object, array $limitationValues)
Definition: ObjectStateLimitationType.php:348
eZ\Publish\SPI\Persistence\Content\ObjectState\Group
This class represents a persistent object state group.
Definition: ObjectState/Group.php:15
eZ\Publish\API\Repository\Values\User\UserReference
This interface represents a user reference for use in sessions and Repository.
Definition: API/Repository/Values/User/UserReference.php:13
eZ\Publish\SPI\Limitation\Type
This interface represent the Limitation Type.
Definition: SPI/Limitation/Type.php:22
eZ\Publish\SPI\Persistence\Content\ObjectState\Handler
The Object State Handler interface provides managing of object states and groups.
Definition: SPI/Persistence/Content/ObjectState/Handler.php:13
eZ\Publish\SPI\Persistence\Content\ObjectState\Handler\getContentState
getContentState($contentId, $stateGroupId)
Gets the object-state of object identified by $contentId.
eZ\Publish\SPI\Persistence\Content\ObjectState\Handler\loadObjectStates
loadObjectStates($groupId)
This method returns the ordered list of object states of a group.
eZ\Publish\SPI\Persistence\Content\ObjectState\Handler\loadAllGroups
loadAllGroups($offset=0, $limit=-1)
Loads all object state groups.
eZ\Publish\API\Repository\Values\Content\Query\Criterion
Definition: API/Repository/Values/Content/Query/Criterion/Ancestor.php:7
eZ\Publish\API\Repository\Values\User\Limitation
Definition: BlockingLimitation.php:7
eZ\Publish\Core\Limitation
Definition: AbstractPersistenceLimitationType.php:7
Copyright © 1998 – 2026 7x. All rights reserved. Licensed under the GNU GPLv2+.