vendor/ibexa/workflow/src/lib/Event/Subscriber/FormProcessor.php line 57

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\Workflow\Event\Subscriber;
  8. use Ibexa\ContentForms\Event\ContentFormEvents;
  9. use Ibexa\ContentForms\Event\FormActionEvent;
  10. use Ibexa\Contracts\Core\Repository\ContentService;
  11. use Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException;
  12. use Ibexa\Contracts\Core\Repository\Values\Content\Content;
  13. use Ibexa\Contracts\Core\Repository\Values\Content\ContentStruct;
  14. use Ibexa\Contracts\Workflow\Registry\WorkflowRegistryInterface;
  15. use Ibexa\Contracts\Workflow\Service\WorkflowServiceInterface;
  16. use Ibexa\Workflow\Exception\NotFoundException;
  17. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  18. use Symfony\Component\HttpFoundation\RedirectResponse;
  19. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  20. class FormProcessor implements EventSubscriberInterface
  21. {
  22. /** @var \Ibexa\Contracts\Core\Repository\ContentService */
  23. private $contentService;
  24. /** @var \Ibexa\Contracts\Workflow\Service\WorkflowServiceInterface */
  25. private $workflowService;
  26. /** @var \Symfony\Component\Routing\Generator\UrlGeneratorInterface */
  27. private $urlGenerator;
  28. /** @var \Ibexa\Contracts\Workflow\Registry\WorkflowRegistryInterface */
  29. private $workflowRegistry;
  30. public function __construct(
  31. ContentService $contentService,
  32. WorkflowServiceInterface $workflowService,
  33. WorkflowRegistryInterface $workflowRegistry,
  34. UrlGeneratorInterface $urlGenerator
  35. ) {
  36. $this->contentService = $contentService;
  37. $this->workflowService = $workflowService;
  38. $this->urlGenerator = $urlGenerator;
  39. $this->workflowRegistry = $workflowRegistry;
  40. }
  41. public static function getSubscribedEvents(): array
  42. {
  43. return [
  44. ContentFormEvents::CONTENT_EDIT => ['onContentEdit', 100],
  45. ];
  46. }
  47. public function onContentEdit(FormActionEvent $event): void
  48. {
  49. $action = $event->getClickedButton();
  50. if ($action !== 'apply') {
  51. return;
  52. }
  53. /** @var \Ibexa\ContentForms\Data\Content\ContentCreateData|\Ibexa\ContentForms\Data\Content\ContentUpdateData $data */
  54. $data = $event->getData();
  55. $form = $event->getForm();
  56. $languageCode = $form->getConfig()->getOption('languageCode');
  57. $draft = $this->saveDraft($event->getData(), $languageCode, []);
  58. $workflowData = $form->get('workflow')->getData();
  59. $workflowName = $workflowData['name'];
  60. $transitionName = $workflowData['transition'];
  61. try {
  62. $workflowMetadata = $this->workflowService->loadWorkflowMetadataForContent($draft, $workflowName);
  63. } catch (NotFoundException $e) {
  64. $workflowMetadata = $this->workflowService->start($draft, $workflowName);
  65. }
  66. if (!$this->workflowService->can($workflowMetadata, $transitionName)) {
  67. // @todo error on transition not possible
  68. // @todo show notification
  69. return;
  70. }
  71. /** @var string $comment */
  72. $comment = $form->get('workflow')->get('comment')->getData() ?? '';
  73. $reviewerId = $form->get('workflow')->get('reviewer')->getData() ?? null;
  74. $workflow = $this->workflowRegistry->getWorkflow($workflowName);
  75. try {
  76. $workflow->apply($workflowMetadata->content, $transitionName, [
  77. 'message' => $comment,
  78. 'reviewerId' => $reviewerId,
  79. ]);
  80. $redirectionUrl = $this->getRedirectionUrl($event, $draft);
  81. } catch (ContentFieldValidationException $e) {
  82. $redirectionUrl = $this->urlGenerator->generate(
  83. 'ibexa.content.draft.edit',
  84. [
  85. 'contentId' => $draft->id,
  86. 'versionNo' => $draft->versionInfo->versionNo,
  87. 'language' => $languageCode,
  88. 'validate' => true,
  89. ]
  90. );
  91. }
  92. $event->setResponse(new RedirectResponse($redirectionUrl));
  93. }
  94. /**
  95. * Saves content draft corresponding to $data.
  96. * Depending on the nature of $data (create or update data), the draft will either be created or simply updated.
  97. *
  98. * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentStruct|\Ibexa\ContentForms\Data\Content\ContentCreateData|\Ibexa\ContentForms\Data\Content\ContentUpdateData $data
  99. * @param string $languageCode
  100. *
  101. * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content
  102. *
  103. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException
  104. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
  105. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
  106. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentValidationException
  107. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException
  108. */
  109. private function saveDraft(ContentStruct $data, string $languageCode, ?array $fieldIdentifiersToValidate = null): Content
  110. {
  111. $mainLanguageCode = $data->isNew()
  112. ? $data->mainLanguageCode
  113. : $data->contentDraft->getVersionInfo()->getContentInfo()->mainLanguageCode;
  114. foreach ($data->fieldsData as $fieldDefIdentifier => $fieldData) {
  115. if ($mainLanguageCode !== $languageCode && !$fieldData->fieldDefinition->isTranslatable) {
  116. continue;
  117. }
  118. $data->setField($fieldDefIdentifier, $fieldData->value, $languageCode);
  119. }
  120. if ($data->isNew()) {
  121. $contentDraft = $this->contentService->createContent($data, $data->getLocationStructs(), $fieldIdentifiersToValidate);
  122. } else {
  123. $contentDraft = $this->contentService->updateContent($data->contentDraft->getVersionInfo(), $data, $fieldIdentifiersToValidate);
  124. }
  125. return $contentDraft;
  126. }
  127. /**
  128. * @param \Ibexa\Contracts\AdminUi\Event\FormActionEvent $event
  129. * @param \Ibexa\Contracts\Core\Repository\Values\Content\Content $draft
  130. *
  131. * @return string
  132. */
  133. private function getRedirectionUrl(FormActionEvent $event, Content $draft): string
  134. {
  135. $referrerLocation = $event->getOption('referrerLocation');
  136. $contentInfo = $draft->contentInfo;
  137. if ($contentInfo->isPublished()) {
  138. $redirectionUrl = $this->urlGenerator->generate(
  139. 'ibexa.content.view',
  140. [
  141. 'contentId' => $referrerLocation ? $referrerLocation->contentId : $contentInfo->id,
  142. 'locationId' => $referrerLocation ? $referrerLocation->id : $contentInfo->mainLocationId,
  143. ]
  144. );
  145. } else {
  146. $redirectionUrl = $this->urlGenerator->generate('ibexa.dashboard');
  147. }
  148. return $redirectionUrl;
  149. }
  150. }
  151. class_alias(FormProcessor::class, 'EzSystems\EzPlatformWorkflow\Event\Subscriber\FormProcessor');