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

api-platform / core / 10014117656

19 Jul 2024 08:44PM UTC coverage: 7.856% (-56.3%) from 64.185%
10014117656

push

github

soyuka
Merge branch 'sf/remove-flag'

0 of 527 new or added lines in 83 files covered. (0.0%)

10505 existing lines in 362 files now uncovered.

12705 of 161727 relevant lines covered (7.86%)

26.85 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
    {
UNCOV
47
    }
2,618✔
48

49
    /**
50
     * {@inheritdoc}
51
     */
52
    public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
53
    {
UNCOV
54
        return static::FORMAT === $format && is_iterable($data);
1,287✔
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
         */
UNCOV
64
        if (static::FORMAT === $format) {
2,324✔
UNCOV
65
            return [
1,805✔
UNCOV
66
                'native-array' => true,
1,805✔
UNCOV
67
                '\Traversable' => true,
1,805✔
UNCOV
68
            ];
1,805✔
69
        }
70

UNCOV
71
        return [];
2,312✔
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
    {
UNCOV
81
        if (!isset($context['resource_class']) || isset($context['api_sub_level'])) {
1,290✔
UNCOV
82
            return $this->normalizeRawCollection($object, $format, $context);
834✔
83
        }
84

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

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

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

UNCOV
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
    {
UNCOV
105
        if (!$object && ($context[Serializer::EMPTY_ARRAY_AS_OBJECT] ?? false) && \is_array($object)) {
834✔
106
            return new \ArrayObject();
3✔
107
        }
108

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

UNCOV
114
        return $data;
834✔
115
    }
116

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

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

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

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

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

UNCOV
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