Skip to content

Commit af8726a

Browse files
committed
Merge 3.1
2 parents a98ef1a + 2aed3c1 commit af8726a

File tree

3 files changed

+84
-4
lines changed

3 files changed

+84
-4
lines changed

phpunit.xml.dist

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<server name="KERNEL_DIR" value="tests/Fixtures/app/" />
1212
<server name="KERNEL_CLASS" value="AppKernel" />
1313
<env name="APP_ENV" value="test" />
14+
<env name="SYMFONY_PHPUNIT_REQUIRE" value="nikic/php-parser:^4.16"/>
1415
</php>
1516

1617
<testsuites>

src/Serializer/AbstractItemNormalizer.php

+5-4
Original file line numberDiff line numberDiff line change
@@ -607,9 +607,10 @@ protected function getFactoryOptions(array $context): array
607607
$options['serializer_groups'] = (array) $context[self::GROUPS];
608608
}
609609

610-
$operationCacheKey = ($context['resource_class'] ?? '').($context['operation_name'] ?? '').($context['api_normalize'] ?? '');
611-
if ($operationCacheKey && isset($this->localFactoryOptionsCache[$operationCacheKey])) {
612-
return $options + $this->localFactoryOptionsCache[$operationCacheKey];
610+
$operationCacheKey = ($context['resource_class'] ?? '').($context['operation_name'] ?? '').($context['root_operation_name'] ?? '');
611+
$suffix = ($context['api_normalize'] ?? '') ? 'n' : '';
612+
if ($operationCacheKey && isset($this->localFactoryOptionsCache[$operationCacheKey.$suffix])) {
613+
return $options + $this->localFactoryOptionsCache[$operationCacheKey.$suffix];
613614
}
614615

615616
// This is a hot spot
@@ -622,7 +623,7 @@ protected function getFactoryOptions(array $context): array
622623
}
623624
}
624625

625-
return $options + $this->localFactoryOptionsCache[$operationCacheKey] = $options;
626+
return $options + $this->localFactoryOptionsCache[$operationCacheKey.$suffix] = $options;
626627
}
627628

628629
/**

src/Serializer/Tests/AbstractItemNormalizerTest.php

+78
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,84 @@ public function testDenormalizeObjectWithNullDisabledTypeEnforcement(): void
15451545
$this->assertInstanceOf(DtoWithNullValue::class, $actual);
15461546
$this->assertEquals(new DtoWithNullValue(), $actual);
15471547
}
1548+
1549+
public function testCacheKey(): void
1550+
{
1551+
$relatedDummy = new RelatedDummy();
1552+
1553+
$dummy = new Dummy();
1554+
$dummy->setName('foo');
1555+
$dummy->setAlias('ignored');
1556+
$dummy->setRelatedDummy($relatedDummy);
1557+
$dummy->relatedDummies->add(new RelatedDummy());
1558+
1559+
$relatedDummies = new ArrayCollection([$relatedDummy]);
1560+
1561+
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
1562+
$propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name', 'alias', 'relatedDummy', 'relatedDummies']));
1563+
1564+
$relatedDummyType = new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class);
1565+
$relatedDummiesType = new Type(Type::BUILTIN_TYPE_OBJECT, false, ArrayCollection::class, true, new Type(Type::BUILTIN_TYPE_INT), $relatedDummyType);
1566+
1567+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
1568+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('')->withReadable(true));
1569+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'alias', Argument::type('array'))->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('')->withReadable(true));
1570+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', Argument::type('array'))->willReturn((new ApiProperty())->withBuiltinTypes([$relatedDummyType])->withDescription('')->withReadable(true)->withWritable(false)->withReadableLink(false));
1571+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies', Argument::type('array'))->willReturn((new ApiProperty())->withBuiltinTypes([$relatedDummiesType])->withReadable(true)->withWritable(false)->withReadableLink(false));
1572+
1573+
$iriConverterProphecy = $this->prophesize(IriConverterInterface::class);
1574+
$iriConverterProphecy->getIriFromResource($dummy, Argument::cetera())->willReturn('/dummies/1');
1575+
$iriConverterProphecy->getIriFromResource($relatedDummy, Argument::cetera())->willReturn('/dummies/2');
1576+
1577+
$propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class);
1578+
$propertyAccessorProphecy->getValue($dummy, 'name')->willReturn('foo');
1579+
$propertyAccessorProphecy->getValue($dummy, 'relatedDummy')->willReturn($relatedDummy);
1580+
$propertyAccessorProphecy->getValue($dummy, 'relatedDummies')->willReturn($relatedDummies);
1581+
1582+
$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
1583+
$resourceClassResolverProphecy->getResourceClass(null, Dummy::class)->willReturn(Dummy::class);
1584+
$resourceClassResolverProphecy->getResourceClass($dummy, null)->willReturn(Dummy::class);
1585+
$resourceClassResolverProphecy->getResourceClass($relatedDummy, RelatedDummy::class)->willReturn(RelatedDummy::class);
1586+
$resourceClassResolverProphecy->getResourceClass($relatedDummies, RelatedDummy::class)->willReturn(RelatedDummy::class);
1587+
$resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true);
1588+
$resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true);
1589+
1590+
$serializerProphecy = $this->prophesize(SerializerInterface::class);
1591+
$serializerProphecy->willImplement(NormalizerInterface::class);
1592+
$serializerProphecy->normalize('foo', null, Argument::type('array'))->willReturn('foo');
1593+
$serializerProphecy->normalize(['/dummies/2'], null, Argument::type('array'))->willReturn(['/dummies/2']);
1594+
1595+
$normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [
1596+
$propertyNameCollectionFactoryProphecy->reveal(),
1597+
$propertyMetadataFactoryProphecy->reveal(),
1598+
$iriConverterProphecy->reveal(),
1599+
$resourceClassResolverProphecy->reveal(),
1600+
$propertyAccessorProphecy->reveal(),
1601+
null,
1602+
null,
1603+
[],
1604+
null,
1605+
null,
1606+
]);
1607+
$normalizer->setSerializer($serializerProphecy->reveal());
1608+
1609+
$expected = [
1610+
'name' => 'foo',
1611+
'relatedDummy' => '/dummies/2',
1612+
'relatedDummies' => ['/dummies/2'],
1613+
];
1614+
$this->assertSame($expected, $normalizer->normalize($dummy, null, [
1615+
'resources' => [],
1616+
'groups' => ['group'],
1617+
'ignored_attributes' => ['alias'],
1618+
'operation_name' => 'operation_name',
1619+
'root_operation_name' => 'root_operation_name',
1620+
]));
1621+
1622+
$operationCacheKey = (new \ReflectionClass($normalizer))->getProperty('localFactoryOptionsCache')->getValue($normalizer);
1623+
$this->assertEquals(array_keys($operationCacheKey), [sprintf('%s%s%s%s', Dummy::class, 'operation_name', 'root_operation_name', 'n')]);
1624+
$this->assertEquals(current($operationCacheKey), ['serializer_groups' => ['group']]);
1625+
}
15481626
}
15491627

15501628
class ObjectWithBasicProperties

0 commit comments

Comments
 (0)