Skip to content

Commit 4902f48

Browse files
committed
add output normalizer
1 parent 76ceaa1 commit 4902f48

File tree

10 files changed

+160
-83
lines changed

10 files changed

+160
-83
lines changed

api/bin/phpunit

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
#!/usr/bin/env php
22
<?php
33

4-
if (!file_exists(dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php')) {
5-
echo "Unable to find the `simple-phpunit.php` script in `vendor/symfony/phpunit-bridge/bin/`.\n";
6-
exit(1);
4+
if (!ini_get('date.timezone')) {
5+
ini_set('date.timezone', 'UTC');
76
}
87

9-
if (false === getenv('SYMFONY_PHPUNIT_DIR')) {
10-
putenv('SYMFONY_PHPUNIT_DIR='.__DIR__.'/.phpunit');
11-
}
8+
if (is_file(dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit')) {
9+
if (PHP_VERSION_ID >= 80000) {
10+
require dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit';
11+
} else {
12+
define('PHPUNIT_COMPOSER_INSTALL', dirname(__DIR__).'/vendor/autoload.php');
13+
require PHPUNIT_COMPOSER_INSTALL;
14+
PHPUnit\TextUI\Command::main();
15+
}
16+
} else {
17+
if (!is_file(dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php')) {
18+
echo "Unable to find the `simple-phpunit.php` script in `vendor/symfony/phpunit-bridge/bin/`.\n";
19+
exit(1);
20+
}
1221

13-
require dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php';
22+
require dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php';
23+
}

api/config/packages/messenger.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,16 @@ framework:
2323
# # replace with your transport name here (e.g., my_transport: 'in-memory://')
2424
# # For more Messenger testing tools, see https://github.com/zenstruck/messenger-test
2525
# async: 'in-memory://'
26+
27+
28+
when@dev:
29+
framework:
30+
messenger:
31+
transports:
32+
async: 'sync://'
33+
34+
when@test:
35+
framework:
36+
messenger:
37+
transports:
38+
async: 'test://'

api/config/services.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ services:
5353

5454
GuzzleHttp\ClientInterface: '@GuzzleHttp\Client'
5555

56-
App\Api\DataTransformer\ArchiveInputProcessor:
56+
App\Api\Processor\ArchiveInputProcessor:
5757
arguments:
5858
$maxExpirationTime: '%env(int:MAX_EXPIRATION_TIME)%'
5959

api/src/Api/DataTransformer/ArchiveOutputProvider.php

Lines changed: 0 additions & 52 deletions
This file was deleted.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Api\Normalizer;
6+
7+
use App\Api\Transformer\ArchiveOutputTransformer;
8+
use App\Entity\Archive;
9+
use Symfony\Component\Serializer\SerializerInterface;
10+
use Symfony\Component\Serializer\SerializerAwareInterface;
11+
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
12+
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
13+
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
14+
15+
#[AsDecorator('api_platform.jsonld.normalizer.item')]
16+
final class OutputNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface
17+
{
18+
private $decorated;
19+
private ArchiveOutputTransformer $archiveOutputTransformer;
20+
21+
public function __construct(NormalizerInterface $decorated, ArchiveOutputTransformer $archiveOutputTransformer)
22+
{
23+
if (!$decorated instanceof DenormalizerInterface) {
24+
throw new \InvalidArgumentException(sprintf('The decorated normalizer must implement the %s.', DenormalizerInterface::class));
25+
}
26+
27+
$this->decorated = $decorated;
28+
$this->archiveOutputTransformer = $archiveOutputTransformer;
29+
}
30+
31+
public function supportsNormalization($data, $format = null)
32+
{
33+
return $this->decorated->supportsNormalization($data, $format);
34+
}
35+
36+
public function normalize($object, $format = null, array $context = [])
37+
{
38+
if ($object instanceof Archive) {
39+
$outputArchive = $this->archiveOutputTransformer->transform($object);
40+
41+
return $this->decorated->normalize($outputArchive, $format, $context);
42+
}
43+
44+
return $this->decorated->normalize($object, $format, $context);
45+
}
46+
47+
public function supportsDenormalization($data, $type, $format = null)
48+
{
49+
return $this->decorated->supportsDenormalization($data, $type, $format);
50+
}
51+
52+
public function denormalize($data, string $type, string $format = null, array $context = [])
53+
{
54+
return $this->decorated->denormalize($data, $type, $format, $context);
55+
}
56+
57+
public function setSerializer(SerializerInterface $serializer)
58+
{
59+
if($this->decorated instanceof SerializerAwareInterface) {
60+
$this->decorated->setSerializer($serializer);
61+
}
62+
}
63+
}

api/src/Api/DataTransformer/ArchiveInputProcessor.php renamed to api/src/Api/Processor/ArchiveInputProcessor.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,19 @@
22

33
declare(strict_types=1);
44

5-
namespace App\Api\DataTransformer;
5+
namespace App\Api\Processor;
66

77
use DateTime;
88
use App\Entity\Archive;
99
use ApiPlatform\Metadata\Operation;
1010
use App\Archive\IdentifierGenerator;
11+
use App\Consumer\Handler\BuildMessage;
12+
use Doctrine\ORM\EntityManagerInterface;
1113
use ApiPlatform\State\ProcessorInterface;
1214
use Symfony\Bundle\SecurityBundle\Security;
1315
use ApiPlatform\Validator\ValidatorInterface;
1416
use ApiPlatform\Serializer\AbstractItemNormalizer;
1517
use Alchemy\Zippy\Archive\Archive as ArchiveArchive;
16-
use App\Consumer\Handler\BuildMessage;
1718
use Symfony\Component\Messenger\MessageBusInterface;
1819
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
1920

@@ -24,8 +25,10 @@ class ArchiveInputProcessor implements ProcessorInterface
2425
private ?int $maxExpirationTime;
2526
private Security $security;
2627
private MessageBusInterface $bus;
28+
private EntityManagerInterface $em;
2729

2830
public function __construct(
31+
EntityManagerInterface $em,
2932
ValidatorInterface $validator,
3033
IdentifierGenerator $identifierGenerator,
3134
Security $security,
@@ -38,11 +41,11 @@ public function __construct(
3841
$this->maxExpirationTime = $maxExpirationTime;
3942
$this->security = $security;
4043
$this->bus = $bus;
44+
$this->em = $em;
4145
}
4246

4347
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): Archive
4448
{
45-
4649
$isNew = !isset($context[AbstractItemNormalizer::OBJECT_TO_POPULATE]);
4750

4851
$this->validator->validate($data, [
@@ -92,8 +95,11 @@ public function process(mixed $data, Operation $operation, array $uriVariables =
9295

9396
$object->setClient($this->security->getUser()->getUserIdentifier());
9497

98+
$this->em->persist($object);
99+
$this->em->flush();
100+
95101
$this->bus->dispatch(new BuildMessage((['id' => $object->getId()])));
96-
102+
97103
return $object;
98104
}
99105
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Api\Transformer;
6+
7+
use App\Api\ArchiveOutput;
8+
use App\Security\JWTManager;
9+
use Doctrine\ORM\EntityManagerInterface;
10+
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
11+
12+
class ArchiveOutputTransformer
13+
{
14+
private UrlGeneratorInterface $urlGenerator;
15+
private JWTManager $JWTManager;
16+
17+
18+
public function __construct(UrlGeneratorInterface $urlGenerator, JWTManager $JWTManager)
19+
{
20+
$this->urlGenerator = $urlGenerator;
21+
$this->JWTManager = $JWTManager;
22+
}
23+
24+
public function transform(mixed $data): ArchiveOutput
25+
{
26+
$output = new ArchiveOutput();
27+
$output->setCreatedAt($data->getCreatedAt());
28+
$output->setUpdatedAt($data->getUpdatedAt());
29+
$output->setId($data->getId());
30+
$output->setIdentifier($data->getIdentifier());
31+
$output->setStatus($data->getStatusLabel());
32+
$output->setExpiresAt($data->getExpiresAt());
33+
34+
$output->setDownloadUrl($this->urlGenerator->generate('download_archive', [
35+
'id' => $data->getId(),
36+
'jwt' => $this->JWTManager->getArchiveJWT($data->getId()),
37+
], UrlGeneratorInterface::ABSOLUTE_URL));
38+
39+
return $output;
40+
}
41+
}

api/src/Controller/DownloadController.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@
1818

1919
class DownloadController extends AbstractController
2020
{
21-
/**
22-
* @Route("/archives/{id}/download", name="download_archive")
23-
*/
21+
#[Route("/archives/{id}/download", name:"download_archive")]
2422
public function __invoke(string $id, Request $request, ArchiveManager $archiveManager, JWTManager $JWTManager): Response
2523
{
2624
$jwt = $request->query->get('jwt');

api/src/Entity/Archive.php

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,11 @@
1717
use Ramsey\Uuid\Doctrine\UuidType;
1818
use ApiPlatform\Metadata\ApiProperty;
1919
use ApiPlatform\Metadata\ApiResource;
20+
use App\Api\Processor\ArchiveInputProcessor;
2021
use App\Repository\ArchiveRepository;
2122
use Gedmo\Mapping\Annotation as Gedmo;
22-
use ApiPlatform\Metadata\GetCollection;
2323
use Doctrine\Common\Collections\Collection;
2424
use Doctrine\Common\Collections\ArrayCollection;
25-
use App\Api\DataTransformer\ArchiveInputProcessor;
26-
use App\Api\DataTransformer\ArchiveOutputProvider;
2725

2826
#[ApiResource(
2927
shortName: "archive",
@@ -33,17 +31,17 @@
3331
"skip_null_values" => false,
3432
],
3533
denormalizationContext: ["groups"=> ["archive:write"]],
36-
input: ArchiveInput::class,
37-
output: ArchiveOutput::class,
3834
operations: [
39-
new GetCollection(),
40-
new Post(),
41-
new Get(),
42-
new Patch(),
43-
new Delete()
35+
new Post(
36+
input: ArchiveInput::class,
37+
processor: ArchiveInputProcessor::class
38+
),
39+
new Get(),
40+
new Patch(),
41+
new Delete(),
4442
],
45-
processor: ArchiveInputProcessor::class,
46-
provider: ArchiveOutputProvider::class
43+
input: ArchiveInput::class,
44+
output: ArchiveOutput::class
4745
)]
4846
#[ORM\Entity(repositoryClass: ArchiveRepository::class)]
4947
#[ORM\Table]

api/symfony.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -407,12 +407,12 @@
407407
"version": "v2.1.0"
408408
},
409409
"symfony/phpunit-bridge": {
410-
"version": "5.1",
410+
"version": "7.2",
411411
"recipe": {
412412
"repo": "github.com/symfony/recipes",
413-
"branch": "master",
414-
"version": "5.1",
415-
"ref": "bf16921ef8309a81d9f046e9b6369c46bcbd031f"
413+
"branch": "main",
414+
"version": "6.3",
415+
"ref": "a411a0480041243d97382cac7984f7dce7813c08"
416416
},
417417
"files": [
418418
".env.test",

0 commit comments

Comments
 (0)