mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-21 23:23:51 +00:00
Merge signature-app-master into branch
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
<?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\DocStoreBundle\Controller;
|
||||
|
||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\RequestPdfSignMessage;
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFPage;
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone;
|
||||
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class SignatureRequestController
|
||||
{
|
||||
public function __construct(
|
||||
private MessageBusInterface $messageBus,
|
||||
private StoredObjectManagerInterface $storedObjectManager,
|
||||
) {}
|
||||
|
||||
#[Route('/api/1.0/document/workflow/{id}/signature-request', name: 'chill_docstore_signature_request')]
|
||||
public function processSignature(StoredObject $storedObject): Response
|
||||
{
|
||||
$content = $this->storedObjectManager->read($storedObject);
|
||||
|
||||
$this->messageBus->dispatch(new RequestPdfSignMessage(
|
||||
0,
|
||||
new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)),
|
||||
0,
|
||||
'test signature',
|
||||
'Mme Caroline Diallo',
|
||||
$content
|
||||
));
|
||||
|
||||
return new Response('<html><head><title>test</title></head><body><p>ok</p></body></html>');
|
||||
}
|
||||
}
|
@@ -313,4 +313,19 @@ class StoredObject implements Document, TrackCreationInterface
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function saveHistory(): void
|
||||
{
|
||||
if ('' === $this->getFilename()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->datas['history'][] = [
|
||||
'filename' => $this->getFilename(),
|
||||
'iv' => $this->getIv(),
|
||||
'key_infos' => $this->getKeyInfos(),
|
||||
'type' => $this->getType(),
|
||||
'before' => (new \DateTimeImmutable('now'))->getTimestamp(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -57,8 +57,8 @@ class StoredObjectDataMapper implements DataMapperInterface
|
||||
|
||||
/** @var StoredObject $viewData */
|
||||
if ($viewData->getFilename() !== $forms['stored_object']->getData()['filename']) {
|
||||
// we do not want to erase the previous object
|
||||
$viewData = new StoredObject();
|
||||
// we want to keep the previous history
|
||||
$viewData->saveHistory();
|
||||
}
|
||||
|
||||
$viewData->setFilename($forms['stored_object']->getData()['filename']);
|
||||
|
@@ -4,13 +4,13 @@
|
||||
Actions
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li v-if="props.canEdit && is_extension_editable(props.storedObject.type)">
|
||||
<li v-if="props.canEdit && is_extension_editable(props.storedObject.type) && props.storedObject.status !== 'stored_object_created'">
|
||||
<wopi-edit-button :stored-object="props.storedObject" :classes="{'dropdown-item': true}" :execute-before-leave="props.executeBeforeLeave"></wopi-edit-button>
|
||||
</li>
|
||||
<li v-if="props.canEdit && is_extension_editable(props.storedObject.type) && props.davLink !== undefined && props.davLinkExpiration !== undefined">
|
||||
<desktop-edit-button :classes="{'dropdown-item': true}" :edit-link="props.davLink" :expiration-link="props.davLinkExpiration"></desktop-edit-button>
|
||||
</li>
|
||||
<li v-if="props.storedObject.type != 'application/pdf' && is_extension_viewable(props.storedObject.type) && props.canConvertPdf">
|
||||
<li v-if="props.storedObject.type != 'application/pdf' && is_extension_viewable(props.storedObject.type) && props.canConvertPdf && props.storedObject.status !== 'stored_object_created'">
|
||||
<convert-button :stored-object="props.storedObject" :filename="filename" :classes="{'dropdown-item': true}"></convert-button>
|
||||
</li>
|
||||
<li v-if="props.canDownload">
|
||||
|
@@ -13,7 +13,7 @@ import {reactive} from "vue";
|
||||
import {StoredObject, StoredObjectCreated} from "../../types";
|
||||
|
||||
interface ConvertButtonConfig {
|
||||
storedObject: StoredObject|StoredObjectCreated,
|
||||
storedObject: StoredObject,
|
||||
classes: { [key: string]: boolean},
|
||||
filename?: string,
|
||||
};
|
||||
|
@@ -11,7 +11,7 @@ import {build_wopi_editor_link} from "./helpers";
|
||||
import {StoredObject, StoredObjectCreated, WopiEditButtonExecutableBeforeLeaveFunction} from "../../types";
|
||||
|
||||
interface WopiEditButtonConfig {
|
||||
storedObject: StoredObject|StoredObjectCreated,
|
||||
storedObject: StoredObject,
|
||||
returnPath?: string,
|
||||
classes: {[k: string] : boolean},
|
||||
executeBeforeLeave?: WopiEditButtonExecutableBeforeLeaveFunction,
|
||||
|
@@ -0,0 +1,23 @@
|
||||
<?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\DocStoreBundle\Service\Signature\Driver\BaseSigner;
|
||||
|
||||
/**
|
||||
* Message which is received when a pdf is signed.
|
||||
*/
|
||||
final readonly class PdfSignedMessage
|
||||
{
|
||||
public function __construct(
|
||||
public readonly int $signatureId,
|
||||
public readonly string $content
|
||||
) {}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
<?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\DocStoreBundle\Service\Signature\Driver\BaseSigner;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
|
||||
|
||||
final readonly class PdfSignedMessageHandler implements MessageHandlerInterface
|
||||
{
|
||||
/**
|
||||
* log prefix.
|
||||
*/
|
||||
private const P = '[pdf signed message] ';
|
||||
|
||||
public function __construct(
|
||||
private LoggerInterface $logger,
|
||||
) {}
|
||||
|
||||
public function __invoke(PdfSignedMessage $message): void
|
||||
{
|
||||
$this->logger->info(self::P.'a message is received', ['signaturedId' => $message->signatureId]);
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
<?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\DocStoreBundle\Service\Signature\Driver\BaseSigner;
|
||||
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
use Symfony\Component\Messenger\Exception\MessageDecodingFailedException;
|
||||
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
|
||||
|
||||
/**
|
||||
* Decode (and requeue) @see{PdfSignedMessage}, which comes from an external producer.
|
||||
*/
|
||||
final readonly class PdfSignedMessageSerializer implements SerializerInterface
|
||||
{
|
||||
public function decode(array $encodedEnvelope): Envelope
|
||||
{
|
||||
$body = $encodedEnvelope['body'];
|
||||
|
||||
try {
|
||||
$decoded = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
|
||||
} catch (\JsonException $e) {
|
||||
throw new MessageDecodingFailedException('Could not deserialize message', previous: $e);
|
||||
}
|
||||
|
||||
if (!array_key_exists('signatureId', $decoded) || !array_key_exists('content', $decoded)) {
|
||||
throw new MessageDecodingFailedException('Could not find expected keys: signatureId or content');
|
||||
}
|
||||
|
||||
$content = base64_decode($decoded['content'], true);
|
||||
|
||||
if (false === $content) {
|
||||
throw new MessageDecodingFailedException('Invalid character found in the base64 encoded content');
|
||||
}
|
||||
|
||||
$message = new PdfSignedMessage($decoded['signatureId'], $content);
|
||||
|
||||
return new Envelope($message);
|
||||
}
|
||||
|
||||
public function encode(Envelope $envelope): array
|
||||
{
|
||||
$message = $envelope->getMessage();
|
||||
|
||||
if (!$message instanceof PdfSignedMessage) {
|
||||
throw new MessageDecodingFailedException('Expected a PdfSignedMessage');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'signatureId' => $message->signatureId,
|
||||
'content' => base64_encode($message->content),
|
||||
];
|
||||
|
||||
return [
|
||||
'body' => json_encode($data, JSON_THROW_ON_ERROR),
|
||||
'headers' => [],
|
||||
];
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
<?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\DocStoreBundle\Service\Signature\Driver\BaseSigner;
|
||||
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone;
|
||||
|
||||
/**
|
||||
* Message which is sent when we request a signature on a pdf.
|
||||
*/
|
||||
final readonly class RequestPdfSignMessage
|
||||
{
|
||||
public function __construct(
|
||||
public int $signatureId,
|
||||
public PDFSignatureZone $PDFSignatureZone,
|
||||
public int $signatureZoneIndex,
|
||||
public string $reason,
|
||||
public string $signerText,
|
||||
public string $content,
|
||||
) {}
|
||||
}
|
@@ -0,0 +1,105 @@
|
||||
<?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\DocStoreBundle\Service\Signature\Driver\BaseSigner;
|
||||
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone;
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
use Symfony\Component\Messenger\Exception\MessageDecodingFailedException;
|
||||
use Symfony\Component\Messenger\Stamp\NonSendableStampInterface;
|
||||
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
/**
|
||||
* Serialize a RequestPdfSignMessage, for external consumer.
|
||||
*/
|
||||
final readonly class RequestPdfSignMessageSerializer implements SerializerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private NormalizerInterface $normalizer,
|
||||
private DenormalizerInterface $denormalizer,
|
||||
) {}
|
||||
|
||||
public function decode(array $encodedEnvelope): Envelope
|
||||
{
|
||||
$body = $encodedEnvelope['body'];
|
||||
$headers = $encodedEnvelope['headers'];
|
||||
|
||||
if (RequestPdfSignMessage::class !== ($headers['Message'] ?? null)) {
|
||||
throw new MessageDecodingFailedException('serializer does not support this message');
|
||||
}
|
||||
|
||||
$data = json_decode($body, true);
|
||||
|
||||
$zoneSignature = $this->denormalizer->denormalize($data['signatureZone'], PDFSignatureZone::class, 'json', [
|
||||
AbstractNormalizer::GROUPS => ['write'],
|
||||
]);
|
||||
|
||||
$content = base64_decode($data['content'], true);
|
||||
|
||||
if (false === $content) {
|
||||
throw new MessageDecodingFailedException('the content could not be converted from base64 encoding');
|
||||
}
|
||||
|
||||
$message = new RequestPdfSignMessage(
|
||||
$data['signatureId'],
|
||||
$zoneSignature,
|
||||
$data['signatureZoneIndex'],
|
||||
$data['reason'],
|
||||
$data['signerText'],
|
||||
$content,
|
||||
);
|
||||
|
||||
// in case of redelivery, unserialize any stamps
|
||||
$stamps = [];
|
||||
if (isset($headers['stamps'])) {
|
||||
$stamps = unserialize($headers['stamps']);
|
||||
}
|
||||
|
||||
return new Envelope($message, $stamps);
|
||||
}
|
||||
|
||||
public function encode(Envelope $envelope): array
|
||||
{
|
||||
$message = $envelope->getMessage();
|
||||
|
||||
if (!$message instanceof RequestPdfSignMessage) {
|
||||
throw new MessageDecodingFailedException('Message is not a RequestPdfSignMessage');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'signatureId' => $message->signatureId,
|
||||
'signatureZoneIndex' => $message->signatureZoneIndex,
|
||||
'signatureZone' => $this->normalizer->normalize($message->PDFSignatureZone, 'json', [AbstractNormalizer::GROUPS => ['read']]),
|
||||
'reason' => $message->reason,
|
||||
'signerText' => $message->signerText,
|
||||
'content' => base64_encode($message->content),
|
||||
];
|
||||
|
||||
$allStamps = [];
|
||||
foreach ($envelope->all() as $stamp) {
|
||||
if ($stamp instanceof NonSendableStampInterface) {
|
||||
continue;
|
||||
}
|
||||
$allStamps = [...$allStamps, ...$stamp];
|
||||
}
|
||||
|
||||
return [
|
||||
'body' => json_encode($data, JSON_THROW_ON_ERROR, 512),
|
||||
'headers' => [
|
||||
'stamps' => serialize($allStamps),
|
||||
'Message' => RequestPdfSignMessage::class,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
<?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\DocStoreBundle\Tests\Entity;
|
||||
|
||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class StoredObjectTest extends KernelTestCase
|
||||
{
|
||||
public function testSaveHistory(): void
|
||||
{
|
||||
$storedObject = new StoredObject();
|
||||
$storedObject
|
||||
->setFilename('test_0')
|
||||
->setIv([2, 4, 6, 8])
|
||||
->setKeyInfos(['key' => ['data0' => 'data0']])
|
||||
->setType('text/html');
|
||||
|
||||
$storedObject->saveHistory();
|
||||
|
||||
$storedObject
|
||||
->setFilename('test_1')
|
||||
->setIv([8, 10, 12])
|
||||
->setKeyInfos(['key' => ['data1' => 'data1']])
|
||||
->setType('text/text');
|
||||
|
||||
$storedObject->saveHistory();
|
||||
|
||||
self::assertEquals('test_0', $storedObject->getDatas()['history'][0]['filename']);
|
||||
self::assertEquals([2, 4, 6, 8], $storedObject->getDatas()['history'][0]['iv']);
|
||||
self::assertEquals(['key' => ['data0' => 'data0']], $storedObject->getDatas()['history'][0]['key_infos']);
|
||||
self::assertEquals('text/html', $storedObject->getDatas()['history'][0]['type']);
|
||||
|
||||
self::assertEquals('test_1', $storedObject->getDatas()['history'][1]['filename']);
|
||||
self::assertEquals([8, 10, 12], $storedObject->getDatas()['history'][1]['iv']);
|
||||
self::assertEquals(['key' => ['data1' => 'data1']], $storedObject->getDatas()['history'][1]['key_infos']);
|
||||
self::assertEquals('text/text', $storedObject->getDatas()['history'][1]['type']);
|
||||
}
|
||||
}
|
@@ -56,14 +56,14 @@ class StoredObjectTypeTest extends TypeTestCase
|
||||
{"filename":"abcdef","iv":[10, 15, 20, 30],"keyInfos":[],"type":"text/html","status":"object_store_created"}
|
||||
JSON];
|
||||
$model = new StoredObject();
|
||||
$originalObjectId = spl_object_id($model);
|
||||
$originalObjectId = spl_object_hash($model);
|
||||
$form = $this->factory->create(StoredObjectType::class, $model, ['has_title' => true]);
|
||||
|
||||
$form->submit($formData);
|
||||
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
$model = $form->getData();
|
||||
$this->assertNotEquals($originalObjectId, spl_object_hash($model));
|
||||
$this->assertEquals($originalObjectId, spl_object_hash($model));
|
||||
$this->assertEquals('abcdef', $model->getFilename());
|
||||
$this->assertEquals([10, 15, 20, 30], $model->getIv());
|
||||
$this->assertEquals('text/html', $model->getType());
|
||||
|
@@ -0,0 +1,63 @@
|
||||
<?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\DocStoreBundle\Tests\Service\Signature\Driver\BaseSigner;
|
||||
|
||||
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\PdfSignedMessage;
|
||||
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\PdfSignedMessageSerializer;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class PdfSignedMessageSerializerTest extends TestCase
|
||||
{
|
||||
public function testDecode(): void
|
||||
{
|
||||
$asString = <<<'JSON'
|
||||
{"signatureId": 0, "content": "dGVzdAo="}
|
||||
JSON;
|
||||
|
||||
$actual = $this->buildSerializer()->decode(['body' => $asString]);
|
||||
|
||||
self::assertInstanceOf(Envelope::class, $actual);
|
||||
$message = $actual->getMessage();
|
||||
self::assertInstanceOf(PdfSignedMessage::class, $message);
|
||||
self::assertEquals("test\n", $message->content);
|
||||
self::assertEquals(0, $message->signatureId);
|
||||
}
|
||||
|
||||
public function testEncode(): void
|
||||
{
|
||||
$envelope = new Envelope(
|
||||
new PdfSignedMessage(0, "test\n")
|
||||
);
|
||||
|
||||
$actual = $this->buildSerializer()->encode($envelope);
|
||||
|
||||
self::assertIsArray($actual);
|
||||
self::assertArrayHasKey('body', $actual);
|
||||
self::assertArrayHasKey('headers', $actual);
|
||||
self::assertEquals([], $actual['headers']);
|
||||
|
||||
self::assertEquals(<<<'JSON'
|
||||
{"signatureId":0,"content":"dGVzdAo="}
|
||||
JSON, $actual['body']);
|
||||
}
|
||||
|
||||
private function buildSerializer(): PdfSignedMessageSerializer
|
||||
{
|
||||
return new PdfSignedMessageSerializer();
|
||||
}
|
||||
}
|
@@ -0,0 +1,137 @@
|
||||
<?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\DocStoreBundle\Tests\Service\Signature\Driver\BaseSigner;
|
||||
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFPage;
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone;
|
||||
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\RequestPdfSignMessage;
|
||||
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\RequestPdfSignMessageSerializer;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class RequestPdfSignMessageSerializerTest extends TestCase
|
||||
{
|
||||
public function testEncode(): void
|
||||
{
|
||||
$serializer = $this->buildSerializer();
|
||||
|
||||
$envelope = new Envelope(
|
||||
$request = new RequestPdfSignMessage(
|
||||
0,
|
||||
new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)),
|
||||
0,
|
||||
'metadata to add to the signature',
|
||||
'Mme Caroline Diallo',
|
||||
'abc'
|
||||
),
|
||||
);
|
||||
|
||||
$actual = $serializer->encode($envelope);
|
||||
$expectedBody = json_encode([
|
||||
'signatureId' => $request->signatureId,
|
||||
'signatureZoneIndex' => $request->signatureZoneIndex,
|
||||
'signatureZone' => ['x' => 10.0],
|
||||
'reason' => $request->reason,
|
||||
'signerText' => $request->signerText,
|
||||
'content' => base64_encode($request->content),
|
||||
]);
|
||||
|
||||
self::assertIsArray($actual);
|
||||
self::assertArrayHasKey('body', $actual);
|
||||
self::assertArrayHasKey('headers', $actual);
|
||||
self::assertEquals($expectedBody, $actual['body']);
|
||||
}
|
||||
|
||||
public function testDecode(): void
|
||||
{
|
||||
$serializer = $this->buildSerializer();
|
||||
|
||||
$request = new RequestPdfSignMessage(
|
||||
0,
|
||||
new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)),
|
||||
0,
|
||||
'metadata to add to the signature',
|
||||
'Mme Caroline Diallo',
|
||||
'abc'
|
||||
);
|
||||
|
||||
$bodyAsString = json_encode([
|
||||
'signatureId' => $request->signatureId,
|
||||
'signatureZoneIndex' => $request->signatureZoneIndex,
|
||||
'signatureZone' => ['x' => 10.0],
|
||||
'reason' => $request->reason,
|
||||
'signerText' => $request->signerText,
|
||||
'content' => base64_encode($request->content),
|
||||
], JSON_THROW_ON_ERROR);
|
||||
|
||||
$actual = $serializer->decode([
|
||||
'body' => $bodyAsString,
|
||||
'headers' => [
|
||||
'Message' => RequestPdfSignMessage::class,
|
||||
],
|
||||
]);
|
||||
|
||||
self::assertInstanceOf(RequestPdfSignMessage::class, $actual->getMessage());
|
||||
self::assertEquals($request->signatureId, $actual->getMessage()->signatureId);
|
||||
self::assertEquals($request->signatureZoneIndex, $actual->getMessage()->signatureZoneIndex);
|
||||
self::assertEquals($request->reason, $actual->getMessage()->reason);
|
||||
self::assertEquals($request->signerText, $actual->getMessage()->signerText);
|
||||
self::assertEquals($request->content, $actual->getMessage()->content);
|
||||
self::assertNotNull($actual->getMessage()->PDFSignatureZone);
|
||||
}
|
||||
|
||||
private function buildSerializer(): RequestPdfSignMessageSerializer
|
||||
{
|
||||
$normalizer =
|
||||
new class () implements NormalizerInterface {
|
||||
public function normalize($object, ?string $format = null, array $context = []): array
|
||||
{
|
||||
if (!$object instanceof PDFSignatureZone) {
|
||||
throw new UnexpectedValueException('expected RequestPdfSignMessage');
|
||||
}
|
||||
|
||||
return [
|
||||
'x' => $object->x,
|
||||
];
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, ?string $format = null): bool
|
||||
{
|
||||
return $data instanceof PDFSignatureZone;
|
||||
}
|
||||
};
|
||||
$denormalizer = new class () implements DenormalizerInterface {
|
||||
public function denormalize($data, string $type, ?string $format = null, array $context = [])
|
||||
{
|
||||
return new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0));
|
||||
}
|
||||
|
||||
public function supportsDenormalization($data, string $type, ?string $format = null)
|
||||
{
|
||||
return PDFSignatureZone::class === $type;
|
||||
}
|
||||
};
|
||||
|
||||
$serializer = new Serializer([$normalizer, $denormalizer]);
|
||||
|
||||
return new RequestPdfSignMessageSerializer($serializer, $serializer);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user