Skip to content

Commit 6a26d02

Browse files
committed
feature #53160 [PropertyInfo] Deprecate PropertyInfo Type (mtarld)
This PR was merged into the 7.1 branch. Discussion ---------- [PropertyInfo] Deprecate PropertyInfo Type | Q | A | ------------- | --- | Branch? | 7.1 | Bug fix? | no | New feature? | no | Deprecations? | yes | Issues | | License | MIT This PR is a follow-up of symfony/symfony#52510. As the TypeInfo's `Type` aims to represent types in the Symfony ecosystem, the PropertyInfo's `Type` needs to be deprecated in favor of the first one. Commits ------- d32e81c816 [PropertyInfo] Deprecate PropertyInfo Type
2 parents 4436611 + be567a3 commit 6a26d02

File tree

3 files changed

+245
-71
lines changed

3 files changed

+245
-71
lines changed

Mapping/Loader/PropertyInfoLoader.php

Lines changed: 139 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@
1515
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
1616
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
1717
use Symfony\Component\PropertyInfo\Type as PropertyInfoType;
18+
use Symfony\Component\TypeInfo\Type as TypeInfoType;
19+
use Symfony\Component\TypeInfo\Type\CollectionType;
20+
use Symfony\Component\TypeInfo\Type\IntersectionType;
21+
use Symfony\Component\TypeInfo\Type\ObjectType;
22+
use Symfony\Component\TypeInfo\Type\UnionType;
23+
use Symfony\Component\TypeInfo\TypeIdentifier;
1824
use Symfony\Component\Validator\Constraints\All;
1925
use Symfony\Component\Validator\Constraints\NotBlank;
2026
use Symfony\Component\Validator\Constraints\NotNull;
@@ -57,7 +63,7 @@ public function loadClassMetadata(ClassMetadata $metadata): bool
5763
continue;
5864
}
5965

60-
$types = $this->typeExtractor->getTypes($className, $property);
66+
$types = $this->getPropertyTypes($className, $property);
6167
if (null === $types) {
6268
continue;
6369
}
@@ -95,42 +101,92 @@ public function loadClassMetadata(ClassMetadata $metadata): bool
95101
}
96102

97103
$loaded = true;
98-
$builtinTypes = [];
99-
$nullable = false;
100-
$scalar = true;
101-
foreach ($types as $type) {
102-
$builtinTypes[] = $type->getBuiltinType();
103-
104-
if ($scalar && !\in_array($type->getBuiltinType(), [PropertyInfoType::BUILTIN_TYPE_INT, PropertyInfoType::BUILTIN_TYPE_FLOAT, PropertyInfoType::BUILTIN_TYPE_STRING, PropertyInfoType::BUILTIN_TYPE_BOOL], true)) {
105-
$scalar = false;
104+
105+
// BC layer for PropertyTypeExtractorInterface::getTypes().
106+
// Can be removed as soon as PropertyTypeExtractorInterface::getTypes() is removed (8.0).
107+
if (\is_array($types)) {
108+
$builtinTypes = [];
109+
$nullable = false;
110+
$scalar = true;
111+
112+
foreach ($types as $type) {
113+
$builtinTypes[] = $type->getBuiltinType();
114+
115+
if ($scalar && !\in_array($type->getBuiltinType(), ['int', 'float', 'string', 'bool'], true)) {
116+
$scalar = false;
117+
}
118+
119+
if (!$nullable && $type->isNullable()) {
120+
$nullable = true;
121+
}
122+
}
123+
124+
if (!$hasTypeConstraint) {
125+
if (1 === \count($builtinTypes)) {
126+
if ($types[0]->isCollection() && \count($collectionValueType = $types[0]->getCollectionValueTypes()) > 0) {
127+
[$collectionValueType] = $collectionValueType;
128+
$this->handleAllConstraintLegacy($property, $allConstraint, $collectionValueType, $metadata);
129+
}
130+
131+
$metadata->addPropertyConstraint($property, $this->getTypeConstraintLegacy($builtinTypes[0], $types[0]));
132+
} elseif ($scalar) {
133+
$metadata->addPropertyConstraint($property, new Type(['type' => 'scalar']));
134+
}
135+
}
136+
137+
if (!$nullable && !$hasNotBlankConstraint && !$hasNotNullConstraint) {
138+
$metadata->addPropertyConstraint($property, new NotNull());
106139
}
140+
} else {
141+
if ($hasTypeConstraint) {
142+
continue;
143+
}
144+
145+
$type = $types;
146+
$nullable = false;
107147

108-
if (!$nullable && $type->isNullable()) {
148+
if ($type instanceof UnionType && $type->isNullable()) {
109149
$nullable = true;
150+
$type = $type->asNonNullable();
110151
}
111-
}
112-
if (!$hasTypeConstraint) {
113-
if (1 === \count($builtinTypes)) {
114-
if ($types[0]->isCollection() && \count($collectionValueType = $types[0]->getCollectionValueTypes()) > 0) {
115-
[$collectionValueType] = $collectionValueType;
116-
$this->handleAllConstraint($property, $allConstraint, $collectionValueType, $metadata);
117-
}
118152

119-
$metadata->addPropertyConstraint($property, $this->getTypeConstraint($builtinTypes[0], $types[0]));
120-
} elseif ($scalar) {
121-
$metadata->addPropertyConstraint($property, new Type(['type' => 'scalar']));
153+
if ($type instanceof CollectionType) {
154+
$this->handleAllConstraint($property, $allConstraint, $type->getCollectionValueType(), $metadata);
155+
}
156+
157+
if (null !== $typeConstraint = $this->getTypeConstraint($type)) {
158+
$metadata->addPropertyConstraint($property, $typeConstraint);
122159
}
123-
}
124160

125-
if (!$nullable && !$hasNotBlankConstraint && !$hasNotNullConstraint) {
126-
$metadata->addPropertyConstraint($property, new NotNull());
161+
if (!$nullable && !$hasNotBlankConstraint && !$hasNotNullConstraint) {
162+
$metadata->addPropertyConstraint($property, new NotNull());
163+
}
127164
}
128165
}
129166

130167
return $loaded;
131168
}
132169

133-
private function getTypeConstraint(string $builtinType, PropertyInfoType $type): Type
170+
/**
171+
* BC layer for PropertyTypeExtractorInterface::getTypes().
172+
* Can be removed as soon as PropertyTypeExtractorInterface::getTypes() is removed (8.0).
173+
*
174+
* @return TypeInfoType|list<PropertyInfoType>|null
175+
*/
176+
private function getPropertyTypes(string $className, string $property): TypeInfoType|array|null
177+
{
178+
if (method_exists($this->typeExtractor, 'getType')) {
179+
return $this->typeExtractor->getType($className, $property);
180+
}
181+
182+
return $this->typeExtractor->getTypes($className, $property);
183+
}
184+
185+
/**
186+
* BC layer for PropertyTypeExtractorInterface::getTypes().
187+
* Can be removed as soon as PropertyTypeExtractorInterface::getTypes() is removed (8.0).
188+
*/
189+
private function getTypeConstraintLegacy(string $builtinType, PropertyInfoType $type): Type
134190
{
135191
if (PropertyInfoType::BUILTIN_TYPE_OBJECT === $builtinType && null !== $className = $type->getClassName()) {
136192
return new Type(['type' => $className]);
@@ -139,7 +195,64 @@ private function getTypeConstraint(string $builtinType, PropertyInfoType $type):
139195
return new Type(['type' => $builtinType]);
140196
}
141197

142-
private function handleAllConstraint(string $property, ?All $allConstraint, PropertyInfoType $propertyInfoType, ClassMetadata $metadata): void
198+
private function getTypeConstraint(TypeInfoType $type): ?Type
199+
{
200+
if ($type instanceof UnionType || $type instanceof IntersectionType) {
201+
return ($type->isA(TypeIdentifier::INT) || $type->isA(TypeIdentifier::FLOAT) || $type->isA(TypeIdentifier::STRING) || $type->isA(TypeIdentifier::BOOL)) ? new Type(['type' => 'scalar']) : null;
202+
}
203+
204+
$baseType = $type->getBaseType();
205+
206+
if ($baseType instanceof ObjectType) {
207+
return new Type(['type' => $baseType->getClassName()]);
208+
}
209+
210+
if (TypeIdentifier::MIXED !== $baseType->getTypeIdentifier()) {
211+
return new Type(['type' => $baseType->getTypeIdentifier()->value]);
212+
}
213+
214+
return null;
215+
}
216+
217+
private function handleAllConstraint(string $property, ?All $allConstraint, TypeInfoType $type, ClassMetadata $metadata): void
218+
{
219+
$containsTypeConstraint = false;
220+
$containsNotNullConstraint = false;
221+
if (null !== $allConstraint) {
222+
foreach ($allConstraint->constraints as $constraint) {
223+
if ($constraint instanceof Type) {
224+
$containsTypeConstraint = true;
225+
} elseif ($constraint instanceof NotNull) {
226+
$containsNotNullConstraint = true;
227+
}
228+
}
229+
}
230+
231+
$constraints = [];
232+
if (!$containsNotNullConstraint && !$type->isNullable()) {
233+
$constraints[] = new NotNull();
234+
}
235+
236+
if (!$containsTypeConstraint && null !== $typeConstraint = $this->getTypeConstraint($type)) {
237+
$constraints[] = $typeConstraint;
238+
}
239+
240+
if (!$constraints) {
241+
return;
242+
}
243+
244+
if (null === $allConstraint) {
245+
$metadata->addPropertyConstraint($property, new All(['constraints' => $constraints]));
246+
} else {
247+
$allConstraint->constraints = array_merge($allConstraint->constraints, $constraints);
248+
}
249+
}
250+
251+
/**
252+
* BC layer for PropertyTypeExtractorInterface::getTypes().
253+
* Can be removed as soon as PropertyTypeExtractorInterface::getTypes() is removed (8.0).
254+
*/
255+
private function handleAllConstraintLegacy(string $property, ?All $allConstraint, PropertyInfoType $propertyInfoType, ClassMetadata $metadata): void
143256
{
144257
$containsTypeConstraint = false;
145258
$containsNotNullConstraint = false;
@@ -159,7 +272,7 @@ private function handleAllConstraint(string $property, ?All $allConstraint, Prop
159272
}
160273

161274
if (!$containsTypeConstraint) {
162-
$constraints[] = $this->getTypeConstraint($propertyInfoType->getBuiltinType(), $propertyInfoType);
275+
$constraints[] = $this->getTypeConstraintLegacy($propertyInfoType->getBuiltinType(), $propertyInfoType);
163276
}
164277

165278
if (null === $allConstraint) {

0 commit comments

Comments
 (0)