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

api-platform / core / 10027319583

21 Jul 2024 09:36AM UTC coverage: 7.847%. Remained the same
10027319583

push

github

web-flow
ci: fix naming of Windows Behat matrix line (#6489)

12688 of 161690 relevant lines covered (7.85%)

26.88 hits per line

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

100.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
    // @noRector \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector
43
    public const FORMAT = 'to-override';
44

45
    public function __construct(protected ResourceClassResolverInterface $resourceClassResolver, protected string $pageParameterName, protected ?ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null)
46
    {
47
    }
2,621✔
48

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

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

71
        return [];
2,315✔
72
    }
73

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

85
        $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class']);
783✔
86
        $collectionContext = $this->initContext($resourceClass, $context);
783✔
87
        $data = [];
783✔
88
        $paginationData = $this->getPaginationData($object, $collectionContext);
783✔
89

90
        $childContext = $this->createOperationContext($collectionContext, $resourceClass);
783✔
91
        if (isset($collectionContext['force_resource_class'])) {
783✔
92
            $childContext['force_resource_class'] = $collectionContext['force_resource_class'];
6✔
93
        }
94

95
        $itemsData = $this->getItemsData($object, $format, $childContext);
783✔
96

97
        return array_merge_recursive($data, $paginationData, $itemsData);
783✔
98
    }
99

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

109
        $data = [];
837✔
110
        foreach ($object as $index => $obj) {
837✔
111
            $data[$index] = $this->normalizer->normalize($obj, $format, $context);
498✔
112
        }
113

114
        return $data;
837✔
115
    }
116

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

125
        if ($object instanceof PartialPaginatorInterface) {
172✔
126
            $paginated = $paginator = true;
139✔
127
            if ($object instanceof PaginatorInterface) {
139✔
128
                $paginated = 1. !== $lastPage = $object->getLastPage();
135✔
129
                $totalItems = $object->getTotalItems();
135✔
130
            } else {
131
                $pageTotalItems = (float) \count($object);
4✔
132
            }
133

134
            $currentPage = $object->getCurrentPage();
139✔
135
            $itemsPerPage = $object->getItemsPerPage();
139✔
136
        } elseif (is_countable($object)) {
33✔
137
            $totalItems = \count($object);
27✔
138
        }
139

140
        return [$paginator, $paginated, $currentPage, $itemsPerPage, $lastPage, $pageTotalItems, $totalItems];
172✔
141
    }
142

143
    protected function getOperation(array $context = []): Operation
144
    {
145
        $metadata = $this->resourceMetadataFactory->create($context['resource_class'] ?? '');
6✔
146

147
        return $metadata->getOperation($context['operation_name'] ?? null);
6✔
148
    }
149

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

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