Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
55.56% covered (warning)
55.56%
5 / 9
CRAP
88.37% covered (warning)
88.37%
38 / 43
MetadataAwareNameConverter
0.00% covered (danger)
0.00%
0 / 1
55.56% covered (warning)
55.56%
5 / 9
31.41
88.37% covered (warning)
88.37%
38 / 43
 __construct
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
3 / 3
 normalize
0.00% covered (danger)
0.00%
0 / 1
4.13
80.00% covered (warning)
80.00%
4 / 5
 denormalize
0.00% covered (danger)
0.00%
0 / 1
4.07
83.33% covered (warning)
83.33%
5 / 6
 getCacheValueForNormalization
0.00% covered (danger)
0.00%
0 / 1
4.07
83.33% covered (warning)
83.33%
5 / 6
 normalizeFallback
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
1 / 1
 getCacheValueForDenormalization
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
4 / 4
 denormalizeFallback
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
1 / 1
 getCacheValueForAttributesMetadata
0.00% covered (danger)
0.00%
0 / 1
8.19
85.71% covered (warning)
85.71%
12 / 14
 getCacheKey
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
3 / 3
<?php
/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Component\Serializer\NameConverter;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
/**
 * @author Fabien Bourigault <bourigaultfabien@gmail.com>
 */
final class MetadataAwareNameConverter implements AdvancedNameConverterInterface
{
    private $metadataFactory;
    /**
     * @var NameConverterInterface|AdvancedNameConverterInterface|null
     */
    private $fallbackNameConverter;
    private static $normalizeCache = [];
    private static $denormalizeCache = [];
    private static $attributesMetadataCache = [];
    public function __construct(ClassMetadataFactoryInterface $metadataFactory, NameConverterInterface $fallbackNameConverter = null)
    {
        $this->metadataFactory = $metadataFactory;
        $this->fallbackNameConverter = $fallbackNameConverter;
    }
    /**
     * {@inheritdoc}
     */
    public function normalize(string $propertyName, string $class = null, string $format = null, array $context = []): string
    {
        if (null === $class) {
            return $this->normalizeFallback($propertyName, $class, $format, $context);
        }
        if (!\array_key_exists($class, self::$normalizeCache) || !\array_key_exists($propertyName, self::$normalizeCache[$class])) {
            self::$normalizeCache[$class][$propertyName] = $this->getCacheValueForNormalization($propertyName, $class);
        }
        return self::$normalizeCache[$class][$propertyName] ?? $this->normalizeFallback($propertyName, $class, $format, $context);
    }
    /**
     * {@inheritdoc}
     */
    public function denormalize(string $propertyName, string $class = null, string $format = null, array $context = []): string
    {
        if (null === $class) {
            return $this->denormalizeFallback($propertyName, $class, $format, $context);
        }
        $cacheKey = $this->getCacheKey($class, $context);
        if (!\array_key_exists($cacheKey, self::$denormalizeCache) || !\array_key_exists($propertyName, self::$denormalizeCache[$cacheKey])) {
            self::$denormalizeCache[$cacheKey][$propertyName] = $this->getCacheValueForDenormalization($propertyName, $class, $context);
        }
        return self::$denormalizeCache[$cacheKey][$propertyName] ?? $this->denormalizeFallback($propertyName, $class, $format, $context);
    }
    private function getCacheValueForNormalization(string $propertyName, string $class): ?string
    {
        if (!$this->metadataFactory->hasMetadataFor($class)) {
            return null;
        }
        $attributesMetadata = $this->metadataFactory->getMetadataFor($class)->getAttributesMetadata();
        if (!\array_key_exists($propertyName, $attributesMetadata)) {
            return null;
        }
        return $attributesMetadata[$propertyName]->getSerializedName() ?? null;
    }
    private function normalizeFallback(string $propertyName, string $class = null, string $format = null, array $context = []): string
    {
        return $this->fallbackNameConverter ? $this->fallbackNameConverter->normalize($propertyName, $class, $format, $context) : $propertyName;
    }
    private function getCacheValueForDenormalization(string $propertyName, string $class, array $context): ?string
    {
        $cacheKey = $this->getCacheKey($class, $context);
        if (!\array_key_exists($cacheKey, self::$attributesMetadataCache)) {
            self::$attributesMetadataCache[$cacheKey] = $this->getCacheValueForAttributesMetadata($class, $context);
        }
        return self::$attributesMetadataCache[$cacheKey][$propertyName] ?? null;
    }
    private function denormalizeFallback(string $propertyName, string $class = null, string $format = null, array $context = []): string
    {
        return $this->fallbackNameConverter ? $this->fallbackNameConverter->denormalize($propertyName, $class, $format, $context) : $propertyName;
    }
    private function getCacheValueForAttributesMetadata(string $class, array $context): array
    {
        if (!$this->metadataFactory->hasMetadataFor($class)) {
            return [];
        }
        $classMetadata = $this->metadataFactory->getMetadataFor($class);
        $cache = [];
        foreach ($classMetadata->getAttributesMetadata() as $name => $metadata) {
            if (null === $metadata->getSerializedName()) {
                continue;
            }
            $groups = $metadata->getGroups();
            if (!$groups && ($context[AbstractNormalizer::GROUPS] ?? [])) {
                continue;
            }
            if ($groups && !array_intersect($groups, (array) ($context[AbstractNormalizer::GROUPS] ?? []))) {
                continue;
            }
            $cache[$metadata->getSerializedName()] = $name;
        }
        return $cache;
    }
    private function getCacheKey(string $class, array $context): string
    {
        if (isset($context['cache_key'])) {
            return $class.'-'.$context['cache_key'];
        }
        return $class.md5(serialize($context[AbstractNormalizer::GROUPS] ?? []));
    }
}