Skip to content

Commit c764081

Browse files
committed
[VarDumper] Fix serialization of stubs with null values
1 parent ca8c10d commit c764081

File tree

3 files changed

+71
-4
lines changed

3 files changed

+71
-4
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Symfony\Component\VarDumper\Cloner\Internal;
4+
5+
/**
6+
* Flags a typed property that has no default value.
7+
*
8+
* This dummy object is used to distinguish a property with a default value of null
9+
* from a property that is uninitialized by default.
10+
*
11+
* @internal
12+
*/
13+
enum NoDefault
14+
{
15+
case NoDefault;
16+
}

src/Symfony/Component/VarDumper/Cloner/Stub.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\VarDumper\Cloner;
1313

14+
use Symfony\Component\VarDumper\Cloner\Internal\NoDefault;
15+
1416
/**
1517
* Represents the main properties of a PHP variable.
1618
*
@@ -50,15 +52,20 @@ public function __sleep(): array
5052
$properties = [];
5153

5254
if (!isset(self::$defaultProperties[$c = static::class])) {
53-
self::$defaultProperties[$c] = get_class_vars($c);
55+
$reflection = new \ReflectionClass($c);
56+
self::$defaultProperties[$c] = [];
57+
58+
foreach ($reflection->getProperties() as $p) {
59+
if ($p->isStatic()) {
60+
continue;
61+
}
5462

55-
foreach ((new \ReflectionClass($c))->getStaticProperties() as $k => $v) {
56-
unset(self::$defaultProperties[$c][$k]);
63+
self::$defaultProperties[$c][$p->name] = $p->hasDefaultValue() ? $p->getDefaultValue() : ($p->hasType() ? NoDefault::NoDefault : null);
5764
}
5865
}
5966

6067
foreach (self::$defaultProperties[$c] as $k => $v) {
61-
if ($this->$k !== $v) {
68+
if ($v === NoDefault::NoDefault || $this->$k !== $v) {
6269
$properties[] = $k;
6370
}
6471
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace Symfony\Component\VarDumper\Tests\Cloner;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Symfony\Component\VarDumper\Cloner\Stub;
7+
8+
final class StubTest extends TestCase
9+
{
10+
public function testUnserializeNullValue()
11+
{
12+
$stub = new Stub();
13+
$stub->value = null;
14+
15+
$stub = unserialize(serialize($stub));
16+
17+
self::assertNull($stub->value);
18+
}
19+
20+
public function testUnserializeNullInTypedProperty()
21+
{
22+
$stub = new MyStub();
23+
$stub->myProp = null;
24+
25+
$stub = unserialize(serialize($stub));
26+
27+
self::assertNull($stub->myProp);
28+
}
29+
30+
public function testUninitializedStubPropertiesAreLeftUninitialized()
31+
{
32+
$stub = new MyStub();
33+
34+
$stub = unserialize(serialize($stub));
35+
36+
$r = new \ReflectionProperty(MyStub::class, 'myProp');
37+
self::assertFalse($r->isInitialized($stub));
38+
}
39+
}
40+
41+
final class MyStub extends Stub
42+
{
43+
public mixed $myProp;
44+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy