• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

api-platform / core / 7047458607

30 Nov 2023 01:53PM UTC coverage: 37.263% (+0.002%) from 37.261%
7047458607

push

github

soyuka
Merge 3.2

20 of 35 new or added lines in 12 files covered. (57.14%)

10 existing lines in 3 files now uncovered.

10295 of 27628 relevant lines covered (37.26%)

21.04 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Elasticsearch/Serializer/DocumentNormalizer.php
1
<?php
2

3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <dunglas@gmail.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11

12
declare(strict_types=1);
13

14
namespace ApiPlatform\Elasticsearch\Serializer;
15

16
use ApiPlatform\Metadata\HttpOperation;
17
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
18
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
19
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
20
use Symfony\Component\Serializer\Exception\LogicException;
21
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface;
22
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
23
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
24
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
25
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
26
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
27
use Symfony\Component\Serializer\SerializerAwareInterface;
28
use Symfony\Component\Serializer\SerializerInterface;
29

30
/**
31
 * Document denormalizer for Elasticsearch.
32
 *
33
 * @experimental
34
 *
35
 * @author Baptiste Meyer <baptiste.meyer@gmail.com>
36
 */
37
final class DocumentNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface
38
{
39
    public const FORMAT = 'elasticsearch';
40

41
    private readonly ObjectNormalizer $decoratedNormalizer;
42

43
    public function __construct(
44
        private readonly ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory,
45
        ClassMetadataFactoryInterface $classMetadataFactory = null,
46
        private readonly ?NameConverterInterface $nameConverter = null,
47
        PropertyAccessorInterface $propertyAccessor = null,
48
        PropertyTypeExtractorInterface $propertyTypeExtractor = null,
49
        ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null,
50
        callable $objectClassResolver = null,
51
        array $defaultContext = [],
52
    ) {
53
        $this->decoratedNormalizer = new ObjectNormalizer($classMetadataFactory, $nameConverter, $propertyAccessor, $propertyTypeExtractor, $classDiscriminatorResolver, $objectClassResolver, $defaultContext);
×
54
    }
55

56
    /**
57
     * {@inheritdoc}
58
     */
59
    public function supportsDenormalization(mixed $data, string $type, string $format = null, array $context = []): bool
60
    {
NEW
61
        return self::FORMAT === $format && $this->decoratedNormalizer->supportsDenormalization($data, $type, $format, $context);
×
62
    }
63

64
    /**
65
     * {@inheritdoc}
66
     */
67
    public function denormalize(mixed $data, string $class, string $format = null, array $context = []): mixed
68
    {
69
        if (\is_string($data['_id'] ?? null) && \is_array($data['_source'] ?? null)) {
×
70
            $data = $this->populateIdentifier($data, $class)['_source'];
×
71
        }
72

73
        return $this->decoratedNormalizer->denormalize($data, $class, $format, $context);
×
74
    }
75

76
    /**
77
     * {@inheritdoc}
78
     */
79
    public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool
80
    {
81
        // prevent the use of lower priority normalizers (e.g. serializer.normalizer.object) for this format
82
        return self::FORMAT === $format;
×
83
    }
84

85
    /**
86
     * {@inheritdoc}
87
     *
88
     * @throws LogicException
89
     */
90
    public function normalize(mixed $object, string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
91
    {
92
        throw new LogicException(sprintf('%s is a write-only format.', self::FORMAT));
×
93
    }
94

95
    /**
96
     * Populates the resource identifier with the document identifier if not present in the original JSON document.
97
     */
98
    private function populateIdentifier(array $data, string $class): array
99
    {
100
        $identifier = 'id';
×
101
        $resourceMetadata = $this->resourceMetadataCollectionFactory->create($class);
×
102

103
        $operation = $resourceMetadata->getOperation();
×
104
        if ($operation instanceof HttpOperation) {
×
105
            $uriVariable = $operation->getUriVariables()[0] ?? null;
×
106

107
            if ($uriVariable) {
×
108
                $identifier = $uriVariable->getIdentifiers()[0] ?? 'id';
×
109
            }
110
        }
111

112
        $identifier = null === $this->nameConverter ? $identifier : $this->nameConverter->normalize($identifier, $class, self::FORMAT);
×
113

114
        if (!isset($data['_source'][$identifier])) {
×
115
            $data['_source'][$identifier] = $data['_id'];
×
116
        }
117

118
        return $data;
×
119
    }
120

121
    /**
122
     * {@inheritdoc}
123
     */
124
    public function setSerializer(SerializerInterface $serializer): void
125
    {
126
        $this->decoratedNormalizer->setSerializer($serializer);
×
127
    }
128

129
    /**
130
     * {@inheritdoc}
131
     */
132
    public function getSupportedTypes(?string $format): array
133
    {
134
        return self::FORMAT === $format ? ['object' => true] : [];
×
135
    }
136
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc