From 941444b7d5b0d8b320f8c4bb061a0935748d4e6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Tue, 10 Sep 2024 14:29:03 +0200 Subject: [PATCH] Add event subscriber to convert docs to PDF before signature Introduce ConvertToPdfBeforeSignatureStepEventSubscriber to convert documents to PDF when reaching a signature step in the workflow. Includes tests to ensure the conversion process only triggers when necessary. --- ...BeforeSignatureStepEventSubscriberTest.php | 208 ++++++++++++++++++ ...oPdfBeforeSignatureStepEventSubscriber.php | 75 +++++++ 2 files changed, 283 insertions(+) create mode 100644 src/Bundle/ChillDocStoreBundle/Tests/Workflow/ConvertToPdfBeforeSignatureStepEventSubscriberTest.php create mode 100644 src/Bundle/ChillDocStoreBundle/Workflow/ConvertToPdfBeforeSignatureStepEventSubscriber.php diff --git a/src/Bundle/ChillDocStoreBundle/Tests/Workflow/ConvertToPdfBeforeSignatureStepEventSubscriberTest.php b/src/Bundle/ChillDocStoreBundle/Tests/Workflow/ConvertToPdfBeforeSignatureStepEventSubscriberTest.php new file mode 100644 index 000000000..572cb192c --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Tests/Workflow/ConvertToPdfBeforeSignatureStepEventSubscriberTest.php @@ -0,0 +1,208 @@ +registerVersion(); + + $converter = $this->prophesize(StoredObjectToPdfConverter::class); + $converter->addConvertedVersion($storedObject, 'fr', 'pdf') + ->shouldBeCalledOnce() + ->will(function ($args) { + /** @var StoredObject $storedObject */ + $storedObject = $args[0]; + + $pointInTime = new StoredObjectPointInTime($storedObject->getCurrentVersion(), StoredObjectPointInTimeReasonEnum::KEEP_BEFORE_CONVERSION); + $newVersion = $storedObject->registerVersion(filename: 'next'); + + return [$pointInTime, $newVersion]; + }); + + $entityWorkflowManager = $this->prophesize(EntityWorkflowManager::class); + $entityWorkflowManager->getAssociatedStoredObject($entityWorkflow)->willReturn($storedObject); + + $request = new Request(); + $request->setLocale('fr'); + $stack = new RequestStack(); + $stack->push($request); + + $eventSubscriber = new ConvertToPdfBeforeSignatureStepEventSubscriber($entityWorkflowManager->reveal(), $converter->reveal(), $stack); + + $registry = $this->buildRegistry($eventSubscriber); + $workflow = $registry->get($entityWorkflow, 'dummy'); + + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $workflow->apply($entityWorkflow, 'to_signature', ['context' => $dto, 'transition' => 'to_signature', 'transitionAt' => new \DateTimeImmutable('now')]); + + self::assertEquals('signature', $entityWorkflow->getStep()); + self::assertNotSame($previousVersion, $storedObject->getCurrentVersion()); + self::assertTrue($previousVersion->hasPointInTimes()); + self::assertCount(2, $storedObject->getVersions()); + self::assertEquals('next', $storedObject->getCurrentVersion()->getFilename()); + } + + public function testConvertToPdfBeforeSignatureStepEventSubscriberToNotASignatureStep(): void + { + $entityWorkflow = new EntityWorkflow(); + $storedObject = new StoredObject(); + $previousVersion = $storedObject->registerVersion(); + + $converter = $this->prophesize(StoredObjectToPdfConverter::class); + $converter->addConvertedVersion($storedObject, 'fr', 'pdf') + ->shouldNotBeCalled(); + + $entityWorkflowManager = $this->prophesize(EntityWorkflowManager::class); + $entityWorkflowManager->getAssociatedStoredObject($entityWorkflow)->willReturn($storedObject); + + $request = new Request(); + $request->setLocale('fr'); + $stack = new RequestStack(); + $stack->push($request); + + $eventSubscriber = new ConvertToPdfBeforeSignatureStepEventSubscriber($entityWorkflowManager->reveal(), $converter->reveal(), $stack); + + $registry = $this->buildRegistry($eventSubscriber); + $workflow = $registry->get($entityWorkflow, 'dummy'); + + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $workflow->apply($entityWorkflow, 'to_something', ['context' => $dto, 'transition' => 'to_something', 'transitionAt' => new \DateTimeImmutable('now')]); + + self::assertEquals('something', $entityWorkflow->getStep()); + self::assertSame($previousVersion, $storedObject->getCurrentVersion()); + self::assertFalse($previousVersion->hasPointInTimes()); + self::assertCount(1, $storedObject->getVersions()); + } + + public function testConvertToPdfBeforeSignatureStepEventSubscriberToSignatureAlreadyAPdf(): void + { + $entityWorkflow = new EntityWorkflow(); + $storedObject = new StoredObject(); + $previousVersion = $storedObject->registerVersion(type: 'application/pdf'); + + $converter = $this->prophesize(StoredObjectToPdfConverter::class); + $converter->addConvertedVersion($storedObject, 'fr', 'pdf') + ->shouldNotBeCalled(); + + $entityWorkflowManager = $this->prophesize(EntityWorkflowManager::class); + $entityWorkflowManager->getAssociatedStoredObject($entityWorkflow)->willReturn($storedObject); + + $request = new Request(); + $request->setLocale('fr'); + $stack = new RequestStack(); + $stack->push($request); + + $eventSubscriber = new ConvertToPdfBeforeSignatureStepEventSubscriber($entityWorkflowManager->reveal(), $converter->reveal(), $stack); + + $registry = $this->buildRegistry($eventSubscriber); + $workflow = $registry->get($entityWorkflow, 'dummy'); + + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $workflow->apply($entityWorkflow, 'to_signature', ['context' => $dto, 'transition' => 'to_signature', 'transitionAt' => new \DateTimeImmutable('now')]); + + self::assertEquals('signature', $entityWorkflow->getStep()); + self::assertSame($previousVersion, $storedObject->getCurrentVersion()); + self::assertFalse($previousVersion->hasPointInTimes()); + self::assertCount(1, $storedObject->getVersions()); + } + + public function testConvertToPdfBeforeSignatureStepEventSubscriberToSignatureWithNoStoredObject(): void + { + $entityWorkflow = new EntityWorkflow(); + + $converter = $this->prophesize(StoredObjectToPdfConverter::class); + $converter->addConvertedVersion(Argument::type(StoredObject::class), 'fr', 'pdf') + ->shouldNotBeCalled(); + + $entityWorkflowManager = $this->prophesize(EntityWorkflowManager::class); + $entityWorkflowManager->getAssociatedStoredObject($entityWorkflow)->willReturn(null); + + $request = new Request(); + $request->setLocale('fr'); + $stack = new RequestStack(); + $stack->push($request); + + $eventSubscriber = new ConvertToPdfBeforeSignatureStepEventSubscriber($entityWorkflowManager->reveal(), $converter->reveal(), $stack); + + $registry = $this->buildRegistry($eventSubscriber); + $workflow = $registry->get($entityWorkflow, 'dummy'); + + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $workflow->apply($entityWorkflow, 'to_signature', ['context' => $dto, 'transition' => 'to_signature', 'transitionAt' => new \DateTimeImmutable('now')]); + + self::assertEquals('signature', $entityWorkflow->getStep()); + } + + private function buildRegistry(EventSubscriberInterface $eventSubscriber): Registry + { + $builder = new DefinitionBuilder(); + $builder + ->setInitialPlaces('initial') + ->addPlaces(['initial', 'signature', 'something']) + ->addTransition(new Transition('to_something', 'initial', 'something')) + ->addTransition(new Transition('to_signature', 'initial', 'signature')); + + $metadataStore = new InMemoryMetadataStore([], ['signature' => ['isSignature' => ['user']]]); + $builder->setMetadataStore($metadataStore); + + $eventDispatcher = new EventDispatcher(); + $eventDispatcher->addSubscriber($eventSubscriber); + + $workflow = new Workflow($builder->build(), new EntityWorkflowMarkingStore(), $eventDispatcher, 'dummy'); + + $supports = new class () implements WorkflowSupportStrategyInterface { + public function supports(WorkflowInterface $workflow, object $subject): bool + { + return true; + } + }; + + $registry = new Registry(); + $registry->addWorkflow($workflow, $supports); + + return $registry; + } +} diff --git a/src/Bundle/ChillDocStoreBundle/Workflow/ConvertToPdfBeforeSignatureStepEventSubscriber.php b/src/Bundle/ChillDocStoreBundle/Workflow/ConvertToPdfBeforeSignatureStepEventSubscriber.php new file mode 100644 index 000000000..0d5fe9323 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Workflow/ConvertToPdfBeforeSignatureStepEventSubscriber.php @@ -0,0 +1,75 @@ + 'convertToPdfBeforeSignatureStepEvent', + ]; + } + + public function convertToPdfBeforeSignatureStepEvent(CompletedEvent $event): void + { + $entityWorkflow = $event->getSubject(); + if (!$entityWorkflow instanceof EntityWorkflow) { + return; + } + + $tos = $event->getTransition()->getTos(); + $workflow = $event->getWorkflow(); + $metadataStore = $workflow->getMetadataStore(); + + foreach ($tos as $to) { + $metadata = $metadataStore->getPlaceMetadata($to); + if (array_key_exists('isSignature', $metadata) && 0 < count($metadata['isSignature'])) { + $this->convertToPdf($entityWorkflow); + + return; + } + } + } + + private function convertToPdf(EntityWorkflow $entityWorkflow): void + { + $storedObject = $this->entityWorkflowManager->getAssociatedStoredObject($entityWorkflow); + + if (null === $storedObject) { + return; + } + + if ('application/pdf' === $storedObject->getCurrentVersion()->getType()) { + return; + } + + $this->storedObjectToPdfConverter->addConvertedVersion($storedObject, $this->requestStack->getCurrentRequest()->getLocale(), 'pdf'); + } +}