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

api-platform / core / 21006071786

14 Jan 2026 06:53PM UTC coverage: 21.366% (-7.7%) from 29.097%
21006071786

Pull #7675

github

web-flow
Merge 5c98a7330 into 73402fc61
Pull Request #7675: feat(doctrine): Add caseInsensitive option to PartialSearchFilter

0 of 11 new or added lines in 2 files covered. (0.0%)

15054 existing lines in 491 files now uncovered.

12306 of 57596 relevant lines covered (21.37%)

49.15 hits per line

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

95.0
/src/Serializer/AbstractCollectionNormalizer.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\Serializer;
15

16
use ApiPlatform\Metadata\Operation;
17
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
18
use ApiPlatform\Metadata\ResourceClassResolverInterface;
19
use ApiPlatform\State\Pagination\PaginatorInterface;
20
use ApiPlatform\State\Pagination\PartialPaginatorInterface;
21
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
22
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
23
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
24
use Symfony\Component\Serializer\Serializer;
25

26
/**
27
 * Base collection normalizer.
28
 *
29
 * @author Baptiste Meyer <baptiste.meyer@gmail.com>
30
 */
31
abstract class AbstractCollectionNormalizer implements NormalizerInterface, NormalizerAwareInterface
32
{
33
    use ContextTrait {
34
        initContext as protected;
35
    }
36
    use NormalizerAwareTrait;
37
    use OperationContextTrait;
38

39
    /**
40
     * This constant must be overridden in the child class.
41
     */
42
    public const FORMAT = 'to-override';
43

44
    public function __construct(protected ResourceClassResolverInterface $resourceClassResolver, protected string $pageParameterName, protected ?ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null)
45
    {
UNCOV
46
    }
1,529✔
47

48
    /**
49
     * {@inheritdoc}
50
     */
51
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
52
    {
UNCOV
53
        return static::FORMAT === $format && is_iterable($data);
782✔
54
    }
55

56
    /**
57
     * {@inheritdoc}
58
     */
59
    public function getSupportedTypes(?string $format): array
60
    {
61
        /*
62
         * At this point, support anything that is_iterable(), i.e. array|Traversable
63
         * for non-objects, symfony uses 'native-'.\gettype($data) :
64
         * https://github.com/tucksaun/symfony/blob/400685a68b00b0932f8ef41096578872b643099c/src/Symfony/Component/Serializer/Serializer.php#L254
65
         */
UNCOV
66
        if (static::FORMAT === $format) {
1,398✔
UNCOV
67
            return [
1,089✔
UNCOV
68
                'native-array' => true,
1,089✔
UNCOV
69
                '\Traversable' => true,
1,089✔
UNCOV
70
            ];
1,089✔
71
        }
72

UNCOV
73
        return [];
1,392✔
74
    }
75

76
    /**
77
     * {@inheritdoc}
78
     *
79
     * @param iterable $data
80
     */
81
    public function normalize(mixed $data, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
82
    {
UNCOV
83
        if (!isset($context['resource_class']) || isset($context['api_sub_level'])) {
782✔
UNCOV
84
            return $this->normalizeRawCollection($data, $format, $context);
534✔
85
        }
86

UNCOV
87
        $resourceClass = $this->resourceClassResolver->getResourceClass($data, $context['resource_class']);
463✔
UNCOV
88
        $collectionContext = $this->initContext($resourceClass, $context);
463✔
UNCOV
89
        $normalizedData = [];
463✔
UNCOV
90
        $paginationData = $this->getPaginationData($data, $collectionContext);
463✔
91

UNCOV
92
        $childContext = $this->createOperationContext($collectionContext, $resourceClass);
463✔
UNCOV
93
        if (isset($collectionContext['force_resource_class'])) {
463✔
UNCOV
94
            $childContext['force_resource_class'] = $collectionContext['force_resource_class'];
7✔
95
        }
96

UNCOV
97
        $itemsData = $this->getItemsData($data, $format, $childContext);
463✔
98

UNCOV
99
        return array_merge_recursive($normalizedData, $paginationData, $itemsData);
463✔
100
    }
101

102
    /**
103
     * Normalizes a raw collection (not API resources).
104
     */
105
    protected function normalizeRawCollection(iterable $object, ?string $format = null, array $context = []): array|\ArrayObject
106
    {
UNCOV
107
        if ([] === $object && ($context[Serializer::EMPTY_ARRAY_AS_OBJECT] ?? false)) {
534✔
108
            return new \ArrayObject();
2✔
109
        }
110

UNCOV
111
        $data = [];
534✔
UNCOV
112
        foreach ($object as $index => $obj) {
534✔
UNCOV
113
            $data[$index] = $this->normalizer->normalize($obj, $format, $context);
308✔
114
        }
115

UNCOV
116
        return $data;
534✔
117
    }
118

119
    /**
120
     * Gets the pagination configuration.
121
     */
122
    protected function getPaginationConfig(iterable $object, array $context = []): array
123
    {
UNCOV
124
        $currentPage = $lastPage = $itemsPerPage = $pageTotalItems = $totalItems = null;
92✔
UNCOV
125
        $paginated = $paginator = false;
92✔
126

UNCOV
127
        if ($object instanceof PartialPaginatorInterface) {
92✔
UNCOV
128
            $paginated = $paginator = true;
82✔
UNCOV
129
            if ($object instanceof PaginatorInterface) {
82✔
UNCOV
130
                $paginated = 1. !== $lastPage = $object->getLastPage();
81✔
UNCOV
131
                $totalItems = $object->getTotalItems();
81✔
132
            } else {
133
                $pageTotalItems = (float) \count($object);
1✔
134
            }
135

UNCOV
136
            $currentPage = $object->getCurrentPage();
82✔
UNCOV
137
            $itemsPerPage = $object->getItemsPerPage();
82✔
UNCOV
138
        } elseif (is_countable($object)) {
10✔
UNCOV
139
            $totalItems = \count($object);
10✔
140
        }
141

UNCOV
142
        return [$paginator, $paginated, $currentPage, $itemsPerPage, $lastPage, $pageTotalItems, $totalItems];
92✔
143
    }
144

145
    protected function getOperation(array $context = []): Operation
146
    {
147
        $metadata = $this->resourceMetadataFactory->create($context['resource_class'] ?? '');
×
148

149
        return $metadata->getOperation($context['operation_name'] ?? null);
×
150
    }
151

152
    /**
153
     * Gets the pagination data.
154
     */
155
    abstract protected function getPaginationData(iterable $object, array $context = []): array;
156

157
    /**
158
     * Gets items data.
159
     */
160
    abstract protected function getItemsData(iterable $object, ?string $format = null, array $context = []): array;
161
}
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

© 2026 Coveralls, Inc