Refactor workflow guard logic and add internal methods

Removed guard logic from EntityWorkflowTransitionEventSubscriber and created a new EntityWorkflowGuardTransition class for separation of concerns. Marked several setter methods in EntityWorkflowStepSignature as internal to guide proper usage. Added comprehensive tests to ensure the new guard logic functions correctly.
This commit is contained in:
2024-09-11 18:29:44 +02:00
parent f0d581b7f8
commit 70671dadac
4 changed files with 291 additions and 44 deletions

View File

@@ -13,20 +13,16 @@ namespace Chill\MainBundle\Workflow\EventSubscriber;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Templating\Entity\UserRender;
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;
final readonly class EntityWorkflowTransitionEventSubscriber implements EventSubscriberInterface
{
public function __construct(
private LoggerInterface $chillLogger,
private Security $security,
private UserRender $userRender,
) {}
public static function getSubscribedEvents(): array
@@ -36,48 +32,9 @@ final readonly class EntityWorkflowTransitionEventSubscriber implements EventSub
'workflow.completed' => [
['markAsFinal', 2048],
],
'workflow.guard' => [
['guardEntityWorkflow', 0],
],
];
}
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(fn (User $u) => $this->userRender->renderString($u, []))->toArray()
),
]
));
}
}
}
public function markAsFinal(Event $event): void
{
// NOTE: it is not possible to move this method to the marking store, because
@@ -109,11 +66,13 @@ final readonly class EntityWorkflowTransitionEventSubscriber implements EventSub
/** @var EntityWorkflow $entityWorkflow */
$entityWorkflow = $event->getSubject();
$user = $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(),
'by_user' => $user instanceof User ? $user->getId() : (string) $user?->getUserIdentifier(),
'entityWorkflow' => $entityWorkflow->getId(),
]);
}