8000 bug #58259 [TypeInfo] Return bound type as base type in `TemplateType… · symfony/symfony@bd3a256 · GitHub
[go: up one dir, main page]

Skip to content

Commit bd3a256

Browse files
committed
bug #58259 [TypeInfo] Return bound type as base type in TemplateType (valtzu)
This PR was merged into the 7.1 branch. Discussion ---------- [TypeInfo] Return bound type as base type in `TemplateType` | Q | A | ------------- | --- | Branch? | 7.1 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | Fix #58031 | License | MIT This supersedes #58033 as simpler approach. Commits ------- f897a7b Fix `TemplateType` handling in `AbstractObjectNormalizer`
2 parents 180f389 + f897a7b commit bd3a256

File tree

2 files changed

+77
-2
lines changed

2 files changed

+77
-2
lines changed

src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
16+
use Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor;
1617
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
1718
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
1819
use Symfony\Component\PropertyInfo\Type as LegacyType;
@@ -37,6 +38,7 @@
3738
use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter;
3839
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
3940
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
41+
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
4042
use Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer;
4143
use Symfony\Component\Serializer\Normalizer\CustomNormalizer;
4244
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
@@ -1247,6 +1249,52 @@ protected function isAllowedAttribute($classOrObject, string $attribute, ?string
12471249
$this->assertInstanceOf(\ArrayObject::class, $actual->foo);
12481250
$this->assertSame(1, $actual->foo->count());
12491251
}
1252+
1253+
public function testTemplateTypeWhenAnObjectIsPassedToDenormalize()
1254+
{
1255+
$normalizer = new class (
1256+
classMetadataFactory: new ClassMetadataFactory(new AttributeLoader()),
1257+
propertyTypeExtractor: new PropertyInfoExtractor(typeExtractors: [new PhpStanExtractor(), new ReflectionExtractor()])
1258+
) extends AbstractObjectNormalizerDummy {
1259+
protected function isAllowedAttribute($classOrObject, string $attribute, ?string $format = null, array $context = []): bool
1260+
{
1261+
return true;
1262+
}
1263+
};
1264+
$serializer = new Serializer([$normalizer]);
1265+
$normalizer->setSerializer($serializer);
1266+
1267+
$denormalizedData = $normalizer->denormalize(['value' => new DummyGenericsValue()], DummyGenericsValueWrapper::class);
1268+
1269+
$this->assertInstanceOf(DummyGenericsValueWrapper::class, $denormalizedData);
1270+
$this->assertInstanceOf(DummyGenericsValue::class, $denormalizedData->value);
1271+
1272+
$this->assertSame('dummy', $denormalizedData->value->type);
1273+
}
1274+
1275+
public function testDenormalizeTemplateType()
1276+
{
1277+
$normalizer = new class (
1278+
classMetadataFactory: new ClassMetadataFactory(new AttributeLoader()),
1279+
propertyTypeExtractor: new PropertyInfoExtractor(typeExtractors: [new PhpStanExtractor(), new ReflectionExtractor()])
1280+
) extends AbstractObjectNormalizerDummy {
1281+
protected function isAllowedAttribute($classOrObject, string $attribute, ?string $format = null, array $context = []): bool
1282+
{
1283+
return true;
1284+
}
1285+
};
1286+
$serializer = new Serializer([new ArrayDenormalizer(), $normalizer]);
1287+
$normalizer->setSerializer($serializer);
1288+
1289+
$denormalizedData = $normalizer->denormalize(['value' => ['type' => 'dummy'], 'values' => [['type' => 'dummy']]], DummyGenericsValueWrapper::class);
1290+
1291+
$this->assertInstanceOf(DummyGenericsValueWrapper::class, $denormalizedData);
1292+
$this->assertInstanceOf(DummyGenericsValue::class, $denormalizedData->value);
1293+
$this->assertContainsOnlyInstancesOf(DummyGenericsValue::class, $denormalizedData->values);
1294+
$this->assertCount(1, $denormalizedData->values);
1295+
$this->assertSame('dummy', $denormalizedData->value->type);
1296+
$this->assertSame('dummy', $denormalizedData->values[0]->type);
1297+
}
12501298
}
12511299

12521300
class AbstractObjectNormalizerDummy extends AbstractObjectNormalizer
@@ -1753,3 +1801,31 @@ public function getSupportedTypes(?string $format): array
17531801
];
17541802
}
17551803
}
1804+
1805+
#[DiscriminatorMap('type', ['dummy' => DummyGenericsValue::class])]
1806+
abstract class AbstractDummyGenericsValue
1807+
{
1808+
public function __construct(
1809+
public string $type,
1810+
) {
1811+
}
1812+
}
1813+
1814+
class DummyGenericsValue extends AbstractDummyGenericsValue
1815+
{
1816+
public function __construct()
1817+
{
1818+
parent::__construct('dummy');
1819+
}
1820+
}
1821+
1822+
/**
1823+
* @template T of AbstractDummyGenericsValue
1824+
*/
1825+
class DummyGenericsValueWrapper
1826+
{
1827+
/** @var T */
1828+
public mixed $value;
1829+
/** @var T[] */
1830+
public array $values;
1831+
}

src/Symfony/Component/TypeInfo/Type/TemplateType.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
namespace Symfony\Component\TypeInfo\Type;
1313

14-
use Symfony\Component\TypeInfo\Exception\LogicException;
1514
use Symfony\Component\TypeInfo\Type;
1615
use Symfony\Component\TypeInfo\TypeIdentifier;
1716

@@ -33,7 +32,7 @@ public function __construct(
3332

3433
public function getBaseType(): BuiltinType|ObjectType
3534
{
36-
throw new LogicException(sprintf('Cannot get base type on "%s" template type.', $this));
35+
return $this->bound->getBaseType();
3736
}
3837

3938
public function isA(TypeIdentifier|string $subject): bool

0 commit comments

Comments
 (0)
0