Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. SerializerPass.php

class SerializerPass

Adds all services with the tags "serializer.encoder" and "serializer.normalizer" as encoders and normalizers to the "serializer" service.

@author Javier Lopez <f12loalf@gmail.com> @author Robin Chalas <robin.chalas@gmail.com>

Hierarchy

  • class \Symfony\Component\Serializer\DependencyInjection\SerializerPass implements \Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface uses \Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait

Expanded class hierarchy of SerializerPass

File

vendor/symfony/serializer/DependencyInjection/SerializerPass.php, line 31

Namespace

Symfony\Component\Serializer\DependencyInjection
View source
class SerializerPass implements CompilerPassInterface {
    use PriorityTaggedServiceTrait;
    private const NAME_CONVERTER_METADATA_AWARE_ID = 'serializer.name_converter.metadata_aware';
    public function process(ContainerBuilder $container) : void {
        if (!$container->hasDefinition('serializer')) {
            return;
        }
        $namedSerializers = $container->hasParameter('.serializer.named_serializers') ? $container->getParameter('.serializer.named_serializers') : [];
        $this->createNamedSerializerTags($container, 'serializer.normalizer', 'include_built_in_normalizers', $namedSerializers);
        $this->createNamedSerializerTags($container, 'serializer.encoder', 'include_built_in_encoders', $namedSerializers);
        if (!($normalizers = $this->findAndSortTaggedServices('serializer.normalizer.default', $container))) {
            throw new RuntimeException('You must tag at least one service as "serializer.normalizer" to use the "serializer" service.');
        }
        if (!($encoders = $this->findAndSortTaggedServices('serializer.encoder.default', $container))) {
            throw new RuntimeException('You must tag at least one service as "serializer.encoder" to use the "serializer" service.');
        }
        if ($container->hasParameter('serializer.default_context')) {
            $defaultContext = $container->getParameter('serializer.default_context');
            $this->bindDefaultContext($container, array_merge($normalizers, $encoders), $defaultContext);
            $container->getParameterBag()
                ->remove('serializer.default_context');
        }
        $this->configureSerializer($container, 'serializer', $normalizers, $encoders, 'default');
        if ($namedSerializers) {
            $this->configureNamedSerializers($container);
        }
    }
    private function createNamedSerializerTags(ContainerBuilder $container, string $tagName, string $configName, array $namedSerializers) : void {
        $serializerNames = array_keys($namedSerializers);
        $withBuiltIn = array_filter($serializerNames, fn(string $name) => $namedSerializers[$name][$configName] ?? false);
        foreach ($container->findTaggedServiceIds($tagName) as $serviceId => $tags) {
            $definition = $container->getDefinition($serviceId);
            foreach ($tags as $tag) {
                $names = (array) ($tag['serializer'] ?? []);
                if (!$names) {
                    $names = [
                        'default',
                    ];
                }
                elseif (\in_array('*', $names, true)) {
                    $names = array_unique([
                        'default',
                        $serializerNames,
                    ]);
                }
                if ($tag['built_in'] ?? false) {
                    $names = array_unique([
                        'default',
                        $names,
                        $withBuiltIn,
                    ]);
                }
                unset($tag['serializer'], $tag['built_in']);
                foreach ($names as $name) {
                    $definition->addTag($tagName . '.' . $name, $tag);
                }
            }
        }
    }
    private function bindDefaultContext(ContainerBuilder $container, array $services, array $defaultContext) : void {
        foreach ($services as $id) {
            $definition = $container->getDefinition((string) $id);
            $definition->setBindings([
                'array $defaultContext' => new BoundArgument($defaultContext, false),
            ] + $definition->getBindings());
        }
    }
    private function configureSerializer(ContainerBuilder $container, string $id, array $normalizers, array $encoders, string $serializerName) : void {
        if ($container->getParameter('kernel.debug') && $container->hasDefinition('serializer.data_collector')) {
            foreach ($normalizers as $i => $normalizer) {
                $normalizers[$i] = $container->register('.debug.serializer.normalizer.' . $normalizer, TraceableNormalizer::class)
                    ->setArguments([
                    $normalizer,
                    new Reference('serializer.data_collector'),
                    $serializerName,
                ]);
            }
            foreach ($encoders as $i => $encoder) {
                $encoders[$i] = $container->register('.debug.serializer.encoder.' . $encoder, TraceableEncoder::class)
                    ->setArguments([
                    $encoder,
                    new Reference('serializer.data_collector'),
                    $serializerName,
                ]);
            }
        }
        $serializerDefinition = $container->getDefinition($id);
        $serializerDefinition->replaceArgument(0, $normalizers);
        $serializerDefinition->replaceArgument(1, $encoders);
    }
    private function configureNamedSerializers(ContainerBuilder $container) : void {
        $defaultSerializerNameConverter = $container->hasParameter('.serializer.name_converter') ? $container->getParameter('.serializer.name_converter') : null;
        foreach ($container->getParameter('.serializer.named_serializers') as $serializerName => $config) {
            $config += [
                'default_context' => [],
                'name_converter' => null,
            ];
            $serializerId = 'serializer.' . $serializerName;
            if (!($normalizers = $this->findAndSortTaggedServices('serializer.normalizer.' . $serializerName, $container))) {
                throw new RuntimeException(\sprintf('The named serializer "%1$s" requires at least one registered normalizer. Tag the normalizers as "serializer.normalizer" with the "serializer" attribute set to "%1$s".', $serializerName));
            }
            if (!($encoders = $this->findAndSortTaggedServices('serializer.encoder.' . $serializerName, $container))) {
                throw new RuntimeException(\sprintf('The named serializer "%1$s" requires at least one registered encoder. Tag the encoders as "serializer.encoder" with the "serializer" attribute set to "%1$s".', $serializerName));
            }
            $config['name_converter'] = $defaultSerializerNameConverter !== $config['name_converter'] ? $this->buildChildNameConverterDefinition($container, $config['name_converter']) : self::NAME_CONVERTER_METADATA_AWARE_ID;
            $normalizers = $this->buildChildDefinitions($container, $serializerName, $normalizers, $config);
            $encoders = $this->buildChildDefinitions($container, $serializerName, $encoders, $config);
            $this->bindDefaultContext($container, array_merge($normalizers, $encoders), $config['default_context']);
            $container->registerChild($serializerId, 'serializer');
            $container->registerAliasForArgument($serializerId, SerializerInterface::class, $serializerName . '.serializer');
            $this->configureSerializer($container, $serializerId, $normalizers, $encoders, $serializerName);
            if ($container->getParameter('kernel.debug') && $container->hasDefinition('debug.serializer')) {
                $container->registerChild($debugId = 'debug.' . $serializerId, 'debug.serializer')
                    ->setDecoratedService($serializerId)
                    ->replaceArgument(0, new Reference($debugId . '.inner'))
                    ->replaceArgument(2, $serializerName);
            }
        }
    }
    private function buildChildNameConverterDefinition(ContainerBuilder $container, ?string $nameConverter) : ?string {
        $childId = self::NAME_CONVERTER_METADATA_AWARE_ID . '.' . ContainerBuilder::hash($nameConverter);
        if (!$container->hasDefinition($childId)) {
            $childDefinition = $container->registerChild($childId, self::NAME_CONVERTER_METADATA_AWARE_ID . '.abstract');
            if (null !== $nameConverter) {
                $childDefinition->addArgument(new Reference($nameConverter));
            }
        }
        return $childId;
    }
    private function buildChildDefinitions(ContainerBuilder $container, string $serializerName, array $services, array $config) : array {
        foreach ($services as &$id) {
            $childId = $id . '.' . $serializerName;
            $definition = $container->registerChild($childId, (string) $id);
            if (null !== ($nameConverterIndex = $this->findNameConverterIndex($container, (string) $id))) {
                $definition->replaceArgument($nameConverterIndex, new Reference($config['name_converter']));
            }
            $id = new Reference($childId);
        }
        return $services;
    }
    private function findNameConverterIndex(ContainerBuilder $container, string $id) : int|string|null {
        foreach ($container->getDefinition($id)
            ->getArguments() as $index => $argument) {
            if ($argument instanceof Reference && self::NAME_CONVERTER_METADATA_AWARE_ID === (string) $argument) {
                return $index;
            }
        }
        return null;
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
PriorityTaggedServiceTrait::findAndSortTaggedServices private function Finds all services with the given tag name and order them by their priority.
SerializerPass::bindDefaultContext private function
SerializerPass::buildChildDefinitions private function
SerializerPass::buildChildNameConverterDefinition private function
SerializerPass::configureNamedSerializers private function
SerializerPass::configureSerializer private function
SerializerPass::createNamedSerializerTags private function
SerializerPass::findNameConverterIndex private function
SerializerPass::NAME_CONVERTER_METADATA_AWARE_ID private constant
SerializerPass::process public function You can modify the container here before it is dumped to PHP code. Overrides CompilerPassInterface::process
RSS feed
Powered by Drupal