Skip to content

Commit 558477c

Browse files
Merge branch '6.4' into 7.2
* 6.4: Fix typo [VarExporter] Dump implicit-nullable types as explicit to prevent the corresponding deprecation [Serializer] Fix readonly property initialization from incorrect scope Update BrevoRequestParser.php
2 parents 7e29d58 + d524bc9 commit 558477c

File tree

8 files changed

+138
-3
lines changed

8 files changed

+138
-3
lines changed

src/Symfony/Component/Mailer/Bridge/Brevo/Webhook/BrevoRequestParser.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ protected function getRequestMatcher(): RequestMatcherInterface
3737
new IsJsonRequestMatcher(),
3838
// https://developers.brevo.com/docs/how-to-use-webhooks#securing-your-webhooks
3939
// localhost is added for testing
40-
new IpsRequestMatcher(['185.107.232.1/24', '1.179.112.1/20', '127.0.0.1']),
40+
new IpsRequestMatcher(['185.107.232.1/24', '1.179.112.1/20', '172.246.240.1/20', '127.0.0.1']),
4141
]);
4242
}
4343

src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
1515
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
16+
use Symfony\Component\Serializer\Exception\LogicException;
1617
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface;
1718
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
1819
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
@@ -181,7 +182,22 @@ protected function setAttributeValue(object $object, string $attribute, mixed $v
181182
return;
182183
}
183184

184-
$reflectionProperty->setValue($object, $value);
185+
if (!$reflectionProperty->isReadOnly()) {
186+
$reflectionProperty->setValue($object, $value);
187+
188+
return;
189+
}
190+
191+
if (!$reflectionProperty->isInitialized($object)) {
192+
$declaringClass = $reflectionProperty->getDeclaringClass();
193+
$declaringClass->getProperty($reflectionProperty->getName())->setValue($object, $value);
194+
195+
return;
196+
}
197+
198+
if ($reflectionProperty->getValue($object) !== $value) {
199+
throw new LogicException(\sprintf('Attempting to change readonly property "%s"::$%s.', $object::class, $reflectionProperty->getName()));
200+
}
185201
}
186202

187203
/**
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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+
namespace Symfony\Component\Serializer\Tests\Fixtures;
13+
14+
class BookDummy
15+
{
16+
public function __construct(
17+
public private(set) string $title,
18+
public protected(set) string $author,
19+
protected private(set) int $pubYear,
20+
) {
21+
}
22+
23+
public function getPubYear(): int
24+
{
25+
return $this->pubYear;
26+
}
27+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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+
namespace Symfony\Component\Serializer\Tests\Fixtures;
13+
14+
readonly class ChildClassDummy extends ParentClassDummy
15+
{
16+
public string $childProp;
17+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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+
namespace Symfony\Component\Serializer\Tests\Fixtures;
13+
14+
readonly class ParentClassDummy
15+
{
16+
private string $parentProp;
17+
18+
public function getParentProp(): string
19+
{
20+
return $this->parentProp;
21+
}
22+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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+
namespace Symfony\Component\Serializer\Tests\Fixtures;
13+
14+
class SpecialBookDummy extends BookDummy
15+
{
16+
}

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@
3030
use Symfony\Component\Serializer\SerializerInterface;
3131
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\GroupDummy;
3232
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\GroupDummyChild;
33+
use Symfony\Component\Serializer\Tests\Fixtures\ChildClassDummy;
3334
use Symfony\Component\Serializer\Tests\Fixtures\Dummy;
3435
use Symfony\Component\Serializer\Tests\Fixtures\Php74Dummy;
3536
use Symfony\Component\Serializer\Tests\Fixtures\PropertyCircularReferenceDummy;
3637
use Symfony\Component\Serializer\Tests\Fixtures\PropertySiblingHolder;
38+
use Symfony\Component\Serializer\Tests\Fixtures\SpecialBookDummy;
3739
use Symfony\Component\Serializer\Tests\Normalizer\Features\CacheableObjectAttributesTestTrait;
3840
use Symfony\Component\Serializer\Tests\Normalizer\Features\CallbacksTestTrait;
3941
use Symfony\Component\Serializer\Tests\Normalizer\Features\CircularReferenceTestTrait;
@@ -176,6 +178,39 @@ public function testDenormalize()
176178
$this->assertEquals('bar', $obj->getBar());
177179
}
178180

181+
/**
182+
* @requires PHP 8.2
183+
*/
184+
public function testDenormalizeWithReadOnlyClass()
185+
{
186+
/** @var ChildClassDummy $object */
187+
$object = $this->normalizer->denormalize(
188+
['parentProp' => 'parentProp', 'childProp' => 'childProp'],
189+
ChildClassDummy::class,
190+
'any'
191+
);
192+
193+
$this->assertSame('parentProp', $object->getParentProp());
194+
$this->assertSame('childProp', $object->childProp);
195+
}
196+
197+
/**
198+
* @requires PHP 8.4
199+
*/
200+
public function testDenormalizeWithAsymmetricPropertyVisibility()
201+
{
202+
/** @var SpecialBookDummy $object */
203+
$object = $this->normalizer->denormalize(
204+
['title' => 'life', 'author' => 'Santiago San Martin', 'pubYear' => 2000],
205+
SpecialBookDummy::class,
206+
'any'
207+
);
208+
209+
$this->assertSame('life', $object->title);
210+
$this->assertSame('Santiago San Martin', $object->author);
211+
$this->assertSame(2000, $object->getPubYear());
212+
}
213+
179214
public function testNormalizeWithParentClass()
180215
{
181216
$group = new GroupDummyChild();

src/Symfony/Component/VarExporter/ProxyHelper.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,9 @@ public static function exportType(\ReflectionFunctionAbstract|\ReflectionPropert
477477
return '';
478478
}
479479
if (null === $glue) {
480-
return (!$noBuiltin && $type->allowsNull() && !\in_array($name, ['mixed', 'null'], true) ? '?' : '').$types[0];
480+
$defaultNull = $owner instanceof \ReflectionParameter && 'NULL' === rtrim(substr(explode('$'.$owner->name.' = ', (string) $owner, 2)[1] ?? '', 0, -2));
481+
482+
return (!$noBuiltin && ($type->allowsNull() || $defaultNull) && !\in_array($name, ['mixed', 'null'], true) ? '?' : '').$types[0];
481483
}
482484
sort($types);
483485

0 commit comments

Comments
 (0)