Move the logic to check if dest users are required to a dedicated constraint

- Create a dedicated constraint to check if the destUsers are required by the applied transition.
- Apply on WorkflowTransitionContextDTO and, if required, use the built-in constraints
- create tests
This commit is contained in:
2024-10-04 11:35:15 +02:00
parent 7cd638c5fc
commit 7913a377c8
5 changed files with 323 additions and 35 deletions

View File

@@ -0,0 +1,31 @@
<?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\Validator;
use Symfony\Component\Validator\Constraint;
/**
* Check that the next stop has a dest user if this is required by the transition.
*/
#[\Attribute]
class TransitionHasDestUserIfRequired extends Constraint
{
public $messageDestUserRequired = 'workflow.You must add at least one dest user or email';
public $codeDestUserRequired = '637c20a6-822c-11ef-a4dd-07b4c0c0efa8';
public $messageDestUserNotAuthorized = 'workflow.dest_user_not_authorized';
public $codeDestUserNotAuthorized = '8377be2c-822e-11ef-b53a-57ad65828a8e';
public function getTargets(): string
{
return self::CLASS_CONSTRAINT;
}
}

View File

@@ -0,0 +1,79 @@
<?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\Validator;
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
use Symfony\Component\Workflow\Registry;
final class TransitionHasDestUserIfRequiredValidator extends ConstraintValidator
{
public function __construct(private readonly Registry $registry) {}
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof TransitionHasDestUserIfRequired) {
throw new UnexpectedTypeException($constraint, TransitionHasDestUserIfRequired::class);
}
if (!$value instanceof WorkflowTransitionContextDTO) {
throw new UnexpectedValueException($value, WorkflowTransitionContextDTO::class);
}
if (null === $value->transition) {
return;
}
$workflow = $this->registry->get($value->entityWorkflow, $value->entityWorkflow->getWorkflowName());
$metadataStore = $workflow->getMetadataStore();
$destUsersRequired = false;
foreach ($value->transition->getTos() as $to) {
$metadata = $metadataStore->getPlaceMetadata($to);
// if the place are only 'isSentExternal' or 'isSignature' or 'final', then, we skip - a destUser is not required
if ($metadata['isSentExternal'] ?? false) {
continue;
}
if ($metadata['isSignature'] ?? false) {
continue;
}
if ($metadata['isFinal'] ?? false) {
continue;
}
// if there isn't any 'isSentExternal' or 'isSignature' or final, then we must have a destUser
$destUsersRequired = true;
}
if (!$destUsersRequired) {
if (0 < count($value->futureDestUsers)) {
$this->context->buildViolation($constraint->messageDestUserNotAuthorized)
->setCode($constraint->codeDestUserNotAuthorized)
->atPath('futureDestUsers')
->addViolation();
}
return;
}
if (0 === count($value->futureDestUsers)) {
$this->context->buildViolation($constraint->messageDestUserRequired)
->setCode($constraint->codeDestUserRequired)
->atPath('futureDestUsers')
->addViolation();
}
}
}

View File

@@ -15,6 +15,7 @@ use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\UserGroup;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Workflow\Validator\TransitionHasDestineeIfIsSentExternal;
use Chill\MainBundle\Workflow\Validator\TransitionHasDestUserIfRequired;
use Chill\PersonBundle\Entity\Person;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use Chill\ThirdPartyBundle\Validator\ThirdPartyHasEmail;
@@ -26,6 +27,7 @@ use Symfony\Component\Workflow\Transition;
* Context for a transition on an workflow entity.
*/
#[TransitionHasDestineeIfIsSentExternal]
#[TransitionHasDestUserIfRequired]
class WorkflowTransitionContextDTO
{
/**
@@ -81,6 +83,7 @@ class WorkflowTransitionContextDTO
])]
public array $futureDestineeEmails = [];
#[Assert\NotNull]
public ?Transition $transition = null;
public string $comment = '';