vendor/ibexa/scheduler/src/lib/Menu/ConfigureMenuListener.php line 75

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\Menu;
  8. use Ibexa\AdminUi\Menu\ContentCreateRightSidebarBuilder;
  9. use Ibexa\AdminUi\Menu\ContentEditRightSidebarBuilder;
  10. use Ibexa\AdminUi\Menu\Event\ConfigureMenuEvent;
  11. use Ibexa\Contracts\Core\Limitation\Target;
  12. use Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException;
  13. use Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException;
  14. use Ibexa\Contracts\Core\Repository\LocationService;
  15. use Ibexa\Contracts\Core\Repository\PermissionResolver;
  16. use Ibexa\Contracts\Core\Repository\Values\Content\ContentCreateStruct;
  17. use Ibexa\Contracts\Core\Repository\Values\Content\Language;
  18. use Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo;
  19. use Ibexa\Contracts\Scheduler\Repository\DateBasedPublishServiceInterface;
  20. use JMS\TranslationBundle\Model\Message;
  21. use JMS\TranslationBundle\Translation\TranslationContainerInterface;
  22. use Knp\Menu\ItemInterface;
  23. use Symfony\Contracts\Translation\TranslatorInterface;
  24. class ConfigureMenuListener implements TranslationContainerInterface
  25. {
  26.     public const MENU_DATE_BASED_PUBLISHER 'menu.date_based_publisher';
  27.     public const MENU_DATE_BASED_PUBLISHER_DISCARD 'menu.date_based_publisher.discard';
  28.     /** @var \Ibexa\Contracts\Scheduler\Repository\DateBasedPublishServiceInterface */
  29.     private $dateBasedPublisherService;
  30.     /** @var \Ibexa\Contracts\Core\Repository\PermissionResolver */
  31.     private $permissionResolver;
  32.     /** @var \Symfony\Contracts\Translation\TranslatorInterface */
  33.     private $translator;
  34.     /** @var \Ibexa\Contracts\Core\Repository\LocationService */
  35.     private $locationService;
  36.     /** @var array<string> */
  37.     private array $publishButtonsNames;
  38.     /**
  39.      * @param array<string> $publishButtonsNames
  40.      */
  41.     public function __construct(
  42.         DateBasedPublishServiceInterface $dateBasedPublisherService,
  43.         PermissionResolver $permissionResolver,
  44.         TranslatorInterface $translator,
  45.         LocationService $locationService,
  46.         array $publishButtonsNames = [
  47.             ContentCreateRightSidebarBuilder::ITEM__PUBLISH,
  48.             ContentEditRightSidebarBuilder::ITEM__PUBLISH,
  49.         ]
  50.     ) {
  51.         $this->dateBasedPublisherService $dateBasedPublisherService;
  52.         $this->permissionResolver $permissionResolver;
  53.         $this->translator $translator;
  54.         $this->locationService $locationService;
  55.         $this->publishButtonsNames $publishButtonsNames;
  56.     }
  57.     /**
  58.      * @param \Ibexa\AdminUi\Menu\Event\ConfigureMenuEvent $event
  59.      *
  60.      * @throws \InvalidArgumentException
  61.      * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException
  62.      * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
  63.      */
  64.     public function onAdminUiMenuConfigure(ConfigureMenuEvent $event)
  65.     {
  66.         $root $event->getMenu();
  67.         $options $event->getOptions();
  68.         $publishAttributes = [
  69.             'class' => 'ibexa-btn--extra-actions',
  70.             'data-actions' => 'publish-later',
  71.             'data-focus-element' => '.dbp-publish-later__pick-input',
  72.         ];
  73.         if (!$this->canContentBePublished($options)) {
  74.             $publishAttributes['disabled'] = 'disabled';
  75.         }
  76.         $scheduleLaterOptions = [
  77.             'attributes' => $publishAttributes,
  78.             'extras' => [
  79.                 'translation_domain' => 'ibexa_scheduler',
  80.                 'template' => '@IbexaScheduler/publish_later_widget.html.twig',
  81.                 'orderNumber' => 20,
  82.             ],
  83.         ];
  84.         $this->appendScheduleLaterToMenu($root$scheduleLaterOptions);
  85.         if ($this->shouldAddDiscardItem($options)) {
  86.             $root->addChild(
  87.                 self::MENU_DATE_BASED_PUBLISHER_DISCARD,
  88.                 [
  89.                     'attributes' => [
  90.                         'class' => 'ibexa-btn--trigger',
  91.                         'data-click' => '#ezplatform_content_forms_content_edit_discard_schedule_publish',
  92.                     ],
  93.                     'extras' => [
  94.                         'translation_domain' => 'ibexa_scheduler',
  95.                         'orderNumber' => 30,
  96.                     ],
  97.                 ]
  98.             );
  99.         }
  100.     }
  101.     private function appendScheduleLaterToMenu(ItemInterface $root, array $options)
  102.     {
  103.         $publishItems array_filter(array_map(
  104.             static fn ($buttonName): ?ItemInterface => $root->getChild($buttonName),
  105.             $this->publishButtonsNames
  106.         ));
  107.         if (count($publishItems) > 0) {
  108.             $publishItem current($publishItems);
  109.             $publishItem->addChild(
  110.                 self::MENU_DATE_BASED_PUBLISHER,
  111.                 $options
  112.             );
  113.         } else {
  114.             $root->addChild(
  115.                 self::MENU_DATE_BASED_PUBLISHER,
  116.                 $options
  117.             );
  118.         }
  119.     }
  120.     /**
  121.      * @param \Ibexa\AdminUi\Menu\Event\ConfigureMenuEvent $event
  122.      *
  123.      * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException
  124.      * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
  125.      */
  126.     public function onPageBuilderMenuConfigure(ConfigureMenuEvent $event)
  127.     {
  128.         $root $event->getMenu();
  129.         $options $event->getOptions();
  130.         if ($this->canContentBePublished($options)) {
  131.             $scheduleLaterOptions = [
  132.                 'attributes' => [
  133.                     'class' => 'ibexa-btn--extra-actions',
  134.                     'data-actions' => 'publish-later',
  135.                 ],
  136.                 'extras' => [
  137.                     'translation_domain' => 'ibexa_scheduler',
  138.                     'template' => '@IbexaScheduler/publish_later_widget.html.twig',
  139.                     'orderNumber' => 15,
  140.                 ],
  141.             ];
  142.             $this->appendScheduleLaterToMenu($root$scheduleLaterOptions);
  143.         }
  144.         if ($this->shouldAddDiscardItem($options)) {
  145.             $root->addChild(
  146.                 self::MENU_DATE_BASED_PUBLISHER_DISCARD,
  147.                 [
  148.                     'attributes' => [
  149.                         'class' => 'ibexa-btn--trigger',
  150.                         'data-click' => '#ezplatform_content_forms_content_edit_discard_schedule_publish',
  151.                     ],
  152.                     'extras' => [
  153.                         'translation_domain' => 'ibexa_scheduler',
  154.                         'orderNumber' => 30,
  155.                         'adaptiveItemsForceHide' => true,
  156.                     ],
  157.                 ]
  158.             );
  159.         }
  160.     }
  161.     /**
  162.      * @param array $options
  163.      *
  164.      * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException
  165.      * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
  166.      *
  167.      * @return bool
  168.      */
  169.     private function canContentBePublished(array $options): bool
  170.     {
  171.         $targets = [];
  172.         /** @var \Ibexa\Contracts\Core\Repository\Values\Content\Content $content */
  173.         $content $options['content'] ?? $options['content_create_struct'];
  174.         $locationCreateStruct \array_key_exists('content_create_struct'$options) ? $options['content_create_struct']->getLocationStructs()[0] : [];
  175.         /** @var \Ibexa\Contracts\Core\Repository\Values\Content\Location|null $location */
  176.         $location $options['location'] ?? null;
  177.         if (!empty($locationCreateStruct)) {
  178.             $targets[] = $locationCreateStruct;
  179.         } elseif ($location !== null) {
  180.             $targets[] = $location;
  181.         }
  182.         if (!empty($options['language']) && $options['language'] instanceof Language) {
  183.             $targets[] = (new Target\Builder\VersionBuilder())
  184.                 ->changeStatusTo(VersionInfo::STATUS_PUBLISHED)
  185.                 ->updateFieldsTo($options['language']->languageCode, [])
  186.                 ->build();
  187.         }
  188.         if ($content instanceof ContentCreateStruct && !empty($locationCreateStruct)) {
  189.             try {
  190.                 /** @var \Ibexa\Contracts\Core\Repository\Values\Content\Location $parentLocation */
  191.                 $parentLocation $this->locationService->loadLocation($locationCreateStruct->parentLocationId);
  192.                 $content->sectionId $parentLocation->contentInfo->sectionId;
  193.             } catch (NotFoundException UnauthorizedException $e) {
  194.                 // If any of those exceptions occurs, simply do not set sectionId
  195.             }
  196.         }
  197.         $canPublish $this->permissionResolver->canUser(
  198.             'content',
  199.             'publish',
  200.             $content,
  201.             $targets
  202.         );
  203.         if (!$canPublish) {
  204.             return $canPublish;
  205.         }
  206.         $isPublished $content->contentInfo->published ?? false;
  207.         if ($isPublished) {
  208.             return $this->permissionResolver->canUser(
  209.                 'content',
  210.                 'edit',
  211.                 $content,
  212.                 $targets
  213.             );
  214.         }
  215.         $isDraft = isset($content->contentInfo) && $content->contentInfo->isDraft();
  216.         if (!$isDraft) {
  217.             return $this->permissionResolver->canUser(
  218.                 'content',
  219.                 'create',
  220.                 $content,
  221.                 $targets
  222.             );
  223.         }
  224.         return true;
  225.     }
  226.     /**
  227.      * @param array $options
  228.      *
  229.      * @return bool
  230.      */
  231.     private function shouldAddDiscardItem(array $options): bool
  232.     {
  233.         if (isset($options['content'])) {
  234.             /** @var \Ibexa\Contracts\Core\Repository\Values\Content\Content $content */
  235.             $content $options['content'];
  236.             $scheduledVersions $this->dateBasedPublisherService->getVersionsEntriesForContent($content->id);
  237.             if (\count($scheduledVersions)) {
  238.                 return true;
  239.             }
  240.         }
  241.         return false;
  242.     }
  243.     /**
  244.      * Returns an array of messages.
  245.      *
  246.      * @return array<Message>
  247.      */
  248.     public static function getTranslationMessages()
  249.     {
  250.         return [
  251.             (new Message(self::MENU_DATE_BASED_PUBLISHER'ibexa_scheduler'))->setDesc('Publish later'),
  252.             (new Message(self::MENU_DATE_BASED_PUBLISHER_DISCARD'ibexa_scheduler'))->setDesc(
  253.                 'Discard publish later'
  254.             ),
  255.         ];
  256.     }
  257. }
  258. class_alias(ConfigureMenuListener::class, 'EzSystems\DateBasedPublisher\Core\Menu\ConfigureMenuListener');