vendor/pimcore/pimcore/bundles/CoreBundle/EventListener/WorkflowManagementListener.php line 104

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Commercial License (PCL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  *  @license    http://www.pimcore.org/license     GPLv3 and PCL
  13.  */
  14. namespace Pimcore\Bundle\CoreBundle\EventListener;
  15. use Pimcore\Event\AdminEvents;
  16. use Pimcore\Event\AssetEvents;
  17. use Pimcore\Event\DataObjectEvents;
  18. use Pimcore\Event\DocumentEvents;
  19. use Pimcore\Event\Model\ElementEventInterface;
  20. use Pimcore\Model\Asset;
  21. use Pimcore\Model\DataObject;
  22. use Pimcore\Model\DataObject\ClassDefinition;
  23. use Pimcore\Model\DataObject\Concrete as ConcreteObject;
  24. use Pimcore\Model\Document;
  25. use Pimcore\Model\Element\ElementInterface;
  26. use Pimcore\Model\Element\Service;
  27. use Pimcore\Model\Element\WorkflowState;
  28. use Pimcore\Workflow\ActionsButtonService;
  29. use Pimcore\Workflow\Manager;
  30. use Pimcore\Workflow\Place;
  31. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  32. use Symfony\Component\EventDispatcher\GenericEvent;
  33. use Symfony\Component\HttpFoundation\RequestStack;
  34. /**
  35.  * @internal
  36.  */
  37. class WorkflowManagementListener implements EventSubscriberInterface
  38. {
  39.     /**
  40.      * @var bool
  41.      */
  42.     protected bool $enabled true;
  43.     public function __construct(
  44.         private Manager $workflowManager,
  45.         private Place\StatusInfo $placeStatusInfo,
  46.         private RequestStack $requestStack,
  47.         private ActionsButtonService $actionsButtonService
  48.     ) {
  49.     }
  50.     /**
  51.      * {@inheritdoc}
  52.      */
  53.     public static function getSubscribedEvents()
  54.     {
  55.         return [
  56.             DataObjectEvents::POST_ADD => 'onElementPostAdd',
  57.             DocumentEvents::POST_ADD => 'onElementPostAdd',
  58.             AssetEvents::POST_ADD => 'onElementPostAdd',
  59.             DataObjectEvents::POST_DELETE => 'onElementPostDelete',
  60.             DocumentEvents::POST_DELETE => 'onElementPostDelete',
  61.             AssetEvents::POST_DELETE => 'onElementPostDelete',
  62.             AdminEvents::OBJECT_GET_PRE_SEND_DATA => 'onAdminElementGetPreSendData',
  63.             AdminEvents::ASSET_GET_PRE_SEND_DATA => 'onAdminElementGetPreSendData',
  64.             AdminEvents::DOCUMENT_GET_PRE_SEND_DATA => 'onAdminElementGetPreSendData',
  65.         ];
  66.     }
  67.     /**
  68.      * Set initial place if defined on element create.
  69.      */
  70.     public function onElementPostAdd(ElementEventInterface $e): void
  71.     {
  72.         /** @var Asset|Document|ConcreteObject $element */
  73.         $element $e->getElement();
  74.         foreach ($this->workflowManager->getAllWorkflows() as $workflowName) {
  75.             $workflow $this->workflowManager->getWorkflowIfExists($element$workflowName);
  76.             if (!$workflow) {
  77.                 continue;
  78.             }
  79.             $hasInitialPlaceConfig count($this->workflowManager->getInitialPlacesForWorkflow($workflow)) > 0;
  80.             // calling getMarking will ensure the initial place is set
  81.             if ($hasInitialPlaceConfig) {
  82.                 $workflow->getMarking($element);
  83.             }
  84.         }
  85.     }
  86.     /**
  87.      * Cleanup status information on element delete
  88.      *
  89.      * @param ElementEventInterface $e
  90.      */
  91.     public function onElementPostDelete(ElementEventInterface $e)
  92.     {
  93.         /**
  94.          * @var Asset|Document|ConcreteObject $element
  95.          */
  96.         $element $e->getElement();
  97.         $list = new WorkflowState\Listing;
  98.         $list->setCondition('cid = ? and ctype = ?', [$element->getId(), Service::getElementType($element)]);
  99.         foreach ($list->load() as $item) {
  100.             $item->delete();
  101.         }
  102.     }
  103.     /**
  104.      * Fired before information is sent back to the admin UI about an element
  105.      *
  106.      * @param GenericEvent $e
  107.      *
  108.      * @throws \Exception
  109.      */
  110.     public function onAdminElementGetPreSendData(GenericEvent $e)
  111.     {
  112.         $element self::extractElementFromEvent($e);
  113.         $data $e->getArgument('data');
  114.         //create a new namespace for WorkflowManagement
  115.         //set some defaults
  116.         $data['workflowManagement'] = [
  117.             'hasWorkflowManagement' => false,
  118.         ];
  119.         foreach ($this->workflowManager->getAllWorkflows() as $workflowName) {
  120.             $workflow $this->workflowManager->getWorkflowIfExists($element$workflowName);
  121.             $workflowConfig $this->workflowManager->getWorkflowConfig($workflowName);
  122.             if (empty($workflow)) {
  123.                 continue;
  124.             }
  125.             $data['workflowManagement']['hasWorkflowManagement'] = true;
  126.             $data['workflowManagement']['workflows'] = $data['workflowManagement']['workflows'] ?? [];
  127.             // Fix: places stored as empty string ("") considered uninitialized prior to Symfony 4.4.8
  128.             $this->workflowManager->ensureInitialPlace($workflowName$element);
  129.             $allowedTransitions $this->actionsButtonService->getAllowedTransitions($workflow$element);
  130.             $globalActions $this->actionsButtonService->getGlobalActions($workflow$element);
  131.             $data['workflowManagement']['workflows'][] = [
  132.                 'name' => $workflow->getName(),
  133.                 'label' => $workflowConfig->getLabel(),
  134.                 'allowedTransitions' => $allowedTransitions,
  135.                 'globalActions' => $globalActions,
  136.             ];
  137.             $marking $workflow->getMarking($element);
  138.             if (!count($marking->getPlaces())) {
  139.                 continue;
  140.             }
  141.             $permissionsRespected false;
  142.             foreach ($this->workflowManager->getOrderedPlaceConfigs($workflow$marking) as $placeConfig) {
  143.                 if (!$permissionsRespected && !empty($placeConfig->getPermissions($workflow$element))) {
  144.                     $data['userPermissions'] = array_merge(
  145.                         (array)$data['userPermissions'],
  146.                         $placeConfig->getUserPermissions($workflow$element)
  147.                     );
  148.                     if ($element instanceof ConcreteObject) {
  149.                         $workflowLayoutId $placeConfig->getObjectLayout($workflow$element);
  150.                         $hasSelectedCustomLayout $this->requestStack->getMainRequest(
  151.                             ) && $this->requestStack->getMainRequest()->query->has(
  152.                                 'layoutId'
  153.                             ) && $this->requestStack->getMainRequest()->query->get('layoutId') !== '';
  154.                         if (!is_null($workflowLayoutId) && !$hasSelectedCustomLayout) {
  155.                             //load the new layout into the object container
  156.                             $validLayouts DataObject\Service::getValidLayouts($element);
  157.                             // check user permissions again
  158.                             if (isset($validLayouts[$workflowLayoutId])) {
  159.                                 $customLayout ClassDefinition\CustomLayout::getById($workflowLayoutId);
  160.                                 $customLayoutDefinition $customLayout->getLayoutDefinitions();
  161.                                 DataObject\Service::enrichLayoutDefinition(
  162.                                     $customLayoutDefinition,
  163.                                     $e->getArgument('object')
  164.                                 );
  165.                                 $data['layout'] = $customLayoutDefinition;
  166.                                 $data['currentLayoutId'] = $workflowLayoutId;
  167.                             }
  168.                         }
  169.                     }
  170.                     $permissionsRespected true;
  171.                 }
  172.             }
  173.         }
  174.         if ($data['workflowManagement']['hasWorkflowManagement']) {
  175.             $data['workflowManagement']['statusInfo'] = $this->placeStatusInfo->getToolbarHtml($element);
  176.         }
  177.         $e->setArgument('data'$data);
  178.     }
  179.     /**
  180.      * @param DataObject\AbstractObject $object
  181.      * @param array $notes
  182.      *
  183.      * @return array
  184.      */
  185.     private function enrichNotes(DataObject\AbstractObject $object, array $notes)
  186.     {
  187.         if (!empty($notes['commentGetterFn'])) {
  188.             $commentGetterFn $notes['commentGetterFn'];
  189.             $notes['commentPrefill'] = $object->$commentGetterFn();
  190.         } elseif (!empty($notes)) {
  191.             $notes['commentPrefill'] = '';
  192.         }
  193.         return $notes;
  194.     }
  195.     /**
  196.      * @param GenericEvent $e
  197.      *
  198.      * @return ElementInterface
  199.      *
  200.      * @throws \Exception
  201.      */
  202.     private static function extractElementFromEvent(GenericEvent $e)
  203.     {
  204.         $element null;
  205.         foreach (['object''asset''document'] as $type) {
  206.             if ($e->hasArgument($type)) {
  207.                 $element $e->getArgument($type);
  208.             }
  209.         }
  210.         if (empty($element)) {
  211.             throw new \Exception('No element found in event');
  212.         }
  213.         return $element;
  214.     }
  215.     public function enable()
  216.     {
  217.         $this->enabled true;
  218.     }
  219.     public function disable()
  220.     {
  221.         $this->enabled false;
  222.     }
  223.     /**
  224.      * @return bool
  225.      */
  226.     public function isEnabled()
  227.     {
  228.         return $this->enabled;
  229.     }
  230. }