diff --git a/UPGRADE-API-1.13.md b/UPGRADE-API-1.13.md index 1b441c0a168..ba0e6b3c140 100644 --- a/UPGRADE-API-1.13.md +++ b/UPGRADE-API-1.13.md @@ -1,5 +1,18 @@ # UPGRADE FROM `v1.12.x` TO `v1.13.0` +1. All the `:read` serialization groups are now split to `index` and `show`. + By this change, the `:read` serialization group is now deprecated and will no more used in the future. + There is a BC layer that will allow you to use the `:read` serialization group `Sylius\Bundle\ApiBundle\SerializerContextBuilder\ReadOperationContextBuilder` by adding the `read` serialization group to your context. + Inside of this service there are 2 configurable parameters `$skipAddingReadGroup` and `$skipAddingIndexAndShowGroups` that will allow you to skip adding the chosen serialization group to your context. + To configure skipping adding the index and show or read serialization groups to the context, add the following configuration to your `config/packages/_sylius.yaml` file: + + ```yaml + sylius_api: + serialization_groups: + skip_adding_index_and_show_groups: true + skip_adding_read_group: true + ``` + 1. The constructor of `Sylius\Bundle\ApiBundle\Serializer\ChannelDenormalizer` has been changed: ```diff diff --git a/src/Sylius/Bundle/ApiBundle/DependencyInjection/Configuration.php b/src/Sylius/Bundle/ApiBundle/DependencyInjection/Configuration.php index 07e6c289d71..ed0839b3a49 100644 --- a/src/Sylius/Bundle/ApiBundle/DependencyInjection/Configuration.php +++ b/src/Sylius/Bundle/ApiBundle/DependencyInjection/Configuration.php @@ -41,6 +41,19 @@ public function getConfigTreeBuilder(): TreeBuilder ->scalarPrototype()->end() ->end() ->end() + ->children() + ->arrayNode('serialization_groups') + ->addDefaultsIfNotSet() + ->children() + ->booleanNode('skip_adding_read_group') + ->defaultFalse() + ->end() + ->booleanNode('skip_adding_index_and_show_groups') + ->defaultFalse() + ->end() + ->end() + ->end() + ->end() ->children() ->variableNode('product_image_prefix') ->defaultValue('media/image') diff --git a/src/Sylius/Bundle/ApiBundle/DependencyInjection/SyliusApiExtension.php b/src/Sylius/Bundle/ApiBundle/DependencyInjection/SyliusApiExtension.php index 2bc40dab2e9..c8bc585d366 100644 --- a/src/Sylius/Bundle/ApiBundle/DependencyInjection/SyliusApiExtension.php +++ b/src/Sylius/Bundle/ApiBundle/DependencyInjection/SyliusApiExtension.php @@ -39,6 +39,8 @@ public function load(array $configs, ContainerBuilder $container): void $config['filter_eager_loading_extension']['restricted_resources'], ); $container->setParameter('sylius_api.order_states_to_filter_out', $config['order_states_to_filter_out']); + $container->setParameter('sylius_api.serialization_groups.skip_adding_read_group', $config['serialization_groups']['skip_adding_read_group']); + $container->setParameter('sylius_api.serialization_groups.skip_adding_index_and_show_groups', $config['serialization_groups']['skip_adding_index_and_show_groups']); $loader->load('services.xml'); diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/services/context_builders.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/services/context_builders.xml index 97b341e9ee8..a5292631a74 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/context_builders.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/context_builders.xml @@ -27,6 +27,16 @@ + + + %sylius_api.serialization_groups.skip_adding_read_group% + %sylius_api.serialization_groups.skip_adding_index_and_show_groups% + + $extractedAttributes + * + * @return array + */ + public function createFromRequest(Request $request, bool $normalization, array $extractedAttributes = null): array + { + $context = $this->decorated->createFromRequest($request, $normalization, $extractedAttributes); + + $groups = $context['groups'] ?? []; + $groups = is_string($groups) ? [$groups] : $groups; + + if ($groups === []) { + return $context; + } + + foreach ($groups as $group) { + if ($this->shouldReadGroupBeAdded($group) && !$this->skipAddingReadGroup) { + $readGroup = str_replace([':show', ':index'], ':read', $group); + + if (in_array($readGroup, $groups, true)) { + continue; + } + + $groups[] = $readGroup; + } + + if ($this->shouldIndexAndShowGroupsBeAdded($group) && !$this->skipAddingIndexAndShowGroups) { + $indexGroup = str_replace(':read', ':index', $group); + $showGroup = str_replace(':read', ':show', $group); + + if (!in_array($indexGroup, $groups, true)) { + $groups[] = $indexGroup; + } + + if (!in_array($showGroup, $groups, true)) { + $groups[] = $showGroup; + } + } + } + + $context['groups'] = $groups; + + return $context; + } + + private function shouldReadGroupBeAdded(string $group): bool + { + return str_ends_with($group, ':show') || str_ends_with($group, ':index'); + } + + private function shouldIndexAndShowGroupsBeAdded(string $group): bool + { + return str_ends_with($group, ':read'); + } +} diff --git a/src/Sylius/Bundle/ApiBundle/Tests/DependencyInjection/SyliusApiExtensionTest.php b/src/Sylius/Bundle/ApiBundle/Tests/DependencyInjection/SyliusApiExtensionTest.php index f9de62d6bf0..da649561b40 100644 --- a/src/Sylius/Bundle/ApiBundle/Tests/DependencyInjection/SyliusApiExtensionTest.php +++ b/src/Sylius/Bundle/ApiBundle/Tests/DependencyInjection/SyliusApiExtensionTest.php @@ -106,6 +106,28 @@ public function it_loads_order_states_to_filter_out_parameter_properly(): void ); } + /** @test */ + public function it_loads_skip_read_and_skip_index_and_show_serialization_groups_parameters_properly(): void + { + $this->container->setParameter('kernel.bundles_metadata', ['SyliusApiBundle' => ['path' => __DIR__ . '../..']]); + + $this->load([ + 'serialization_groups' => [ + 'skip_adding_read_group' => true, + 'skip_adding_index_and_show_groups' => false, + ], + ]); + + $this->assertContainerBuilderHasParameter( + 'sylius_api.serialization_groups.skip_adding_read_group', + true, + ); + $this->assertContainerBuilderHasParameter( + 'sylius_api.serialization_groups.skip_adding_index_and_show_groups', + false, + ); + } + /** @test */ public function it_loads_default_filter_eager_loading_extension_restricted_operations_configuration_properly(): void { diff --git a/src/Sylius/Bundle/ApiBundle/spec/SerializerContextBuilder/ReadOperationContextBuilderSpec.php b/src/Sylius/Bundle/ApiBundle/spec/SerializerContextBuilder/ReadOperationContextBuilderSpec.php new file mode 100644 index 00000000000..5617133a554 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/spec/SerializerContextBuilder/ReadOperationContextBuilderSpec.php @@ -0,0 +1,83 @@ +beConstructedWith($decoratedSerializerContextBuilder, false, false); + } + + function it_updates_an_context_with_index_and_show_serialization_groups_if_only_read_provided( + Request $request, + SerializerContextBuilderInterface $decoratedSerializerContextBuilder, + ): void { + $decoratedSerializerContextBuilder->createFromRequest($request, true, [])->willReturn([ + 'groups' => ['foo:read'], + ]); + + $this->createFromRequest($request, true, [])->shouldReturn([ + 'groups' => ['foo:read', 'foo:index', 'foo:show'], + ]); + } + + function it_updates_an_context_with_read_serialization_groups_if_only_index_and_show_provided( + Request $request, + SerializerContextBuilderInterface $decoratedSerializerContextBuilder, + ): void { + $decoratedSerializerContextBuilder->createFromRequest($request, true, [])->willReturn([ + 'groups' => ['foo:read'], + ]); + + $this->createFromRequest($request, true, [])->shouldReturn([ + 'groups' => ['foo:read', 'foo:index', 'foo:show'], + ]); + } + + function it_does_not_update_context_with_read_group_if_skip_adding_read_parameter_is_set_to_true( + Request $request, + SerializerContextBuilderInterface $decoratedSerializerContextBuilder, + ): void { + $this->beConstructedWith($decoratedSerializerContextBuilder, true, false); + + $decoratedSerializerContextBuilder->createFromRequest($request, true, [])->willReturn([ + 'groups' => ['foo:show'], + ]); + + $this->createFromRequest($request, true, [])->shouldReturn([ + 'groups' => ['foo:show'], + ]); + } + + function it_does_not_update_context_with_show_and_index_group_if_skip_adding_show_and_index_is_set_to_true( + Request $request, + SerializerContextBuilderInterface $decoratedSerializerContextBuilder, + ): void { + $this->beConstructedWith($decoratedSerializerContextBuilder, false, true); + + $decoratedSerializerContextBuilder->createFromRequest($request, true, [])->willReturn([ + 'groups' => ['foo:read'], + ]); + + $this->createFromRequest($request, true, [])->shouldReturn([ + 'groups' => ['foo:read'], + ]); + } +}