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

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 Enterprise License (PEL)
  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 PEL
  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\AbstractElement;
  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. use Symfony\Component\Workflow\Registry;
  35. class WorkflowManagementListener implements EventSubscriberInterface
  36. {
  37.     /**
  38.      * @var bool
  39.      */
  40.     protected $enabled true;
  41.     /**
  42.      * @var Manager
  43.      */
  44.     private $workflowManager;
  45.     /**
  46.      * @var Registry
  47.      */
  48.     private $workflowRegistry;
  49.     /**
  50.      * @var Place\StatusInfo
  51.      */
  52.     private $placeStatusInfo;
  53.     /**
  54.      * @var RequestStack
  55.      */
  56.     private $requestStack;
  57.     /**
  58.      * @var ActionsButtonService
  59.      */
  60.     private $actionsButtonService;
  61.     public function __construct(Manager $workflowManagerRegistry $workflowRegistryPlace\StatusInfo $placeStatusInfoRequestStack $requestStackActionsButtonService $actionsButtonService)
  62.     {
  63.         $this->workflowManager $workflowManager;
  64.         $this->workflowRegistry $workflowRegistry;
  65.         $this->placeStatusInfo $placeStatusInfo;
  66.         $this->requestStack $requestStack;
  67.         $this->actionsButtonService $actionsButtonService;
  68.     }
  69.     /**
  70.      * @inheritDoc
  71.      */
  72.     public static function getSubscribedEvents()
  73.     {
  74.         return [
  75.             DataObjectEvents::PRE_ADD => 'onElementPreAdd',
  76.             DocumentEvents::PRE_ADD => 'onElementPreAdd',
  77.             AssetEvents::PRE_ADD => 'onElementPreAdd',
  78.             DataObjectEvents::POST_DELETE => 'onElementPostDelete',
  79.             DocumentEvents::POST_DELETE => 'onElementPostDelete',
  80.             AssetEvents::POST_DELETE => 'onElementPostDelete',
  81.             AdminEvents::OBJECT_GET_PRE_SEND_DATA => 'onAdminElementGetPreSendData',
  82.             AdminEvents::ASSET_GET_PRE_SEND_DATA => 'onAdminElementGetPreSendData',
  83.             AdminEvents::DOCUMENT_GET_PRE_SEND_DATA => 'onAdminElementGetPreSendData',
  84.         ];
  85.     }
  86.     /**
  87.      * Set initial place if defined on element create.
  88.      */
  89.     public function onElementPreAdd(ElementEventInterface $e): void
  90.     {
  91.         /** @var Asset|Document|ConcreteObject $element */
  92.         $element $e->getElement();
  93.         foreach ($this->workflowManager->getAllWorkflows() as $workflowName) {
  94.             $workflow $this->workflowManager->getWorkflowIfExists($element$workflowName);
  95.             if (!$workflow) {
  96.                 continue;
  97.             }
  98.             $hasInitialPlaceConfig count($this->workflowManager->getInitialPlacesForWorkflow($workflow)) > 0;
  99.             // calling getMarking will ensure the initial place is set
  100.             if ($hasInitialPlaceConfig) {
  101.                 $workflow->getMarking($element);
  102.             }
  103.         }
  104.     }
  105.     /**
  106.      * Cleanup status information on element delete
  107.      *
  108.      * @param ElementEventInterface $e
  109.      */
  110.     public function onElementPostDelete(ElementEventInterface $e)
  111.     {
  112.         /**
  113.          * @var Asset|Document|ConcreteObject $element
  114.          */
  115.         $element $e->getElement();
  116.         $list = new WorkflowState\Listing;
  117.         $list->setCondition('cid = ? and ctype = ?', [$element->getId(), Service::getType($element)]);
  118.         foreach ($list->load() as $item) {
  119.             $item->delete();
  120.         }
  121.     }
  122.     /**
  123.      * Fired before information is sent back to the admin UI about an element
  124.      *
  125.      * @param GenericEvent $e
  126.      *
  127.      * @throws \Exception
  128.      */
  129.     public function onAdminElementGetPreSendData(GenericEvent $e)
  130.     {
  131.         $element self::extractElementFromEvent($e);
  132.         $data $e->getArgument('data');
  133.         //create a new namespace for WorkflowManagement
  134.         //set some defaults
  135.         $data['workflowManagement'] = [
  136.             'hasWorkflowManagement' => false,
  137.         ];
  138.         foreach ($this->workflowManager->getAllWorkflows() as $workflowName) {
  139.             $workflow $this->workflowManager->getWorkflowIfExists($element$workflowName);
  140.             $workflowConfig $this->workflowManager->getWorkflowConfig($workflowName);
  141.             if (empty($workflow)) {
  142.                 continue;
  143.             }
  144.             $data['workflowManagement']['hasWorkflowManagement'] = true;
  145.             $data['workflowManagement']['workflows'] = $data['workflowManagement']['workflows'] ?? [];
  146.             // Fix: places stored as empty string ("") considered uninitialized prior to Symfony 4.4.8
  147.             $this->workflowManager->ensureInitialPlace($workflowName$element);
  148.             $allowedTransitions $this->actionsButtonService->getAllowedTransitions($workflow$element);
  149.             $globalActions $this->actionsButtonService->getGlobalActions($workflow$element);
  150.             $data['workflowManagement']['workflows'][] = [
  151.                 'name' => $workflow->getName(),
  152.                 'label' => $workflowConfig->getLabel(),
  153.                 'allowedTransitions' => $allowedTransitions,
  154.                 'globalActions' => $globalActions
  155.             ];
  156.             $marking $workflow->getMarking($element);
  157.             if (!sizeof($marking->getPlaces())) {
  158.                 continue;
  159.             }
  160.             $permissionsRespected false;
  161.             foreach ($this->workflowManager->getOrderedPlaceConfigs($workflow$marking) as $placeConfig) {
  162.                 if (!$permissionsRespected && !empty($placeConfig->getPermissions($workflow$element))) {
  163.                     $data['userPermissions'] = array_merge((array)$data['userPermissions'], $placeConfig->getUserPermissions($workflow$element));
  164.                     if ($element instanceof ConcreteObject) {
  165.                         $workflowLayoutId $placeConfig->getObjectLayout($workflow$element);
  166.                         $hasSelectedCustomLayout $this->requestStack->getMasterRequest() && $this->requestStack->getMasterRequest()->query->has('layoutId') && $this->requestStack->getMasterRequest()->query->get('layoutId') !== '';
  167.                         if (!is_null($workflowLayoutId) && !$hasSelectedCustomLayout) {
  168.                             //load the new layout into the object container
  169.                             $validLayouts DataObject\Service::getValidLayouts($element);
  170.                             //check that the layout id is valid before trying to load
  171.                             if (!empty($validLayouts)) {
  172.                                 // check user permissions again
  173.                                 if ($validLayouts && $validLayouts[$workflowLayoutId]) {
  174.                                     $customLayout ClassDefinition\CustomLayout::getById($workflowLayoutId);
  175.                                     $customLayoutDefinition $customLayout->getLayoutDefinitions();
  176.                                     DataObject\Service::enrichLayoutDefinition($customLayoutDefinition$e->getArgument('object'));
  177.                                     $data['layout'] = $customLayoutDefinition;
  178.                                     $data['currentLayoutId'] = $workflowLayoutId;
  179.                                 }
  180.                             }
  181.                         }
  182.                     }
  183.                     $permissionsRespected true;
  184.                 }
  185.             }
  186.         }
  187.         if ($data['workflowManagement']['hasWorkflowManagement']) {
  188.             $data['workflowManagement']['statusInfo'] = $this->placeStatusInfo->getToolbarHtml($element);
  189.         }
  190.         $e->setArgument('data'$data);
  191.     }
  192.     /**
  193.      * @param DataObject\AbstractObject $object
  194.      * @param array $notes
  195.      *
  196.      * @return array
  197.      */
  198.     private function enrichNotes(DataObject\AbstractObject $object, array $notes)
  199.     {
  200.         if (!empty($notes['commentGetterFn'])) {
  201.             $commentGetterFn $notes['commentGetterFn'];
  202.             $notes['commentPrefill'] = $object->$commentGetterFn();
  203.         } elseif (!empty($notes)) {
  204.             $notes['commentPrefill'] = '';
  205.         }
  206.         return $notes;
  207.     }
  208.     /**
  209.      * @param GenericEvent $e
  210.      *
  211.      * @return AbstractElement
  212.      *
  213.      * @throws \Exception
  214.      */
  215.     private static function extractElementFromEvent(GenericEvent $e)
  216.     {
  217.         $element null;
  218.         foreach (['object''asset''document'] as $type) {
  219.             if ($e->hasArgument($type)) {
  220.                 $element $e->getArgument($type);
  221.             }
  222.         }
  223.         if (empty($element)) {
  224.             throw new \Exception('No element found in event');
  225.         }
  226.         return $element;
  227.     }
  228.     public function enable()
  229.     {
  230.         $this->enabled true;
  231.     }
  232.     public function disable()
  233.     {
  234.         $this->enabled false;
  235.     }
  236.     /**
  237.      * @return bool
  238.      */
  239.     public function isEnabled()
  240.     {
  241.         return $this->enabled;
  242.     }
  243. }