From 3b262421210ac0ee664e97dc21115f16bea360ec Mon Sep 17 00:00:00 2001 From: "Nek (Maxime Veber)" Date: Wed, 19 Aug 2020 01:19:13 +0200 Subject: [PATCH] feat(serialization): add context builder This commit fix #10 by adding the toolkit for having custom serialization context. --- .../DependencyInjection/MelodiiaExtension.php | 5 ++ .../Symfony/Resources/config/services.yaml | 7 +++ .../Listener/SerializeOnKernelView.php | 11 +++- .../Context/ContextBuilderChain.php | 29 +++++++++ .../Context/ContextBuilderChainInterface.php | 12 ++++ .../Context/ContextBuilderInterface.php | 18 ++++++ .../Listener/SerializeOnKernelViewTest.php | 17 ++++- .../Context/ContextBuilderFactoryTest.php | 63 +++++++++++++++++++ 8 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 src/Serialization/Context/ContextBuilderChain.php create mode 100644 src/Serialization/Context/ContextBuilderChainInterface.php create mode 100644 src/Serialization/Context/ContextBuilderInterface.php create mode 100644 tests/Melodiia/Serialization/Context/ContextBuilderFactoryTest.php diff --git a/src/Bridge/Symfony/DependencyInjection/MelodiiaExtension.php b/src/Bridge/Symfony/DependencyInjection/MelodiiaExtension.php index 78dbc07..e5262d7 100644 --- a/src/Bridge/Symfony/DependencyInjection/MelodiiaExtension.php +++ b/src/Bridge/Symfony/DependencyInjection/MelodiiaExtension.php @@ -10,6 +10,7 @@ use SwagIndustries\Melodiia\Documentation\Controller\OpenApiController; use SwagIndustries\Melodiia\Documentation\Controller\OpenApiJsonController; use SwagIndustries\Melodiia\Documentation\OpenApiDocFactory; +use SwagIndustries\Melodiia\Serialization\Context\ContextBuilderInterface; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; @@ -21,6 +22,7 @@ class MelodiiaExtension extends Extension { const TAG_CRUD_FILTER = 'melodiia.crud_filter'; + const TAG_CONTEXT_BUILDER = 'melodiia.context_builder'; public function load(array $configs, ContainerBuilder $container) { @@ -42,6 +44,9 @@ public function load(array $configs, ContainerBuilder $container) // Autoconf $container->registerForAutoconfiguration(FilterInterface::class)->addTag(self::TAG_CRUD_FILTER); + $container + ->registerForAutoconfiguration(ContextBuilderInterface::class) + ->addTag(self::TAG_CONTEXT_BUILDER); } private function configureApi(string $name, array $apiConf, ContainerBuilder $container) diff --git a/src/Bridge/Symfony/Resources/config/services.yaml b/src/Bridge/Symfony/Resources/config/services.yaml index 1e91fc7..a5d9819 100644 --- a/src/Bridge/Symfony/Resources/config/services.yaml +++ b/src/Bridge/Symfony/Resources/config/services.yaml @@ -35,6 +35,13 @@ services: class: SwagIndustries\Melodiia\Response\Listener\SerializeOnKernelView autoconfigure: true autowire: true + arguments: + $contextBuilderChain: '@melodiia.context_builder_chain' + + melodiia.context_builder_chain: + class: SwagIndustries\Melodiia\Serialization\Context\ContextBuilderChain + arguments: + $builders: !tagged_iterator melodiia.context_builder imports: - 'crud.yaml' diff --git a/src/Response/Listener/SerializeOnKernelView.php b/src/Response/Listener/SerializeOnKernelView.php index 9fc237d..65dba3a 100644 --- a/src/Response/Listener/SerializeOnKernelView.php +++ b/src/Response/Listener/SerializeOnKernelView.php @@ -5,6 +5,7 @@ namespace SwagIndustries\Melodiia\Response\Listener; use SwagIndustries\Melodiia\Response\ApiResponse; +use SwagIndustries\Melodiia\Serialization\Context\ContextBuilderChainInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpKernel\Event\ViewEvent; @@ -23,9 +24,13 @@ class SerializeOnKernelView implements EventSubscriberInterface */ private $serializer; - public function __construct(SerializerInterface $serializer) + /** @var ContextBuilderChainInterface */ + private $contextBuilderChain; + + public function __construct(SerializerInterface $serializer, ContextBuilderChainInterface $contextBuilderChain) { $this->serializer = $serializer; + $this->contextBuilderChain = $contextBuilderChain; } public static function getSubscribedEvents() @@ -42,9 +47,11 @@ public function onKernelView(ViewEvent $event) return; } + $context = $this->contextBuilderChain->buildContext([], $response); + $event->setResponse( new JsonResponse( - $this->serializer->serialize($response, 'json'), + $this->serializer->serialize($response, 'json', $context), $response->httpStatus(), [], true diff --git a/src/Serialization/Context/ContextBuilderChain.php b/src/Serialization/Context/ContextBuilderChain.php new file mode 100644 index 0000000..111605b --- /dev/null +++ b/src/Serialization/Context/ContextBuilderChain.php @@ -0,0 +1,29 @@ +builders = $builders; + } + + public function buildContext(array $context, ApiResponse $response): array + { + foreach ($this->builders as $builder) { + if ($builder->supports($response)) { + $context = $builder->buildContext($context, $response); + } + } + + return $context; + } +} diff --git a/src/Serialization/Context/ContextBuilderChainInterface.php b/src/Serialization/Context/ContextBuilderChainInterface.php new file mode 100644 index 0000000..c5b09cd --- /dev/null +++ b/src/Serialization/Context/ContextBuilderChainInterface.php @@ -0,0 +1,12 @@ +serializer = $this->prophesize(SerializerInterface::class); - $this->listener = new SerializeOnKernelView($this->serializer->reveal()); + $this->contextChain = $this->prophesize(ContextBuilderChainInterface::class); + $this->contextChain->buildContext(Argument::cetera())->willReturn([]); + $this->listener = new SerializeOnKernelView($this->serializer->reveal(), $this->contextChain->reveal()); + } + + public function tearDown(): void + { + $this->serializer = null; + $this->contextChain = null; + $this->listener = null; } public function testItSubscribeOnKernelView() diff --git a/tests/Melodiia/Serialization/Context/ContextBuilderFactoryTest.php b/tests/Melodiia/Serialization/Context/ContextBuilderFactoryTest.php new file mode 100644 index 0000000..2d6942f --- /dev/null +++ b/tests/Melodiia/Serialization/Context/ContextBuilderFactoryTest.php @@ -0,0 +1,63 @@ +buildContext([], $this->prophesize(ApiResponse::class)->reveal()); + $this->assertTrue($context['foo']); + $this->assertTrue($context['bar']); + $this->assertFalse(isset($context['baz'])); + } +}