vendor/ibexa/scheduler/src/lib/Form/Processor/ContentFormProcessor.php line 130

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\Scheduler\Form\Processor;
  8. use DateTime;
  9. use Exception;
  10. use Ibexa\ContentForms\Data\Content\ContentCreateData;
  11. use Ibexa\ContentForms\Data\Content\ContentUpdateData;
  12. use Ibexa\ContentForms\Event\FormActionEvent;
  13. use Ibexa\Contracts\AdminUi\Notification\TranslatableNotificationHandlerInterface;
  14. use Ibexa\Contracts\Core\Repository\ContentService;
  15. use Ibexa\Contracts\Core\Repository\LocationService;
  16. use Ibexa\Contracts\Core\Repository\Values\Content\Content;
  17. use Ibexa\Contracts\Core\Repository\Values\Content\ContentStruct;
  18. use Ibexa\Contracts\Scheduler\Repository\DateBasedPublishServiceInterface;
  19. use Ibexa\Core\Base\Exceptions\InvalidArgumentException;
  20. use Ibexa\Scheduler\Form\ContentEditTypeExtension;
  21. use Ibexa\Scheduler\Form\Event\ContentEditEvents;
  22. use JMS\TranslationBundle\Annotation\Desc;
  23. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  24. use Symfony\Component\HttpFoundation\RedirectResponse;
  25. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  26. /**
  27.  * Listens for and processes RepositoryForm events.
  28.  */
  29. class ContentFormProcessor implements EventSubscriberInterface
  30. {
  31.     /** @var \Ibexa\Contracts\Core\Repository\ContentService */
  32.     private $contentService;
  33.     /** @var \Ibexa\Contracts\Core\Repository\LocationService */
  34.     private $locationService;
  35.     /** @var \Symfony\Component\Routing\Generator\UrlGeneratorInterface */
  36.     private $urlGenerator;
  37.     /** @var \Ibexa\Contracts\AdminUi\Notification\TranslatableNotificationHandlerInterface */
  38.     private $notificationHandler;
  39.     /** @var \Ibexa\Contracts\Scheduler\Repository\DateBasedPublishServiceInterface */
  40.     private $scheduleService;
  41.     public function __construct(
  42.         ContentService $contentService,
  43.         LocationService $locationService,
  44.         UrlGeneratorInterface $urlGenerator,
  45.         TranslatableNotificationHandlerInterface $notificationHandler,
  46.         DateBasedPublishServiceInterface $scheduleService
  47.     ) {
  48.         $this->contentService $contentService;
  49.         $this->locationService $locationService;
  50.         $this->urlGenerator $urlGenerator;
  51.         $this->notificationHandler $notificationHandler;
  52.         $this->scheduleService $scheduleService;
  53.     }
  54.     /**
  55.      * {@inheritdoc}
  56.      */
  57.     public static function getSubscribedEvents(): array
  58.     {
  59.         return [
  60.             ContentEditEvents::CONTENT_SCHEDULE_PUBLISH => ['processSchedulePublish'10],
  61.             ContentEditEvents::CONTENT_DISCARD_SCHEDULE_PUBLISH => ['processDiscardSchedulePublish'10],
  62.         ];
  63.     }
  64.     public function processDiscardSchedulePublish(FormActionEvent $event): void
  65.     {
  66.         /** @var \Ibexa\ContentForms\Data\Content\ContentCreateData|\Ibexa\ContentForms\Data\Content\ContentUpdateData $data */
  67.         $data $event->getData();
  68.         $form $event->getForm();
  69.         $languageCode $form->getConfig()->getOption('languageCode');
  70.         try {
  71.             $contentDraft $this->saveDraft($data$languageCode);
  72.             $this->scheduleService->unschedulePublish($contentDraft->versionInfo->id);
  73.             $locationId $contentDraft->versionInfo->contentInfo->mainLocationId;
  74.             $contentId $contentDraft->id;
  75.             if (empty($locationId)) {
  76.                 $locations $this->locationService->loadParentLocationsForDraftContent($contentDraft->versionInfo);
  77.                 $location array_shift($locations);
  78.                 $locationId $location->id;
  79.                 $contentId $location->contentId;
  80.             }
  81.             $redirectUrl $this->urlGenerator->generate('ibexa.content.view', [
  82.                 'contentId' => $contentId,
  83.                 'locationId' => $locationId,
  84.             ]);
  85.             $this->notificationHandler->success(
  86.                 /** @Desc("Canceled scheduled publication.") */
  87.                 'date_based_publisher.discard.publish_later',
  88.                 [],
  89.                 'ibexa_scheduler'
  90.             );
  91.             $event->setResponse(new RedirectResponse($redirectUrl));
  92.         } catch (Exception $e) {
  93.             $this->notificationHandler->error(
  94.                 /** @Desc("Cannot cancel future publication: %reason%") */
  95.                 'date_based_publisher.error.discard.publish_later',
  96.                 ['%reason%' => $e->getMessage()],
  97.                 'ibexa_scheduler'
  98.             );
  99.             $event->setResponse(
  100.                 new RedirectResponse(
  101.                     $this->getContentEditUrl($data$languageCode)
  102.                 )
  103.             );
  104.         }
  105.     }
  106.     /**
  107.      * @param \Ibexa\ContentForms\Event\FormActionEvent $event
  108.      *
  109.      * @throws \Ibexa\Core\Base\Exceptions\InvalidArgumentException
  110.      */
  111.     public function processSchedulePublish(FormActionEvent $event): void
  112.     {
  113.         /** @var \Ibexa\ContentForms\Data\Content\ContentCreateData|\Ibexa\ContentForms\Data\Content\ContentUpdateData $data */
  114.         $data $event->getData();
  115.         $form $event->getForm();
  116.         $languageCode $form->getConfig()->getOption('languageCode');
  117.         $scheduleLater $form->get(ContentEditTypeExtension::EXTENSION_NAME);
  118.         try {
  119.             $contentDraft $this->saveDraft($data$languageCode);
  120.             $locationId $contentDraft->versionInfo->contentInfo->mainLocationId;
  121.             $contentId $contentDraft->id;
  122.             $versionId $contentDraft->versionInfo->id;
  123.             if (empty($locationId)) {
  124.                 $locations $this->locationService->loadParentLocationsForDraftContent($contentDraft->versionInfo);
  125.                 $location array_shift($locations);
  126.                 $locationId $location->id;
  127.                 $contentId $location->contentId;
  128.             }
  129.             $redirectUrl $this->urlGenerator->generate('ibexa.content.view', [
  130.                 'contentId' => $contentId,
  131.                 'locationId' => $locationId,
  132.             ]);
  133.             $when DateTime::createFromFormat('U'$scheduleLater['timestamp']->getData());
  134.             if ($this->scheduleService->isScheduledPublish($versionId)) {
  135.                 $scheduledVersion $this->scheduleService->getScheduledPublish($versionId);
  136.                 $this->scheduleService->updateScheduledPublish($scheduledVersion$when);
  137.             } else {
  138.                 $this->scheduleService->schedulePublish($contentDraft->versionInfo$when);
  139.             }
  140.             $this->notificationHandler->success(
  141.                 /** @Desc("Scheduled content for publication.") */
  142.                 'date_based_publisher.success.publish_later',
  143.                 [],
  144.                 'ibexa_scheduler'
  145.             );
  146.             $event->setResponse(new RedirectResponse($redirectUrl));
  147.         } catch (Exception $e) {
  148.             $this->notificationHandler->error(
  149.                 /** @Desc("Cannot schedule content: %reason%") */
  150.                 'date_based_publisher.error.publish_later',
  151.                 ['%reason%' => $e->getMessage()],
  152.                 'ibexa_scheduler'
  153.             );
  154.             $event->setResponse(
  155.                 new RedirectResponse(
  156.                     $this->getContentEditUrl($data$languageCode)
  157.                 )
  158.             );
  159.         }
  160.     }
  161.     /**
  162.      * Saves content draft corresponding to $data.
  163.      * Depending on the nature of $data (create or update data), the draft will either be created or simply updated.
  164.      *
  165.      * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentStruct|\Ibexa\ContentForms\Data\Content\ContentCreateData|\Ibexa\ContentForms\Data\Content\ContentUpdateData $data
  166.      * @param string $languageCode
  167.      *
  168.      * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content
  169.      *
  170.      * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException
  171.      * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
  172.      * @throws \Ibexa\Core\Base\Exceptions\InvalidArgumentException
  173.      * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentValidationException
  174.      * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException
  175.      */
  176.     private function saveDraft(ContentStruct $datastring $languageCode): Content
  177.     {
  178.         if (false === ($data instanceof ContentUpdateData) && false === ($data instanceof ContentCreateData)) {
  179.             throw new InvalidArgumentException(
  180.                 '$data',
  181.                 'Expected ContentUpdateData or ContentCreateData'
  182.             );
  183.         }
  184.         $mainLanguageCode $this->resolveMainLanguageCode($data);
  185.         foreach ($data->fieldsData as $fieldDefIdentifier => $fieldData) {
  186.             if ($mainLanguageCode !== $languageCode && false === $fieldData->fieldDefinition->isTranslatable) {
  187.                 continue;
  188.             }
  189.             $data->setField($fieldDefIdentifier$fieldData->value$languageCode);
  190.         }
  191.         if ($data->isNew()) {
  192.             $contentDraft $this->contentService->createContent($data$data->getLocationStructs());
  193.         } else {
  194.             $contentDraft $this->contentService->updateContent($data->contentDraft->getVersionInfo(), $data);
  195.         }
  196.         return $contentDraft;
  197.     }
  198.     /**
  199.      * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentStruct|\Ibexa\ContentForms\Data\Content\ContentCreateData|\Ibexa\ContentForms\Data\Content\ContentUpdateData $data
  200.      *
  201.      * @return string
  202.      */
  203.     private function resolveMainLanguageCode(ContentStruct $data): string
  204.     {
  205.         return $data->isNew()
  206.             ? $data->mainLanguageCode
  207.             $data->contentDraft->getVersionInfo()->getContentInfo()->mainLanguageCode;
  208.     }
  209.     /**
  210.      * Returns content create or edit URL depending on $data type.
  211.      *
  212.      * @param \Ibexa\ContentForms\Data\Content\ContentData|\Ibexa\ContentForms\Data\Content\ContentCreateData|\Ibexa\ContentForms\Data\Content\ContentUpdateData $data
  213.      * @param string $languageCode
  214.      *
  215.      * @return string
  216.      *
  217.      * @throws \Symfony\Component\Routing\Exception\RouteNotFoundException
  218.      * @throws \Symfony\Component\Routing\Exception\MissingMandatoryParametersException
  219.      * @throws \Symfony\Component\Routing\Exception\InvalidParameterException
  220.      */
  221.     private function getContentEditUrl($datastring $languageCode): string
  222.     {
  223.         return $data->isNew()
  224.             ? $this->urlGenerator->generate('ibexa.content.create.proxy', [
  225.                 'parentLocationId' => $data->getLocationStructs()[0]->parentLocationId,
  226.                 'contentTypeIdentifier' => $data->contentType->identifier,
  227.                 'languageCode' => $languageCode,
  228.             ])
  229.             : $this->urlGenerator->generate('ibexa.content.draft.edit', [
  230.                 'contentId' => $data->contentDraft->id,
  231.                 'versionNo' => $data->contentDraft->getVersionInfo()->versionNo,
  232.                 'language' => $languageCode,
  233.             ]);
  234.     }
  235. }
  236. class_alias(ContentFormProcessor::class, 'EzSystems\DateBasedPublisher\Core\Form\Processor\ContentFormProcessor');