chill-bundles/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/EntityWorkflowTransitionEventSubscriber.php

155 lines
4.9 KiB
PHP

<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\MainBundle\Workflow\EventSubscriber;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Templating\Entity\UserRender;
use DateTimeImmutable;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Workflow\Event\Event;
use Symfony\Component\Workflow\Event\GuardEvent;
use Symfony\Component\Workflow\TransitionBlocker;
use function array_key_exists;
class EntityWorkflowTransitionEventSubscriber implements EventSubscriberInterface
{
private LoggerInterface $chillLogger;
private Security $security;
private UserRender $userRender;
public function __construct(
LoggerInterface $chillLogger,
Security $security,
UserRender $userRender
) {
$this->chillLogger = $chillLogger;
$this->security = $security;
$this->userRender = $userRender;
}
public static function getSubscribedEvents(): array
{
return [
'workflow.transition' => 'onTransition',
'workflow.completed' => [
['markAsFinal', 2048],
['addDests', 2048],
],
'workflow.guard' => [
['guardEntityWorkflow', 0],
],
];
}
public function addDests(Event $event): void
{
if (!$event->getSubject() instanceof EntityWorkflow) {
return;
}
/** @var EntityWorkflow $entityWorkflow */
$entityWorkflow = $event->getSubject();
foreach ($entityWorkflow->futureDestUsers as $user) {
$entityWorkflow->getCurrentStep()->addDestUser($user);
}
foreach ($entityWorkflow->futureDestEmails as $email) {
$entityWorkflow->getCurrentStep()->addDestEmail($email);
}
}
public function guardEntityWorkflow(GuardEvent $event)
{
if (!$event->getSubject() instanceof EntityWorkflow) {
return;
}
/** @var EntityWorkflow $entityWorkflow */
$entityWorkflow = $event->getSubject();
if ($entityWorkflow->isFinal()) {
$event->addTransitionBlocker(
new TransitionBlocker(
'workflow.The workflow is finalized',
'd6306280-7535-11ec-a40d-1f7bee26e2c0'
)
);
return;
}
if (!$entityWorkflow->getCurrentStep()->getAllDestUser()->contains($this->security->getUser())) {
if (!$event->getMarking()->has('initial')) {
$event->addTransitionBlocker(new TransitionBlocker(
'workflow.You are not allowed to apply a transition on this workflow. Only those users are allowed: %users%',
'f3eeb57c-7532-11ec-9495-e7942a2ac7bc',
[
'%users%' => implode(
', ',
$entityWorkflow->getCurrentStep()->getAllDestUser()->map(function (User $u) {
return $this->userRender->renderString($u, []);
})->toArray()
),
]
));
}
}
}
public function markAsFinal(Event $event): void
{
if (!$event->getSubject() instanceof EntityWorkflow) {
return;
}
/** @var EntityWorkflow $entityWorkflow */
$entityWorkflow = $event->getSubject();
$step = $entityWorkflow->getCurrentStep();
$placeMetadata = $event->getWorkflow()->getMetadataStore()
->getPlaceMetadata($step->getCurrentStep());
if (array_key_exists('isFinal', $placeMetadata) && true === $placeMetadata['isFinal']) {
$step->setIsFinal(true);
}
}
public function onTransition(Event $event): void
{
if (!$event->getSubject() instanceof EntityWorkflow) {
return;
}
/** @var EntityWorkflow $entityWorkflow */
$entityWorkflow = $event->getSubject();
$step = $entityWorkflow->getCurrentStep();
$step
->setTransitionAfter($event->getTransition()->getName())
->setTransitionAt(new DateTimeImmutable('now'))
->setTransitionBy($this->security->getUser());
$this->chillLogger->info('[workflow] apply transition on entityWorkflow', [
'relatedEntityClass' => $entityWorkflow->getRelatedEntityClass(),
'relatedEntityId' => $entityWorkflow->getRelatedEntityId(),
'transition' => $event->getTransition()->getName(),
'by_user' => $this->security->getUser(),
'entityWorkflow' => $entityWorkflow->getId(),
]);
}
}