Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit76bcfb5

Browse files
committed
convert legacy types to TypeInfo types if getType() is not implemented
1 parent7abc106 commit76bcfb5

File tree

5 files changed

+279
-2
lines changed

5 files changed

+279
-2
lines changed

‎src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespaceSymfony\Component\PropertyInfo;
1313

1414
usePsr\Cache\CacheItemPoolInterface;
15+
useSymfony\Component\PropertyInfo\Util\LegacyTypeConverter;
1516
useSymfony\Component\TypeInfo\Type;
1617

1718
/**
@@ -61,7 +62,40 @@ public function getProperties(string $class, array $context = []): ?array
6162
*/
6263
publicfunctiongetType(string$class,string$property,array$context = []): ?Type
6364
{
64-
return$this->extract('getType', [$class,$property,$context]);
65+
try {
66+
$serializedArguments =serialize([$class,$property,$context]);
67+
}catch (\Exception) {
68+
// If arguments are not serializable, skip the cache
69+
if (method_exists($this->propertyInfoExtractor,'getType')) {
70+
return$this->propertyInfoExtractor->getType($class,$property,$context);
71+
}
72+
73+
return LegacyTypeConverter::toTypeInfoType($this->propertyInfoExtractor->getTypes($class,$property,$context));
74+
}
75+
76+
// Calling rawurlencode escapes special characters not allowed in PSR-6's keys
77+
$key =rawurlencode('getType.'.$serializedArguments);
78+
79+
if (\array_key_exists($key,$this->arrayCache)) {
80+
return$this->arrayCache[$key];
81+
}
82+
83+
$item =$this->cacheItemPool->getItem($key);
84+
85+
if ($item->isHit()) {
86+
return$this->arrayCache[$key] =$item->get();
87+
}
88+
89+
if (method_exists($this->propertyInfoExtractor,'getType')) {
90+
$value =$this->propertyInfoExtractor->getType($class,$property,$context);
91+
}else {
92+
$value = LegacyTypeConverter::toTypeInfoType($this->propertyInfoExtractor->getTypes($class,$property,$context));
93+
}
94+
95+
$item->set($value);
96+
$this->cacheItemPool->save($item);
97+
98+
return$this->arrayCache[$key] =$value;
6599
}
66100

67101
publicfunctiongetTypes(string$class,string$property,array$context = []): ?array

‎src/Symfony/Component/PropertyInfo/PropertyInfoExtractor.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespaceSymfony\Component\PropertyInfo;
1313

14+
useSymfony\Component\PropertyInfo\Util\LegacyTypeConverter;
1415
useSymfony\Component\TypeInfo\Type;
1516

1617
/**
@@ -58,7 +59,23 @@ public function getLongDescription(string $class, string $property, array $conte
5859
*/
5960
publicfunctiongetType(string$class,string$property,array$context = []): ?Type
6061
{
61-
return$this->extract($this->typeExtractors,'getType', [$class,$property,$context]);
62+
foreach ($this->typeExtractorsas$extractor) {
63+
if (!method_exists($extractor,'getType')) {
64+
$legacyTypes =$extractor->getTypes($class,$property,$context);
65+
66+
if (null !==$legacyTypes) {
67+
return LegacyTypeConverter::toTypeInfoType($legacyTypes);
68+
}
69+
70+
continue;
71+
}
72+
73+
if (null !==$value =$extractor->getType($class,$property,$context)) {
74+
return$value;
75+
}
76+
}
77+
78+
returnnull;
6279
}
6380

6481
publicfunctiongetTypes(string$class,string$property,array$context = []): ?array

‎src/Symfony/Component/PropertyInfo/Tests/PropertyInfoCacheExtractorTest.php

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@
1212
namespaceSymfony\Component\PropertyInfo\Tests;
1313

1414
useSymfony\Component\Cache\Adapter\ArrayAdapter;
15+
useSymfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
1516
useSymfony\Component\PropertyInfo\PropertyInfoCacheExtractor;
17+
useSymfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
18+
useSymfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
19+
useSymfony\Component\PropertyInfo\Tests\Fixtures\Dummy;
20+
useSymfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy;
21+
useSymfony\Component\TypeInfo\Type;
1622

1723
/**
1824
* @author Kévin Dunglas <dunglas@gmail.com>
@@ -76,4 +82,89 @@ public function testIsInitializable()
7682
parent::testIsInitializable();
7783
parent::testIsInitializable();
7884
}
85+
86+
/**
87+
* @group legacy
88+
* @dataProvider provideNestedExtractorWithoutGetTypeImplementationData
89+
*/
90+
publicfunctiontestNestedExtractorWithoutGetTypeImplementation(string$property, ?Type$expectedType)
91+
{
92+
$propertyInfoCacheExtractor =newPropertyInfoCacheExtractor(newclass()implements PropertyInfoExtractorInterface {
93+
privatePropertyTypeExtractorInterface$propertyTypeExtractor;
94+
95+
publicfunction__construct()
96+
{
97+
$this->propertyTypeExtractor =newPhpDocExtractor();
98+
}
99+
100+
publicfunctiongetTypes(string$class,string$property,array$context = []): ?array
101+
{
102+
return$this->propertyTypeExtractor->getTypes($class,$property,$context);
103+
}
104+
105+
publicfunctionisReadable(string$class,string$property,array$context = []): ?bool
106+
{
107+
returnnull;
108+
}
109+
110+
publicfunctionisWritable(string$class,string$property,array$context = []): ?bool
111+
{
112+
returnnull;
113+
}
114+
115+
publicfunctiongetShortDescription(string$class,string$property,array$context = []): ?string
116+
{
117+
returnnull;
118+
}
119+
120+
publicfunctiongetLongDescription(string$class,string$property,array$context = []): ?string
121+
{
122+
returnnull;
123+
}
124+
125+
publicfunctiongetProperties(string$class,array$context = []): ?array
126+
{
127+
returnnull;
128+
}
129+
},newArrayAdapter());
130+
131+
if (null ===$expectedType) {
132+
$this->assertNull($propertyInfoCacheExtractor->getType(Dummy::class,$property));
133+
}else {
134+
$this->assertEquals($expectedType,$propertyInfoCacheExtractor->getType(Dummy::class,$property));
135+
}
136+
}
137+
138+
publicfunctionprovideNestedExtractorWithoutGetTypeImplementationData()
139+
{
140+
yield ['bar', Type::string()];
141+
yield ['baz', Type::int()];
142+
yield ['bal', Type::object(\DateTimeImmutable::class)];
143+
yield ['parent', Type::object(ParentDummy::class)];
144+
yield ['collection', Type::array(Type::object(\DateTimeImmutable::class), Type::int())];
145+
yield ['nestedCollection', Type::array(Type::array(Type::string(), Type::int()), Type::int())];
146+
yield ['mixedCollection', Type::array()];
147+
yield ['B', Type::object(ParentDummy::class)];
148+
yield ['Id', Type::int()];
149+
yield ['Guid', Type::string()];
150+
yield ['g', Type::nullable(Type::array())];
151+
yield ['h', Type::nullable(Type::string())];
152+
yield ['i', Type::nullable(Type::union(Type::string(), Type::int()))];
153+
yield ['j', Type::nullable(Type::object(\DateTimeImmutable::class))];
154+
yield ['nullableCollectionOfNonNullableElements', Type::nullable(Type::array(Type::int(), Type::int()))];
155+
yield ['nonNullableCollectionOfNullableElements', Type::array(Type::nullable(Type::int()), Type::int())];
156+
yield ['nullableCollectionOfMultipleNonNullableElementTypes', Type::nullable(Type::array(Type::union(Type::int(), Type::string()), Type::int()))];
157+
yield ['xTotals', Type::array()];
158+
yield ['YT', Type::string()];
159+
yield ['emptyVar',null];
160+
yield ['iteratorCollection', Type::collection(Type::object(\Iterator::class), Type::string(), Type::union(Type::string(), Type::int()))];
161+
yield ['iteratorCollectionWithKey', Type::collection(Type::object(\Iterator::class), Type::string(), Type::int())];
162+
yield ['nestedIterators', Type::collection(Type::object(\Iterator::class), Type::collection(Type::object(\Iterator::class), Type::string(), Type::int()), Type::int())];
163+
yield ['arrayWithKeys', Type::array(Type::string(), Type::string())];
164+
yield ['arrayWithKeysAndComplexValue', Type::array(Type::nullable(Type::array(Type::nullable(Type::string()), Type::int())), Type::string())];
165+
yield ['arrayOfMixed', Type::array(Type::mixed(), Type::string())];
166+
yield ['noDocBlock',null];
167+
yield ['listOfStrings', Type::array(Type::string(), Type::int())];
168+
yield ['parentAnnotation', Type::object(ParentDummy::class)];
169+
}
79170
}

‎src/Symfony/Component/PropertyInfo/Tests/PropertyInfoExtractorTest.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,75 @@
1111

1212
namespaceSymfony\Component\PropertyInfo\Tests;
1313

14+
useSymfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
15+
useSymfony\Component\PropertyInfo\PropertyInfoExtractor;
16+
useSymfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
17+
useSymfony\Component\PropertyInfo\Tests\Fixtures\Dummy;
18+
useSymfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy;
19+
useSymfony\Component\TypeInfo\Type;
20+
1421
/**
1522
* @author Kévin Dunglas <dunglas@gmail.com>
1623
*/
1724
class PropertyInfoExtractorTestextends AbstractPropertyInfoExtractorTest
1825
{
26+
/**
27+
* @group legacy
28+
* @dataProvider provideNestedExtractorWithoutGetTypeImplementationData
29+
*/
30+
publicfunctiontestNestedExtractorWithoutGetTypeImplementation(string$property, ?Type$expectedType)
31+
{
32+
$propertyInfoExtractor =newPropertyInfoExtractor([], [newclass()implements PropertyTypeExtractorInterface {
33+
privatePropertyTypeExtractorInterface$propertyTypeExtractor;
34+
35+
publicfunction__construct()
36+
{
37+
$this->propertyTypeExtractor =newPhpDocExtractor();
38+
}
39+
40+
publicfunctiongetTypes(string$class,string$property,array$context = []): ?array
41+
{
42+
return$this->propertyTypeExtractor->getTypes($class,$property,$context);
43+
}
44+
}]);
45+
46+
if (null ===$expectedType) {
47+
$this->assertNull($propertyInfoExtractor->getType(Dummy::class,$property));
48+
}else {
49+
$this->assertEquals($expectedType,$propertyInfoExtractor->getType(Dummy::class,$property));
50+
}
51+
}
52+
53+
publicfunctionprovideNestedExtractorWithoutGetTypeImplementationData()
54+
{
55+
yield ['bar', Type::string()];
56+
yield ['baz', Type::int()];
57+
yield ['bal', Type::object(\DateTimeImmutable::class)];
58+
yield ['parent', Type::object(ParentDummy::class)];
59+
yield ['collection', Type::array(Type::object(\DateTimeImmutable::class), Type::int())];
60+
yield ['nestedCollection', Type::array(Type::array(Type::string(), Type::int()), Type::int())];
61+
yield ['mixedCollection', Type::array()];
62+
yield ['B', Type::object(ParentDummy::class)];
63+
yield ['Id', Type::int()];
64+
yield ['Guid', Type::string()];
65+
yield ['g', Type::nullable(Type::array())];
66+
yield ['h', Type::nullable(Type::string())];
67+
yield ['i', Type::nullable(Type::union(Type::string(), Type::int()))];
68+
yield ['j', Type::nullable(Type::object(\DateTimeImmutable::class))];
69+
yield ['nullableCollectionOfNonNullableElements', Type::nullable(Type::array(Type::int(), Type::int()))];
70+
yield ['nonNullableCollectionOfNullableElements', Type::array(Type::nullable(Type::int()), Type::int())];
71+
yield ['nullableCollectionOfMultipleNonNullableElementTypes', Type::nullable(Type::array(Type::union(Type::int(), Type::string()), Type::int()))];
72+
yield ['xTotals', Type::array()];
73+
yield ['YT', Type::string()];
74+
yield ['emptyVar',null];
75+
yield ['iteratorCollection', Type::collection(Type::object(\Iterator::class), Type::string(), Type::union(Type::string(), Type::int()))];
76+
yield ['iteratorCollectionWithKey', Type::collection(Type::object(\Iterator::class), Type::string(), Type::int())];
77+
yield ['nestedIterators', Type::collection(Type::object(\Iterator::class), Type::collection(Type::object(\Iterator::class), Type::string(), Type::int()), Type::int())];
78+
yield ['arrayWithKeys', Type::array(Type::string(), Type::string())];
79+
yield ['arrayWithKeysAndComplexValue', Type::array(Type::nullable(Type::array(Type::nullable(Type::string()), Type::int())), Type::string())];
80+
yield ['arrayOfMixed', Type::array(Type::mixed(), Type::string())];
81+
yield ['noDocBlock',null];
82+
yield ['listOfStrings', Type::array(Type::string(), Type::int())];
83+
yield ['parentAnnotation', Type::object(ParentDummy::class)];
84+
}
1985
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.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+
namespaceSymfony\Component\PropertyInfo\Util;
13+
14+
useSymfony\Component\PropertyInfo\TypeasLegacyType;
15+
useSymfony\Component\TypeInfo\Type;
16+
17+
/**
18+
* @internal
19+
*/
20+
class LegacyTypeConverter
21+
{
22+
/**
23+
* @param LegacyType[]|null $legacyTypes
24+
*/
25+
publicstaticfunctiontoTypeInfoType(?array$legacyTypes): ?Type
26+
{
27+
if (null ===$legacyTypes || [] ===$legacyTypes) {
28+
returnnull;
29+
}
30+
31+
$nullable =false;
32+
$types = [];
33+
34+
foreach ($legacyTypesas$legacyType) {
35+
if ($legacyType->isCollection() && !\in_array($legacyType->getBuiltinType(), [LegacyType::BUILTIN_TYPE_ARRAY, LegacyType::BUILTIN_TYPE_ITERABLE],true)) {
36+
$typeInfoType = Type::collection(Type::object(\Iterator::class),self::toTypeInfoType($legacyType->getCollectionValueTypes()),self::toTypeInfoType($legacyType->getCollectionKeyTypes()));
37+
}else {
38+
$typeInfoType =match ($legacyType->getBuiltinType()) {
39+
LegacyType::BUILTIN_TYPE_ARRAY => Type::array(self::toTypeInfoType($legacyType->getCollectionValueTypes()),self::toTypeInfoType($legacyType->getCollectionKeyTypes())),
40+
LegacyType::BUILTIN_TYPE_BOOL => Type::bool(),
41+
LegacyType::BUILTIN_TYPE_CALLABLE => Type::callable(),
42+
LegacyType::BUILTIN_TYPE_FALSE => Type::false(),
43+
LegacyType::BUILTIN_TYPE_FLOAT => Type::float(),
44+
LegacyType::BUILTIN_TYPE_INT => Type::int(),
45+
LegacyType::BUILTIN_TYPE_ITERABLE => Type::iterable(self::toTypeInfoType($legacyType->getCollectionValueTypes()),self::toTypeInfoType($legacyType->getCollectionKeyTypes())),
46+
LegacyType::BUILTIN_TYPE_OBJECT => Type::object($legacyType->getClassName()),
47+
LegacyType::BUILTIN_TYPE_RESOURCE => Type::resource(),
48+
LegacyType::BUILTIN_TYPE_STRING => Type::string(),
49+
LegacyType::BUILTIN_TYPE_TRUE => Type::true(),
50+
default =>null,
51+
};
52+
}
53+
54+
if (LegacyType::BUILTIN_TYPE_NULL ===$legacyType->getBuiltinType() ||$legacyType->isNullable()) {
55+
$nullable =true;
56+
}
57+
58+
if (null !==$typeInfoType) {
59+
$types[] =$typeInfoType;
60+
}
61+
}
62+
63+
if (1 ===\count($types)) {
64+
return$nullable ? Type::nullable($types[0]) :$types[0];
65+
}
66+
67+
return$nullable ? Type::nullable(Type::union(...$types)) : Type::union(...$types);
68+
}
69+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp