vendor/ibexa/permissions/src/lib/EventSubscriber/FieldPermissionCheckSubscriber.php line 60

Open in your IDE?
  1. <?php
  2. /**
  3. * @copyright Copyright (C) Ibexa AS. All rights reserved.
  4. * @license For full copyright and license information view LICENSE file distributed with this source code.
  5. */
  6. declare(strict_types=1);
  7. namespace Ibexa\Permissions\EventSubscriber;
  8. use Ibexa\ContentForms\Event\ContentCreateFieldOptionsEvent;
  9. use Ibexa\ContentForms\Event\ContentFormEvents;
  10. use Ibexa\ContentForms\Event\ContentUpdateFieldOptionsEvent;
  11. use Ibexa\ContentForms\Event\UserCreateFieldOptionsEvent;
  12. use Ibexa\ContentForms\Event\UserUpdateFieldOptionsEvent;
  13. use Ibexa\Contracts\Core\FieldType\Value;
  14. use Ibexa\Contracts\Core\Limitation\Target;
  15. use Ibexa\Contracts\Core\Repository\ContentService;
  16. use Ibexa\Contracts\Core\Repository\LocationService;
  17. use Ibexa\Contracts\Core\Repository\PermissionResolver;
  18. use Ibexa\Contracts\Core\Repository\Values\Content\Field;
  19. use Ibexa\Core\FieldType\User;
  20. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  21. class FieldPermissionCheckSubscriber implements EventSubscriberInterface
  22. {
  23. /** @var \Ibexa\Contracts\Core\Repository\ContentService */
  24. private $contentService;
  25. /** @var \Ibexa\Contracts\Core\Repository\LocationService */
  26. private $locationService;
  27. /** @var \Ibexa\Contracts\Core\Repository\PermissionResolver */
  28. private $permissionResolver;
  29. private User\Type $userType;
  30. public function __construct(
  31. ContentService $contentService,
  32. LocationService $locationService,
  33. PermissionResolver $permissionResolver,
  34. User\Type $userType
  35. ) {
  36. $this->contentService = $contentService;
  37. $this->locationService = $locationService;
  38. $this->permissionResolver = $permissionResolver;
  39. $this->userType = $userType;
  40. }
  41. public static function getSubscribedEvents(): array
  42. {
  43. return [
  44. ContentFormEvents::CONTENT_EDIT_FIELD_OPTIONS => 'onContentEditFieldOptions',
  45. ContentFormEvents::CONTENT_CREATE_FIELD_OPTIONS => 'onContentCreateFieldOptions',
  46. ContentFormEvents::USER_EDIT_FIELD_OPTIONS => 'onUserEditFieldOptions',
  47. ContentFormEvents::USER_CREATE_FIELD_OPTIONS => 'onUserCreateFieldOptions',
  48. ];
  49. }
  50. public function onContentCreateFieldOptions(ContentCreateFieldOptionsEvent $event)
  51. {
  52. $contentCreateStruct = clone $event->getContentCreateStruct();
  53. $contentField = $event->getFieldData()->field;
  54. $contentCreateStruct->fields = [
  55. new Field([
  56. 'id' => $contentField->id,
  57. 'fieldDefIdentifier' => $contentField->fieldDefIdentifier,
  58. 'fieldTypeIdentifier' => $contentField->fieldTypeIdentifier,
  59. 'languageCode' => $contentField->languageCode,
  60. 'value' => new class() implements Value {
  61. public function __get(string $property)
  62. {
  63. return uniqid($property);
  64. }
  65. public function __toString(): string
  66. {
  67. return 'non-empty-value';
  68. }
  69. },
  70. ]),
  71. ];
  72. $locationCreateStructs = $contentCreateStruct->getLocationStructs();
  73. if (empty($contentCreateStruct->sectionId)) {
  74. if (isset($locationCreateStructs[0])) {
  75. $location = $this->locationService->loadLocation(
  76. $locationCreateStructs[0]->parentLocationId
  77. );
  78. $contentCreateStruct->sectionId = $location->contentInfo->sectionId;
  79. } else {
  80. $contentCreateStruct->sectionId = 1;
  81. }
  82. }
  83. if (!$this->permissionResolver->canUser('content', 'create', $contentCreateStruct, $locationCreateStructs)) {
  84. $event->setOption('disabled', true);
  85. }
  86. }
  87. public function onContentEditFieldOptions(ContentUpdateFieldOptionsEvent $event): void
  88. {
  89. $updatedFields = [
  90. $event->getFieldData()->field,
  91. ];
  92. $content = $event->getContent();
  93. $contentUpdateStruct = clone $event->getContentUpdateStruct();
  94. $contentUpdateStruct->fields = $updatedFields;
  95. if (!$this->permissionResolver->canUser(
  96. 'content',
  97. 'edit',
  98. $content,
  99. [
  100. (new Target\Builder\VersionBuilder())
  101. ->updateFields($updatedFields)
  102. ->updateFieldsTo(
  103. $contentUpdateStruct->initialLanguageCode,
  104. $contentUpdateStruct->fields
  105. )
  106. ->build(),
  107. ]
  108. )) {
  109. $event->setOption('disabled', true);
  110. }
  111. }
  112. /**
  113. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
  114. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException
  115. */
  116. public function onUserCreateFieldOptions(UserCreateFieldOptionsEvent $event): void
  117. {
  118. $userCreateStruct = clone $event->getUserCreateStruct();
  119. $contentField = $event->getFieldData()->field;
  120. $parentGroups = $userCreateStruct->getParentGroups();
  121. $locationCreateStructs = [];
  122. /** @var \Ibexa\Contracts\Core\Repository\Values\User\UserGroup $parentGroup */
  123. foreach ($parentGroups as $parentGroup) {
  124. $locationCreateStructs[] = $this->locationService->newLocationCreateStruct(
  125. $parentGroup->getContentInfo()->getMainLocationId()
  126. );
  127. }
  128. $userCreateStruct->fields = [
  129. new Field([
  130. 'id' => $contentField->id,
  131. 'fieldDefIdentifier' => $contentField->fieldDefIdentifier,
  132. 'fieldTypeIdentifier' => $contentField->fieldTypeIdentifier,
  133. 'languageCode' => $contentField->languageCode,
  134. 'value' => $this->userType->getEmptyValue(),
  135. ]),
  136. ];
  137. if (!$this->permissionResolver->canUser('content', 'create', $userCreateStruct, $locationCreateStructs)) {
  138. $event->setOption('disabled', true);
  139. }
  140. }
  141. /**
  142. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
  143. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException
  144. */
  145. public function onUserEditFieldOptions(UserUpdateFieldOptionsEvent $event): void
  146. {
  147. $updatedFields = [
  148. $event->getFieldData()->field,
  149. ];
  150. if (!$this->userCanEditContentField($event, $updatedFields)) {
  151. $event->setOption('disabled', true);
  152. }
  153. }
  154. /**
  155. * @param array<\Ibexa\Contracts\Core\Repository\Values\Content\Field> $fields
  156. *
  157. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
  158. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException
  159. */
  160. private function userCanEditContentField(UserUpdateFieldOptionsEvent $event, array $fields): bool
  161. {
  162. return $this->permissionResolver->canUser(
  163. 'content',
  164. 'edit',
  165. $event->getContent(),
  166. [
  167. (new Target\Builder\VersionBuilder())
  168. ->updateFields($fields)
  169. ->updateFieldsTo(
  170. $event->getOption('languageCode'),
  171. $fields,
  172. )
  173. ->build(),
  174. ]
  175. );
  176. }
  177. }
  178. class_alias(FieldPermissionCheckSubscriber::class, 'Ibexa\Platform\Permissions\EventSubscriber\FieldPermissionCheckSubscriber');