Files
chill-bundles/src/Bundle/ChillMainBundle/Workflow/EventSubscriber/EntityWorkflowGuardUnsignedTransition.php
Julien Fastré cf2fe1bba7 Add guards and tests for entity workflow transitions
Introduced EntityWorkflowGuardUnsignedTransition to block transitions with pending signatures. Implemented a new center resolver and added comprehensive unit tests for verifying transition rules and permissions.
2024-09-24 11:08:22 +02:00

70 lines
2.4 KiB
PHP

<?php
declare(strict_types=1);
/*
* 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.
*/
namespace Chill\MainBundle\Workflow\EventSubscriber;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowSignatureStateEnum;
use Chill\MainBundle\Security\Authorization\EntityWorkflowTransitionVoter;
use Chill\MainBundle\Templating\Entity\ChillEntityRenderManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Workflow\Event\GuardEvent;
use Symfony\Component\Workflow\TransitionBlocker;
/**
* Block the transition on EntityWorkflow if there is a still pending signature.
*/
final readonly class EntityWorkflowGuardUnsignedTransition implements EventSubscriberInterface
{
public function __construct(private ChillEntityRenderManagerInterface $chillEntityRenderManager, private Security $security) {}
public static function getSubscribedEvents(): array
{
return [
'workflow.guard' => [
['guardWaitingForSignature', 0],
],
];
}
public function guardWaitingForSignature(GuardEvent $event): void
{
$entityWorkflow = $event->getSubject();
if (!$entityWorkflow instanceof EntityWorkflow) {
return;
}
$transitionMetadata = $event->getWorkflow()->getMetadataStore()->getTransitionMetadata($event->getTransition());
if (false === ($transitionMetadata['isForward'] ?? true)) {
return;
}
foreach ($entityWorkflow->getCurrentStep()->getSignatures() as $signature) {
if (EntityWorkflowSignatureStateEnum::PENDING === $signature->getState()) {
if ($this->security->isGranted(EntityWorkflowTransitionVoter::APPLY_ALL_TRANSITIONS, $entityWorkflow)) {
continue;
}
$event->addTransitionBlocker(
new TransitionBlocker(
'workflow.blocked_waiting_for_pending_signer',
'2eabe9e6-79c2-11ef-986c-2ba376180859',
['signer' => $this->chillEntityRenderManager->renderString($signature->getSigner(), ['addAge' => false])]
)
);
}
}
}
}