Add PDF signature zone availability checks

Introduce `PDFSignatureZoneAvailable` service to check available PDF signature zones. Updated `WorkflowAddSignatureController` to use the new service. Added unit tests to verify the correctness of the functionality.
This commit is contained in:
2024-09-04 13:48:46 +02:00
parent c6a6d76790
commit e17203ca3a
5 changed files with 236 additions and 25 deletions

View File

@@ -11,11 +11,9 @@ declare(strict_types=1);
namespace Chill\MainBundle\Controller;
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZoneParser;
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZoneAvailable;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStepSignature;
use Chill\MainBundle\Workflow\EntityWorkflowManager;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -23,21 +21,18 @@ use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Twig\Environment;
final class WorkflowAddSignatureController
final readonly class WorkflowAddSignatureController
{
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly EntityWorkflowManager $entityWorkflowManager,
private readonly StoredObjectManagerInterface $storedObjectManager,
private readonly PDFSignatureZoneParser $PDFSignatureZoneParser,
private readonly NormalizerInterface $normalizer,
private readonly Environment $twig
private EntityWorkflowManager $entityWorkflowManager,
private PDFSignatureZoneAvailable $PDFSignatureZoneAvailable,
private NormalizerInterface $normalizer,
private Environment $twig
) {}
#[Route(path: '/{_locale}/main/workflow/signature/{signature_id}/sign', name: 'chill_main_workflow_signature', methods: 'GET')]
public function __invoke(int $signature_id, Request $request, WorkflowController $workflowController): Response
#[Route(path: '/{_locale}/main/workflow/signature/{id}/sign', name: 'chill_main_workflow_signature', methods: 'GET')]
public function __invoke(EntityWorkflowStepSignature $signature, Request $request): Response
{
$signature = $this->entityManager->getRepository(EntityWorkflowStepSignature::class)->find($signature_id);
$entityWorkflow = $signature->getStep()->getEntityWorkflow();
$storedObject = $this->entityWorkflowManager->getAssociatedStoredObject($entityWorkflow);
@@ -45,20 +40,18 @@ final class WorkflowAddSignatureController
throw new NotFoundHttpException('No stored object found');
}
$zones = [];
$content = $this->storedObjectManager->read($storedObject);
if (null != $content) {
$zones = $this->PDFSignatureZoneParser->findSignatureZones($content);
}
$zones = $this->PDFSignatureZoneAvailable->getAvailableSignatureZones($entityWorkflow);
$signatureClient = [];
$signatureClient['id'] = $signature->getId();
$signatureClient['storedObject'] = $this->normalizer->normalize($storedObject, 'json');
$signatureClient['zones'] = $zones;
return new Response($this->twig->render(
'@ChillMain/Workflow/_signature_sign.html.twig',
['signature' => $signatureClient]
));
return new Response(
$this->twig->render(
'@ChillMain/Workflow/_signature_sign.html.twig',
['signature' => $signatureClient]
)
);
}
}

View File

@@ -20,6 +20,7 @@ use Chill\MainBundle\Workflow\Validator\EntityWorkflowCreation;
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Selectable;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;
@@ -52,12 +53,12 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface
private int $relatedEntityId;
/**
* @var Collection<int, EntityWorkflowStep>
* @var Collection<int, EntityWorkflowStep>&Selectable<int, EntityWorkflowStep>
*/
#[Assert\Valid(traverse: true)]
#[ORM\OneToMany(mappedBy: 'entityWorkflow', targetEntity: EntityWorkflowStep::class, cascade: ['persist'], orphanRemoval: true)]
#[ORM\OrderBy(['transitionAt' => \Doctrine\Common\Collections\Criteria::ASC, 'id' => 'ASC'])]
private Collection $steps;
private Collection&Selectable $steps;
/**
* @var array|EntityWorkflowStep[]|null
@@ -242,7 +243,7 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface
throw new \RuntimeException();
}
public function getSteps(): ArrayCollection|Collection
public function getSteps(): Collection&Selectable
{
return $this->steps;
}

View File

@@ -0,0 +1,72 @@
<?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\Tests\Controller;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Service\Signature\PDFPage;
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone;
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZoneAvailable;
use Chill\MainBundle\Controller\WorkflowAddSignatureController;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Workflow\EntityWorkflowManager;
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
use Chill\PersonBundle\Entity\Person;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Twig\Environment;
/**
* @internal
*
* @coversNothing
*/
class WorkflowAddSignatureControllerTest extends TestCase
{
public function testAddSignature(): void
{
$storedObject = new StoredObject();
$entityWorkflow = new EntityWorkflow();
$stepTransition = new WorkflowTransitionContextDTO($entityWorkflow);
$stepTransition->futurePersonSignatures[] = new Person();
$entityWorkflow->setStep('step_signature', $stepTransition, 'to_signature', new \DateTimeImmutable('now'), new User());
$signature = $entityWorkflow->getCurrentStep()->getSignatures()->first();
$entityWorkflowManager = $this->createMock(EntityWorkflowManager::class);
$entityWorkflowManager->method('getAssociatedStoredObject')
->with($entityWorkflow)
->willReturn($storedObject);
$pdfSignatureZoneAvailable = $this->createMock(PDFSignatureZoneAvailable::class);
$pdfSignatureZoneAvailable->method('getAvailableSignatureZones')->withAnyParameters()
->willReturn([
new PDFSignatureZone(1, 0.0, 0.0, 100, 100, new PDFPage(1, 500.0, 500.0)),
]);
$normalizer = $this->createMock(NormalizerInterface::class);
$normalizer->method('normalize')->withAnyParameters()
->willReturn([]);
$twig = $this->createMock(Environment::class);
$twig->method('render')->with('@ChillMain/Workflow/_signature_sign.html.twig', $this->isType('array'))
->willReturn('ok');
$controller = new WorkflowAddSignatureController($entityWorkflowManager, $pdfSignatureZoneAvailable, $normalizer, $twig);
$actual = $controller($signature, new Request());
self::assertEquals(200, $actual->getStatusCode());
self::assertEquals('ok', $actual->getContent());
}
}