vendor/ibexa/workflow/src/lib/Event/Subscriber/AbstractMenuSubscriber.php line 147

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\AdminUi\Menu\ContentCreateRightSidebarBuilder;
  9. use Ibexa\AdminUi\Menu\ContentEditRightSidebarBuilder;
  10. use Ibexa\AdminUi\Menu\Event\ConfigureMenuEvent;
  11. use Ibexa\Contracts\Core\Repository\PermissionResolver;
  12. use Ibexa\Contracts\Core\Repository\Values\ValueObject;
  13. use Ibexa\Contracts\Workflow\Registry\WorkflowDefinitionMetadataRegistryInterface;
  14. use Ibexa\Contracts\Workflow\Registry\WorkflowRegistryInterface;
  15. use Knp\Menu\FactoryInterface;
  16. use Knp\Menu\ItemInterface;
  17. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  18. use Symfony\Component\Workflow\Exception\LogicException;
  19. use Symfony\Component\Workflow\Workflow;
  20. abstract class AbstractMenuSubscriber implements EventSubscriberInterface
  21. {
  22.     protected const PUBLISH_MENU_ITEMS = [
  23.         ContentCreateRightSidebarBuilder::ITEM__PUBLISH,
  24.         ContentEditRightSidebarBuilder::ITEM__PUBLISH,
  25.     ];
  26.     /** @var \Knp\Menu\FactoryInterface */
  27.     private $menuFactory;
  28.     /** @var \Ibexa\Contracts\Workflow\Registry\WorkflowRegistryInterface */
  29.     private $workflowRegistry;
  30.     /** @var \Ibexa\Workflow\Factory\Registry\WorkflowDefinitionMetadataRegistryFactory */
  31.     private $workflowDefinitionMetadataRegistry;
  32.     /** @var \Ibexa\Contracts\Core\Repository\PermissionResolver */
  33.     private $permissionResolver;
  34.     public function __construct(
  35.         FactoryInterface $menuFactory,
  36.         WorkflowRegistryInterface $workflowRegistry,
  37.         WorkflowDefinitionMetadataRegistryInterface $workflowDefinitionMetadataRegistry,
  38.         PermissionResolver $permissionResolver
  39.     ) {
  40.         $this->menuFactory $menuFactory;
  41.         $this->workflowRegistry $workflowRegistry;
  42.         $this->workflowDefinitionMetadataRegistry $workflowDefinitionMetadataRegistry;
  43.         $this->permissionResolver $permissionResolver;
  44.     }
  45.     private function getWorkflows(ValueObject $subject): array
  46.     {
  47.         $workflows $this->workflowRegistry->getSupportedWorkflows($subject);
  48.         return $this->filterWorkflows($workflows$subject);
  49.     }
  50.     public function addTransitionButtonsToContentEdit(ConfigureMenuEvent $event): void
  51.     {
  52.         $root $event->getMenu();
  53.         $options $event->getOptions();
  54.         /** @var \Ibexa\Contracts\Core\Repository\Values\Content\Content $content */
  55.         $content $options['content'];
  56.         $workflows $this->getWorkflows($content);
  57.         $workflowMenuItems = [];
  58.         foreach ($workflows as $workflow) {
  59.             $workflowMenuItems array_replace(
  60.                 $workflowMenuItems,
  61.                 $this->createWorkflowMenuItems($workflow$workflow->getEnabledTransitions($content), $options)
  62.             );
  63.         }
  64.         $root->setChildren(array_replace($workflowMenuItems$root->getChildren()));
  65.     }
  66.     public function addTransitionButtonsToContentCreate(ConfigureMenuEvent $event): void
  67.     {
  68.         $root $event->getMenu();
  69.         $options $event->getOptions();
  70.         /** @var \Ibexa\Contracts\Core\Repository\Values\Content\ContentCreateStruct $contentCreateStruct */
  71.         $contentCreateStruct $options['content_create_struct'];
  72.         $workflows $this->getWorkflows($contentCreateStruct);
  73.         $workflowMenuItems = [];
  74.         foreach ($workflows as $workflow) {
  75.             $workflowMenuItems array_replace(
  76.                 $workflowMenuItems,
  77.                 $this->createWorkflowMenuItems($workflow$workflow->getEnabledTransitions($contentCreateStruct), $options)
  78.             );
  79.         }
  80.         $root->setChildren(array_replace($workflowMenuItems$root->getChildren()));
  81.     }
  82.     private function filterWorkflows($workflowsValueObject $subject): array
  83.     {
  84.         $workflows array_filter($workflows, static function (Workflow $workflow) use ($subject) {
  85.             try {
  86.                 $workflow->getMarking($subject);
  87.                 return true;
  88.             } catch (LogicException $e) {
  89.                 return false;
  90.             }
  91.         });
  92.         // quick_review works as fallback so we remove it when there are other workflows
  93.         if (count($workflows) > 1) {
  94.             unset($workflows['quick_review']);
  95.         }
  96.         return $workflows;
  97.     }
  98.     public function removePublishButtonsOnContentEdit(ConfigureMenuEvent $event): void
  99.     {
  100.         $root $event->getMenu();
  101.         $options $event->getOptions();
  102.         /** @var \Ibexa\Contracts\Core\Repository\Values\Content\Content $content */
  103.         $content $options['content'];
  104.         $canPublish $this->permissionResolver->canUser('content''publish'$content);
  105.         if ($canPublish) {
  106.             return;
  107.         }
  108.         $workflows $this->workflowRegistry->getSupportedWorkflows($content);
  109.         if (!$this->hasEnabledTransitions($workflows$content)) {
  110.             return;
  111.         }
  112.         $this->removePublishMenuItems($root);
  113.     }
  114.     public function removePublishButtonsOnContentCreate(ConfigureMenuEvent $event): void
  115.     {
  116.         $root $event->getMenu();
  117.         $options $event->getOptions();
  118.         /** @var \Ibexa\Contracts\Core\Repository\Values\Content\ContentCreateStruct $contentCreateStruct */
  119.         $contentCreateStruct $options['content_create_struct'];
  120.         $canPublish $this->permissionResolver->canUser('content''publish'$contentCreateStruct);
  121.         if ($canPublish) {
  122.             return;
  123.         }
  124.         $workflows $this->workflowRegistry->getSupportedWorkflows($contentCreateStruct);
  125.         if (!$this->hasEnabledTransitions($workflows$contentCreateStruct)) {
  126.             return;
  127.         }
  128.         $this->removePublishMenuItems($root);
  129.     }
  130.     private function createWorkflowMenuItems(Workflow $workflow, array $transitions, array $options): array
  131.     {
  132.         $workflowMetadataRegistry $this->workflowDefinitionMetadataRegistry->getWorkflowMetadata($workflow->getName());
  133.         $workflowTransitionsMetadata $workflowMetadataRegistry->getTransitionsMetadata();
  134.         $menuItems = [];
  135.         $orderNumber 1;
  136.         foreach ($transitions as $transition) {
  137.             $transitionMetadata $workflowTransitionsMetadata[$transition->getName()];
  138.             $transitionLabel $transitionMetadata->getLabel();
  139.             $transitionValidate $transitionMetadata->getValidate();
  140.             $menuItemKey sprintf('workflow__apply__%s__%s'$workflow->getName(), $transition->getName());
  141.             $menuItemParameters = [
  142.                 'label' => $transitionLabel,
  143.                 'attributes' => [
  144.                     'class' => 'ibexa-btn--extra-actions',
  145.                     'data-actions' => $menuItemKey,
  146.                     'data-validate' => $transitionValidate,
  147.                     'data-focus-element' => '.ibexa-workflow-apply-transition__user-input',
  148.                 ],
  149.                 'extras' => [
  150.                     'translation_domain' => 'ibexa_workflow',
  151.                     'template' => '@ibexadesign/ibexa_workflow/apply_transition_widget.html.twig',
  152.                     'template_parameters' => [
  153.                         'action' => $menuItemKey,
  154.                         'workflow' => $workflow->getName(),
  155.                         'transition' => $transition->getName(),
  156.                         'reviewer' => [
  157.                             'required' => $transitionMetadata->getReviewersMetadata()->isRequired(),
  158.                         ],
  159.                         'context' => [
  160.                             'action' => isset($options['content']) ? 'edit' 'create',
  161.                             'options' => $options,
  162.                         ],
  163.                     ],
  164.                     'orderNumber' => $orderNumber++,
  165.                 ],
  166.             ];
  167.             if ($transitionMetadata->getIcon()) {
  168.                 $menuItemParameters['extras']['icon_path'] = $transitionMetadata->getIcon();
  169.             } else {
  170.                 $menuItemParameters['extras']['icon'] = 'review';
  171.             }
  172.             $menuItems[$menuItemKey] = $this->menuFactory->createItem(
  173.                 $menuItemKey,
  174.                 $menuItemParameters
  175.             );
  176.         }
  177.         return $menuItems;
  178.     }
  179.     private function hasEnabledTransitions(array $workflows$subject): bool
  180.     {
  181.         $enabledTransitions = [];
  182.         foreach ($workflows as $workflow) {
  183.             $enabledTransitions array_merge($enabledTransitions$workflow->getEnabledTransitions($subject));
  184.         }
  185.         return !empty($enabledTransitions);
  186.     }
  187.     private function removePublishMenuItems(ItemInterface $root): void
  188.     {
  189.         foreach (self::PUBLISH_MENU_ITEMS as $name) {
  190.             $root->removeChild($name);
  191.         }
  192.     }
  193. }
  194. class_alias(AbstractMenuSubscriber::class, 'EzSystems\EzPlatformWorkflow\Event\Subscriber\AbstractMenuSubscriber');