Skip to content

Commit 6066de1

Browse files
committed
Merge branch '6.4' into 7.1
* 6.4: [AssetMapper] Fix `JavaScriptImportPathCompiler` regex for non-latin characters Definition::$class may not be class-string require Cache component versions compatible with Redis 6.1 [Twitter][Notifier] Fix post INIT upload [Messenger][RateLimiter] fix additional message handled when using a rate limiter [Serializer] fixed object normalizer for a class with `cancel` method Fix bucket size reduce when previously created with bigger size
2 parents 763e313 + 9d862d6 commit 6066de1

File tree

7 files changed

+194
-6
lines changed

7 files changed

+194
-6
lines changed

Mapping/Loader/AttributeLoader.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata): bool
124124
}
125125

126126
$accessorOrMutator = preg_match('/^(get|is|has|set)(.+)$/i', $method->name, $matches);
127-
if ($accessorOrMutator) {
127+
if ($accessorOrMutator && !ctype_lower($matches[2][0])) {
128128
$attributeName = lcfirst($matches[2]);
129129

130130
if (isset($attributesMetadata[$attributeName])) {

Normalizer/GetSetMethodNormalizer.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ private function isGetMethod(\ReflectionMethod $method): bool
8787
return !$method->isStatic()
8888
&& !($method->getAttributes(Ignore::class) || $method->getAttributes(LegacyIgnore::class))
8989
&& !$method->getNumberOfRequiredParameters()
90-
&& ((2 < ($methodLength = \strlen($method->name)) && str_starts_with($method->name, 'is'))
91-
|| (3 < $methodLength && (str_starts_with($method->name, 'has') || str_starts_with($method->name, 'get')))
90+
&& ((2 < ($methodLength = \strlen($method->name)) && str_starts_with($method->name, 'is') && !ctype_lower($method->name[2]))
91+
|| (3 < $methodLength && (str_starts_with($method->name, 'has') || str_starts_with($method->name, 'get')) && !ctype_lower($method->name[3]))
9292
);
9393
}
9494

@@ -100,7 +100,9 @@ private function isSetMethod(\ReflectionMethod $method): bool
100100
return !$method->isStatic()
101101
&& !$method->getAttributes(Ignore::class)
102102
&& 0 < $method->getNumberOfParameters()
103-
&& str_starts_with($method->name, 'set');
103+
&& str_starts_with($method->name, 'set')
104+
&& !ctype_lower($method->name[3])
105+
;
104106
}
105107

106108
protected function extractAttributes(object $object, ?string $format = null, array $context = []): array

Normalizer/ObjectNormalizer.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ protected function extractAttributes(object $object, ?string $format = null, arr
8888
$name = $reflMethod->name;
8989
$attributeName = null;
9090

91-
if (3 < \strlen($name) && match ($name[0]) {
91+
// ctype_lower check to find out if method looks like accessor but actually is not, e.g. hash, cancel
92+
if (3 < \strlen($name) && !ctype_lower($name[3]) && match ($name[0]) {
9293
'g' => str_starts_with($name, 'get'),
9394
'h' => str_starts_with($name, 'has'),
9495
'c' => str_starts_with($name, 'can'),
@@ -100,7 +101,7 @@ protected function extractAttributes(object $object, ?string $format = null, arr
100101
if (!$reflClass->hasProperty($attributeName)) {
101102
$attributeName = lcfirst($attributeName);
102103
}
103-
} elseif ('is' !== $name && str_starts_with($name, 'is')) {
104+
} elseif ('is' !== $name && str_starts_with($name, 'is') && !ctype_lower($name[2])) {
104105
// issers
105106
$attributeName = substr($name, 2);
106107

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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+
namespace Symfony\Component\Serializer\Tests\Fixtures\Attributes;
13+
14+
class AccessorishGetters
15+
{
16+
public function hash(): void
17+
{
18+
}
19+
20+
public function cancel()
21+
{
22+
}
23+
24+
public function getField1()
25+
{
26+
}
27+
28+
public function isField2()
29+
{
30+
}
31+
32+
public function hasField3()
33+
{
34+
}
35+
36+
public function setField4()
37+
{
38+
}
39+
}

Tests/Mapping/Loader/AttributeLoaderTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\AbstractDummyFirstChild;
2424
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\AbstractDummySecondChild;
2525
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\AbstractDummyThirdChild;
26+
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\AccessorishGetters;
2627
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\BadAttributeDummy;
2728
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\BadMethodContextDummy;
2829
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\ContextDummyParent;
@@ -229,6 +230,22 @@ public function testLoadWithInvalidAttribute()
229230
$this->loader->loadClassMetadata($classMetadata);
230231
}
231232

233+
public function testIgnoresAccessorishGetters()
234+
{
235+
$classMetadata = new ClassMetadata(AccessorishGetters::class);
236+
$this->loader->loadClassMetadata($classMetadata);
237+
238+
$attributesMetadata = $classMetadata->getAttributesMetadata();
239+
240+
self::assertCount(4, $classMetadata->getAttributesMetadata());
241+
242+
self::assertArrayHasKey('field1', $attributesMetadata);
243+
self::assertArrayHasKey('field2', $attributesMetadata);
244+
self::assertArrayHasKey('field3', $attributesMetadata);
245+
self::assertArrayHasKey('field4', $attributesMetadata);
246+
self::assertArrayNotHasKey('h', $attributesMetadata);
247+
}
248+
232249
protected function getLoaderForContextMapping(): AttributeLoader
233250
{
234251
return $this->loader;

Tests/Normalizer/GetSetMethodNormalizerTest.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,14 @@ public function testNormalizeWithDiscriminator()
521521
$this->assertSame(['type' => 'one', 'url' => 'URL_ONE'], $normalizer->normalize(new GetSetMethodDiscriminatedDummyOne()));
522522
}
523523

524+
public function testNormalizeWithMethodNamesSimilarToAccessors()
525+
{
526+
$classMetadataFactory = new ClassMetadataFactory(new AttributeLoader());
527+
$normalizer = new GetSetMethodNormalizer($classMetadataFactory);
528+
529+
$this->assertSame(['class' => 'class', 123 => 123], $normalizer->normalize(new GetSetWithAccessorishMethod()));
530+
}
531+
524532
public function testDenormalizeWithDiscriminator()
525533
{
526534
$classMetadataFactory = new ClassMetadataFactory(new AttributeLoader());
@@ -908,3 +916,46 @@ public function setBar($bar = null, $other = true)
908916
$this->bar = $bar;
909917
}
910918
}
919+
920+
class GetSetWithAccessorishMethod
921+
{
922+
public function cancel()
923+
{
924+
return 'cancel';
925+
}
926+
927+
public function hash()
928+
{
929+
return 'hash';
930+
}
931+
932+
public function getClass()
933+
{
934+
return 'class';
935+
}
936+
937+
public function setClass()
938+
{
939+
}
940+
941+
public function get123()
942+
{
943+
return 123;
944+
}
945+
946+
public function set123()
947+
{
948+
}
949+
950+
public function gettings()
951+
{
952+
}
953+
954+
public function settings()
955+
{
956+
}
957+
958+
public function isolate()
959+
{
960+
}
961+
}

Tests/Normalizer/ObjectNormalizerTest.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,24 @@ public function testObjectNormalizerWithAttributeLoaderAndObjectHasStaticPropert
961961
$normalizer = new ObjectNormalizer(new ClassMetadataFactory(new AttributeLoader()));
962962
$this->assertSame([], $normalizer->normalize($class));
963963
}
964+
965+
public function testNormalizeWithMethodNamesSimilarToAccessors()
966+
{
967+
$classMetadataFactory = new ClassMetadataFactory(new AttributeLoader());
968+
$normalizer = new ObjectNormalizer($classMetadataFactory);
969+
970+
$object = new ObjectWithAccessorishMethods();
971+
$normalized = $normalizer->normalize($object);
972+
973+
$this->assertFalse($object->isAccessorishCalled());
974+
$this->assertSame([
975+
'accessorishCalled' => false,
976+
'tell' => true,
977+
'class' => true,
978+
'responsibility' => true,
979+
123 => 321
980+
], $normalized);
981+
}
964982
}
965983

966984
class ProxyObjectDummy extends ObjectDummy
@@ -1243,3 +1261,63 @@ class ObjectDummyWithIgnoreAttributeAndPrivateProperty
12431261

12441262
private $private = 'private';
12451263
}
1264+
1265+
class ObjectWithAccessorishMethods
1266+
{
1267+
private $accessorishCalled = false;
1268+
1269+
public function isAccessorishCalled()
1270+
{
1271+
return $this->accessorishCalled;
1272+
}
1273+
1274+
public function cancel()
1275+
{
1276+
$this->accessorishCalled = true;
1277+
}
1278+
1279+
public function hash()
1280+
{
1281+
$this->accessorishCalled = true;
1282+
}
1283+
1284+
public function canTell()
1285+
{
1286+
return true;
1287+
}
1288+
1289+
public function getClass()
1290+
{
1291+
return true;
1292+
}
1293+
1294+
public function hasResponsibility()
1295+
{
1296+
return true;
1297+
}
1298+
1299+
public function get_foo()
1300+
{
1301+
return 'bar';
1302+
}
1303+
1304+
public function get123()
1305+
{
1306+
return 321;
1307+
}
1308+
1309+
public function gettings()
1310+
{
1311+
$this->accessorishCalled = true;
1312+
}
1313+
1314+
public function settings()
1315+
{
1316+
$this->accessorishCalled = true;
1317+
}
1318+
1319+
public function isolate()
1320+
{
1321+
$this->accessorishCalled = true;
1322+
}
1323+
}

0 commit comments

Comments
 (0)