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

api-platform / core / 15023181448

14 May 2025 02:19PM UTC coverage: 0.0% (-8.4%) from 8.418%
15023181448

Pull #7139

github

web-flow
Merge 9f45709da into 1862d03b7
Pull Request #7139: refactor(symfony): remove obsolete option `validator.query-parameter-validation`

0 of 4 new or added lines in 1 file covered. (0.0%)

11266 existing lines in 366 files now uncovered.

0 of 50828 relevant lines covered (0.0%)

0.0 hits per line

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

0.0
/src/Metadata/Resource/Factory/LinkFactory.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\Metadata\Resource\Factory;
15

16
use ApiPlatform\Metadata\Exception\RuntimeException;
17
use ApiPlatform\Metadata\Link;
18
use ApiPlatform\Metadata\Metadata;
19
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
20
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
21
use ApiPlatform\Metadata\ResourceClassResolverInterface;
22
use ApiPlatform\Metadata\Util\TypeHelper;
23
use Symfony\Component\TypeInfo\Type;
24

25
/**
26
 * @internal
27
 */
28
final class LinkFactory implements LinkFactoryInterface, PropertyLinkFactoryInterface
29
{
30
    /**
31
     * @var array<class-string, string[]>
32
     */
33
    private $localIdentifiersPerResourceClassCache = [];
34

35
    public function __construct(private readonly PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, private readonly PropertyMetadataFactoryInterface $propertyMetadataFactory, private readonly ResourceClassResolverInterface $resourceClassResolver)
36
    {
UNCOV
37
    }
×
38

39
    /**
40
     * {@inheritdoc}
41
     */
42
    public function createLinkFromProperty(Metadata $operation, string $property): Link
43
    {
44
        $metadata = $this->propertyMetadataFactory->create($resourceClass = $operation->getClass(), $property);
×
45
        $relationClass = $this->getPropertyClassType($metadata->getNativeType());
×
46
        if (!$relationClass) {
×
47
            throw new RuntimeException(\sprintf('We could not find a class matching the uriVariable "%s" on "%s".', $property, $resourceClass));
×
48
        }
49

50
        $identifiers = $this->resourceClassResolver->isResourceClass($relationClass) ? $this->getIdentifiersFromResourceClass($relationClass) : ['id'];
×
51

52
        return new Link(fromClass: $relationClass, toProperty: $property, identifiers: $identifiers, parameterName: $property);
×
53
    }
54

55
    /**
56
     * {@inheritdoc}
57
     */
58
    public function createLinksFromIdentifiers(Metadata $operation): array
59
    {
UNCOV
60
        $identifiers = $this->getIdentifiersFromResourceClass($resourceClass = $operation->getClass());
×
61

UNCOV
62
        if (!$identifiers) {
×
UNCOV
63
            return [];
×
64
        }
65

UNCOV
66
        $link = (new Link())->withFromClass($resourceClass)->withIdentifiers($identifiers);
×
UNCOV
67
        $parameterName = $identifiers[0];
×
UNCOV
68
        if ('value' === $parameterName && enum_exists($resourceClass)) {
×
UNCOV
69
            $parameterName = 'id';
×
70
        }
71

UNCOV
72
        if (1 < \count($identifiers)) {
×
73
            $parameterName = 'id';
×
74
            $link = $link->withCompositeIdentifier(true);
×
75
        }
76

UNCOV
77
        return [$link->withParameterName($parameterName)];
×
78
    }
79

80
    /**
81
     * {@inheritdoc}
82
     */
83
    public function createLinksFromRelations(Metadata $operation): array
84
    {
UNCOV
85
        $links = [];
×
UNCOV
86
        foreach ($this->propertyNameCollectionFactory->create($resourceClass = $operation->getClass()) as $property) {
×
UNCOV
87
            $metadata = $this->propertyMetadataFactory->create($resourceClass, $property);
×
88

UNCOV
89
            if (!($relationClass = $this->getPropertyClassType($metadata->getNativeType())) || !$this->resourceClassResolver->isResourceClass($relationClass)) {
×
UNCOV
90
                continue;
×
91
            }
92

UNCOV
93
            $identifiers = $this->getIdentifiersFromResourceClass($resourceClass);
×
94

UNCOV
95
            $links[] = (new Link())->withFromProperty($property)->withFromClass($resourceClass)->withToClass($relationClass)->withIdentifiers($identifiers);
×
96
        }
97

UNCOV
98
        return $links;
×
99
    }
100

101
    /**
102
     * {@inheritdoc}
103
     */
104
    public function createLinksFromAttributes(Metadata $operation): array
105
    {
UNCOV
106
        $links = [];
×
107
        try {
UNCOV
108
            $reflectionClass = new \ReflectionClass($resourceClass = $operation->getClass());
×
UNCOV
109
            foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $property) {
×
UNCOV
110
                $reflectionProperty = $reflectionClass->getProperty($property);
×
111

UNCOV
112
                foreach ($reflectionProperty->getAttributes(Link::class) as $attributeLink) {
×
113
                    $metadata = $this->propertyMetadataFactory->create($resourceClass, $property);
×
114

115
                    $attributeLink = $attributeLink->newInstance()
×
116
                        ->withFromProperty($property);
×
117

118
                    if (!$attributeLink->getFromClass()) {
×
119
                        $attributeLink = $attributeLink->withFromClass($resourceClass)->withToClass($this->getPropertyClassType($metadata->getNativeType()) ?? $resourceClass);
×
120
                    }
121

122
                    $links[] = $attributeLink;
×
123
                }
124
            }
UNCOV
125
        } catch (\ReflectionException) {
×
126
        }
127

UNCOV
128
        return $links;
×
129
    }
130

131
    /**
132
     * {@inheritdoc}
133
     */
134
    public function completeLink(Link $link): Link
135
    {
UNCOV
136
        if (!$link->getIdentifiers()) {
×
UNCOV
137
            $link = $link->withIdentifiers($this->getIdentifiersFromResourceClass($link->getFromClass()));
×
138
        }
139

UNCOV
140
        if (1 < \count((array) $link->getIdentifiers())) {
×
141
            $link = $link->withCompositeIdentifier(true);
×
142
        }
143

UNCOV
144
        return $link;
×
145
    }
146

147
    /**
148
     * @param class-string $resourceClass
149
     *
150
     * @return string[]
151
     */
152
    private function getIdentifiersFromResourceClass(string $resourceClass): array
153
    {
UNCOV
154
        if (isset($this->localIdentifiersPerResourceClassCache[$resourceClass])) {
×
UNCOV
155
            return $this->localIdentifiersPerResourceClassCache[$resourceClass];
×
156
        }
157

UNCOV
158
        $hasIdProperty = false;
×
UNCOV
159
        $identifiers = [];
×
UNCOV
160
        foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $property) {
×
UNCOV
161
            $isIdentifier = $this->propertyMetadataFactory->create($resourceClass, $property)->isIdentifier();
×
162

UNCOV
163
            if (!$hasIdProperty && null === $isIdentifier) {
×
UNCOV
164
                $hasIdProperty = 'id' === $property;
×
165
            }
166

UNCOV
167
            if ($isIdentifier) {
×
UNCOV
168
                $identifiers[] = $property;
×
169
            }
170
        }
171

UNCOV
172
        if ($hasIdProperty && !$identifiers) {
×
173
            return $this->localIdentifiersPerResourceClassCache[$resourceClass] = ['id'];
×
174
        }
175

UNCOV
176
        if (!$hasIdProperty && !$identifiers && enum_exists($resourceClass)) {
×
UNCOV
177
            return $this->localIdentifiersPerResourceClassCache[$resourceClass] = ['value'];
×
178
        }
179

UNCOV
180
        return $this->localIdentifiersPerResourceClassCache[$resourceClass] = $identifiers;
×
181
    }
182

183
    private function getPropertyClassType(?Type $type): ?string
184
    {
UNCOV
185
        if (!$type) {
×
UNCOV
186
            return null;
×
187
        }
188

UNCOV
189
        if ($collectionValueType = TypeHelper::getCollectionValueType($type)) {
×
UNCOV
190
            return $this->getPropertyClassType($collectionValueType);
×
191
        }
192

UNCOV
193
        return TypeHelper::getClassName($type);
×
194
    }
195
}
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