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

api-platform / core / 14980015570

12 May 2025 06:41PM UTC coverage: 26.309% (+2.6%) from 23.685%
14980015570

Pull #7140

github

web-flow
Merge 1e6b14143 into 202c60fcb
Pull Request #7140: Fix: PHPize HTTP cache headers

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

4614 existing lines in 185 files now uncovered.

13550 of 51504 relevant lines covered (26.31%)

71.73 hits per line

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

24.42
/src/OpenApi/Factory/TypeFactoryTrait.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\OpenApi\Factory;
15

16
use Ramsey\Uuid\UuidInterface;
17
use Symfony\Component\PropertyInfo\Type as LegacyType;
18
use Symfony\Component\TypeInfo\Type as NativeType;
19
use Symfony\Component\TypeInfo\Type\CollectionType;
20
use Symfony\Component\TypeInfo\Type\ObjectType;
21
use Symfony\Component\TypeInfo\TypeIdentifier;
22
use Symfony\Component\Uid\Ulid;
23
use Symfony\Component\Uid\Uuid;
24

25
/**
26
 * @internal
27
 */
28
trait TypeFactoryTrait
29
{
30
    /**
31
     * @return array<string, mixed>
32
     */
33
    private function getType(LegacyType|NativeType $type): array
34
    {
35
        if ($type instanceof NativeType) {
33✔
36
            return $this->getNativeType($type);
33✔
37
        }
38

UNCOV
39
        if ($type->isCollection()) {
×
UNCOV
40
            $keyType = $type->getCollectionKeyTypes()[0] ?? null;
×
UNCOV
41
            $subType = ($type->getCollectionValueTypes()[0] ?? null) ?? new LegacyType($type->getBuiltinType(), false, $type->getClassName(), false);
×
42

UNCOV
43
            if (null !== $keyType && LegacyType::BUILTIN_TYPE_STRING === $keyType->getBuiltinType()) {
×
UNCOV
44
                return $this->addNullabilityToTypeDefinition([
×
UNCOV
45
                    'type' => 'object',
×
UNCOV
46
                    'additionalProperties' => $this->getType($subType),
×
UNCOV
47
                ], $type);
×
48
            }
49

UNCOV
50
            return $this->addNullabilityToTypeDefinition([
×
UNCOV
51
                'type' => 'array',
×
UNCOV
52
                'items' => $this->getType($subType),
×
UNCOV
53
            ], $type);
×
54
        }
55

UNCOV
56
        return $this->addNullabilityToTypeDefinition($this->makeLegacyBasicType($type), $type);
×
57
    }
58

59
    /**
60
     * @return array<string, mixed>
61
     */
62
    private function getNativeType(NativeType $type): array
63
    {
64
        if ($type instanceof CollectionType) {
33✔
65
            $keyType = $type->getCollectionKeyType();
33✔
66
            $subType = $type->getCollectionValueType();
33✔
67

68
            if ($keyType->isIdentifiedBy(TypeIdentifier::STRING)) {
33✔
69
                return $this->addNullabilityToTypeDefinition([
×
70
                    'type' => 'object',
×
71
                    'additionalProperties' => $this->getNativeType($subType),
×
72
                ], $type);
×
73
            }
74

75
            return $this->addNullabilityToTypeDefinition([
33✔
76
                'type' => 'array',
33✔
77
                'items' => $this->getNativeType($subType),
33✔
78
            ], $type);
33✔
79
        }
80

81
        return $this->addNullabilityToTypeDefinition($this->makeBasicType($type), $type);
33✔
82
    }
83

84
    /**
85
     * @return array<string, mixed>
86
     */
87
    private function makeLegacyBasicType(LegacyType $type): array
88
    {
89
        return match ($type->getBuiltinType()) {
×
90
            LegacyType::BUILTIN_TYPE_INT => ['type' => 'integer'],
×
UNCOV
91
            LegacyType::BUILTIN_TYPE_FLOAT => ['type' => 'number'],
×
92
            LegacyType::BUILTIN_TYPE_BOOL => ['type' => 'boolean'],
×
93
            LegacyType::BUILTIN_TYPE_OBJECT => $this->getClassType($type->getClassName(), $type->isNullable()),
×
94
            default => ['type' => 'string'],
×
95
        };
×
96
    }
97

98
    /**
99
     * @return array<string, mixed>
100
     */
101
    private function makeBasicType(NativeType $type): array
102
    {
103
        if ($type->isIdentifiedBy(TypeIdentifier::INT)) {
33✔
104
            return ['type' => 'integer'];
31✔
105
        }
106
        if ($type->isIdentifiedBy(TypeIdentifier::FLOAT)) {
33✔
107
            return ['type' => 'number'];
31✔
108
        }
109
        if ($type->isIdentifiedBy(TypeIdentifier::BOOL)) {
33✔
110
            return ['type' => 'boolean'];
31✔
111
        }
112
        if ($type instanceof ObjectType) {
33✔
113
            return $this->getClassType($type->getClassName(), $type->isNullable());
×
114
        }
115

116
        // Default for other built-in types like string, resource, mixed, etc.
117
        return ['type' => 'string'];
33✔
118
    }
119

120
    /**
121
     * Gets the JSON Schema document which specifies the data type corresponding to the given PHP class, and recursively adds needed new schema to the current schema if provided.
122
     *
123
     * @return array<string, mixed>
124
     */
125
    private function getClassType(?string $className, bool $nullable): array
126
    {
127
        if (null === $className) {
×
128
            return ['type' => 'string'];
×
129
        }
130

UNCOV
131
        if (is_a($className, \DateTimeInterface::class, true)) {
×
UNCOV
132
            return [
×
UNCOV
133
                'type' => 'string',
×
UNCOV
134
                'format' => 'date-time',
×
UNCOV
135
            ];
×
136
        }
UNCOV
137
        if (is_a($className, \DateInterval::class, true)) {
×
UNCOV
138
            return [
×
UNCOV
139
                'type' => 'string',
×
UNCOV
140
                'format' => 'duration',
×
UNCOV
141
            ];
×
142
        }
UNCOV
143
        if (is_a($className, UuidInterface::class, true) || is_a($className, Uuid::class, true)) {
×
UNCOV
144
            return [
×
UNCOV
145
                'type' => 'string',
×
UNCOV
146
                'format' => 'uuid',
×
UNCOV
147
            ];
×
148
        }
UNCOV
149
        if (is_a($className, Ulid::class, true)) {
×
UNCOV
150
            return [
×
UNCOV
151
                'type' => 'string',
×
UNCOV
152
                'format' => 'ulid',
×
UNCOV
153
            ];
×
154
        }
UNCOV
155
        if (is_a($className, \SplFileInfo::class, true)) {
×
UNCOV
156
            return [
×
UNCOV
157
                'type' => 'string',
×
UNCOV
158
                'format' => 'binary',
×
UNCOV
159
            ];
×
160
        }
161

UNCOV
162
        if (is_a($className, \BackedEnum::class, true)) {
×
UNCOV
163
            $enumCases = array_map(static fn (\BackedEnum $enum): string|int => $enum->value, $className::cases());
×
164

UNCOV
165
            $type = \is_string($enumCases[0] ?? '') ? 'string' : 'integer';
×
166

UNCOV
167
            if ($nullable) {
×
UNCOV
168
                $enumCases[] = null;
×
169
            }
170

UNCOV
171
            return [
×
UNCOV
172
                'type' => $type,
×
UNCOV
173
                'enum' => $enumCases,
×
UNCOV
174
            ];
×
175
        }
176

UNCOV
177
        return ['type' => 'string'];
×
178
    }
179

180
    /**
181
     * @param array<string, mixed> $jsonSchema
182
     *
183
     * @return array<string, mixed>
184
     */
185
    private function addNullabilityToTypeDefinition(array $jsonSchema, LegacyType|NativeType $type): array
186
    {
187
        if (!$type->isNullable()) {
33✔
188
            return $jsonSchema;
33✔
189
        }
190

UNCOV
191
        $typeDefinition = ['anyOf' => [$jsonSchema]];
×
UNCOV
192
        $typeDefinition['anyOf'][] = ['type' => 'null'];
×
193

UNCOV
194
        return $typeDefinition;
×
195
    }
196
}
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