Skip to content

Commit 8ac3fb5

Browse files
feature #61417 [String] Deprecate implementing __sleep/wakeup() on string implementations (nicolas-grekas)
This PR was merged into the 7.4 branch. Discussion ---------- [String] Deprecate implementing `__sleep/wakeup()` on string implementations | Q | A | ------------- | --- | Branch? | 7.4 | Bug fix? | no | New feature? | yes | Deprecations? | yes | Issues | - | License | MIT Similar to #61412 Commits ------- 467e172 [String] Deprecate implementing `__sleep/wakeup()` on string implementations
2 parents 25f216f + 467e172 commit 8ac3fb5

File tree

10 files changed

+159
-10
lines changed

10 files changed

+159
-10
lines changed

UPGRADE-7.4.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ Serializer
7171

7272
* Make `AttributeMetadata` and `ClassMetadata` final
7373

74+
String
75+
------
76+
77+
* Deprecate implementing `__sleep/wakeup()` on string implementations
78+
7479
Translation
7580
-----------
7681

src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,24 +108,30 @@ public function __serialize(): array
108108

109109
public function __unserialize(array $data): void
110110
{
111-
if (self::class !== (new \ReflectionMethod($this, '__wakeup'))->class) {
111+
if ($wakeup = self::class !== (new \ReflectionMethod($this, '__wakeup'))->class) {
112112
trigger_deprecation('symfony/http-kernel', '7.4', 'Implementing "%s::__wakeup()" is deprecated, use "__unserialize()" instead.', get_debug_type($this));
113113
}
114114

115115
if (\in_array(array_keys($data), [['data'], ["\0*\0data"]], true)) {
116116
$this->data = $data['data'] ?? $data["\0*\0data"];
117117

118+
if ($wakeup) {
119+
$this->__wakeup();
120+
}
121+
118122
return;
119123
}
120124

121125
trigger_deprecation('symfony/http-kernel', '7.4', 'Passing more than just key "data" to "%s::__unserialize()" is deprecated, populate properties in "%s::__unserialize()" instead.', self::class, get_debug_type($this));
122126

123-
\Closure::bind(function ($data) {
127+
\Closure::bind(function ($data) use ($wakeup) {
124128
foreach ($data as $key => $value) {
125129
$this->{("\0" === $key[0] ?? '') ? substr($key, 1 + strrpos($key, "\0")) : $key} = $value;
126130
}
127131

128-
$this->__wakeup();
132+
if ($wakeup) {
133+
$this->__wakeup();
134+
}
129135
}, $this, static::class)($data);
130136
}
131137

@@ -136,6 +142,8 @@ public function __unserialize(array $data): void
136142
*/
137143
public function __sleep(): array
138144
{
145+
trigger_deprecation('symfony/http-kernel', '7.4', 'Calling "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this));
146+
139147
return ['data'];
140148
}
141149

@@ -146,6 +154,7 @@ public function __sleep(): array
146154
*/
147155
public function __wakeup(): void
148156
{
157+
trigger_deprecation('symfony/http-kernel', '7.4', 'Calling "%s::__wakeup()" is deprecated, use "__unserialize()" instead.', get_debug_type($this));
149158
}
150159

151160
/**

src/Symfony/Component/HttpKernel/Kernel.php

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -802,25 +802,46 @@ public function __serialize(): array
802802

803803
public function __unserialize(array $data): void
804804
{
805-
if (self::class !== (new \ReflectionMethod($this, '__wakeup'))->class) {
805+
if ($wakeup = self::class !== (new \ReflectionMethod($this, '__wakeup'))->class) {
806806
trigger_deprecation('symfony/http-kernel', '7.4', 'Implementing "%s::__wakeup()" is deprecated, use "__unserialize()" instead.', get_debug_type($this));
807807
}
808808

809809
if (\in_array(array_keys($data), [['environment', 'debug'], ["\0*\0environment", "\0*\0debug"]], true)) {
810-
$this->environment = $data['environment'] ?? $data["\0*\0environment"];
811-
$this->debug = $data['debug'] ?? $data["\0*\0debug"];
810+
$environment = $data['environment'] ?? $data["\0*\0environment"];
811+
$debug = $data['debug'] ?? $data["\0*\0debug"];
812+
813+
if (\is_object($environment) || \is_object($debug)) {
814+
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
815+
}
816+
817+
$this->environment = $environment;
818+
$this->debug = $debug;
819+
820+
if ($wakeup) {
821+
$this->__wakeup();
822+
} else {
823+
$this->__construct($environment, $debug);
824+
}
812825

813826
return;
814827
}
815828

816829
trigger_deprecation('symfony/http-kernel', '7.4', 'Passing more than just key "environment" and "debug" to "%s::__unserialize()" is deprecated, populate properties in "%s::__unserialize()" instead.', self::class, get_debug_type($this));
817830

818-
\Closure::bind(function ($data) {
831+
\Closure::bind(function ($data) use ($wakeup) {
819832
foreach ($data as $key => $value) {
820833
$this->{("\0" === $key[0] ?? '') ? substr($key, 1 + strrpos($key, "\0")) : $key} = $value;
821834
}
822835

823-
$this->__wakeup();
836+
if ($wakeup) {
837+
$this->__wakeup();
838+
} else {
839+
if (\is_object($this->environment) || \is_object($this->debug)) {
840+
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
841+
}
842+
843+
$this->__construct($this->environment, $this->debug);
844+
}
824845
}, $this, static::class)($data);
825846
}
826847

@@ -831,6 +852,8 @@ public function __unserialize(array $data): void
831852
*/
832853
public function __sleep(): array
833854
{
855+
trigger_deprecation('symfony/http-kernel', '7.4', 'Calling "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this));
856+
834857
return ['environment', 'debug'];
835858
}
836859

@@ -841,6 +864,8 @@ public function __sleep(): array
841864
*/
842865
public function __wakeup(): void
843866
{
867+
trigger_deprecation('symfony/http-kernel', '7.4', 'Calling "%s::__wakeup()" is deprecated, use "__unserialize()" instead.', get_debug_type($this));
868+
844869
if (\is_object($this->environment) || \is_object($this->debug)) {
845870
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
846871
}

src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ public function merge(AttributeMetadataInterface $attributeMetadata): void
219219
/**
220220
* @internal since Symfony 7.4, will be replaced by `__serialize()` in 8.0
221221
*
222-
* @final since Symfony 7.4
222+
* @final since Symfony 7.4, will be replaced by `__serialize()` in 8.0
223223
*/
224224
public function __sleep(): array
225225
{

src/Symfony/Component/Serializer/Mapping/ClassMetadata.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ public function setClassDiscriminatorMapping(?ClassDiscriminatorMapping $mapping
9696
/**
9797
* @internal since Symfony 7.4, will be replaced by `__serialize()` in 8.0
9898
*
99-
* @final since Symfony 7.4
99+
* @final since Symfony 7.4, will be replaced by `__serialize()` in 8.0
100100
*/
101101
public function __sleep(): array
102102
{

src/Symfony/Component/String/AbstractString.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,8 +706,37 @@ public function wordwrap(int $width = 75, string $break = "\n", bool $cut = fals
706706
return $str;
707707
}
708708

709+
public function __serialize(): array
710+
{
711+
if (self::class === (new \ReflectionMethod($this, '__sleep'))->class) {
712+
return ['string' => $this->string];
713+
}
714+
715+
trigger_deprecation('symfony/string', '7.4', 'Implementing "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this));
716+
717+
$data = [];
718+
foreach ($this->__sleep() as $key) {
719+
try {
720+
if (($r = new \ReflectionProperty($this, $key))->isInitialized($this)) {
721+
$data[$key] = $r->getValue($this);
722+
}
723+
} catch (\ReflectionException) {
724+
$data[$key] = $this->$key;
725+
}
726+
}
727+
728+
return $data;
729+
}
730+
731+
/**
732+
* @internal since Symfony 7.4, will be removed in 8.0
733+
*
734+
* @final since Symfony 7.4, will be removed in 8.0
735+
*/
709736
public function __sleep(): array
710737
{
738+
trigger_deprecation('symfony/string', '7.4', 'Calling "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this));
739+
711740
return ['string'];
712741
}
713742

src/Symfony/Component/String/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.4
5+
---
6+
7+
* Deprecate implementing `__sleep/wakeup()` on string implementations
8+
49
7.3
510
---
611

src/Symfony/Component/String/LazyString.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,35 @@ public function __toString(): string
101101
}
102102
}
103103

104+
public function __serialize(): array
105+
{
106+
if (self::class === (new \ReflectionMethod($this, '__sleep'))->class) {
107+
$this->__toString();
108+
109+
return ['value' => $this->value];
110+
}
111+
112+
trigger_deprecation('symfony/string', '7.4', 'Implementing "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this));
113+
114+
$data = [];
115+
foreach ($this->__sleep() as $key) {
116+
try {
117+
if (($r = new \ReflectionProperty($this, $key))->isInitialized($this)) {
118+
$data[$key] = $r->getValue($this);
119+
}
120+
} catch (\ReflectionException) {
121+
$data[$key] = $this->$key;
122+
}
123+
}
124+
125+
return $data;
126+
}
127+
128+
/**
129+
* @internal since Symfony 7.4, will be removed in 8.0
130+
*
131+
* @final since Symfony 7.4, will be removed in 8.0
132+
*/
104133
public function __sleep(): array
105134
{
106135
$this->__toString();

src/Symfony/Component/String/UnicodeString.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,8 +366,54 @@ public function startsWith(string|iterable|AbstractString $prefix): bool
366366
return $prefix === $grapheme;
367367
}
368368

369+
public function __unserialize(array $data): void
370+
{
371+
if ($wakeup = self::class !== (new \ReflectionMethod($this, '__wakeup'))->class) {
372+
trigger_deprecation('symfony/string', '7.4', 'Implementing "%s::__wakeup()" is deprecated, use "__unserialize()" instead.', get_debug_type($this));
373+
}
374+
375+
try {
376+
if (\in_array(array_keys($data), [['string'], ["\0*\0string"]], true)) {
377+
$this->string = $data['string'] ?? $data["\0*\0string"];
378+
379+
if ($wakeup) {
380+
$this->__wakeup();
381+
}
382+
383+
return;
384+
}
385+
386+
trigger_deprecation('symfony/string', '7.4', 'Passing more than just key "string" to "%s::__unserialize()" is deprecated, populate properties in "%s::__unserialize()" instead.', self::class, get_debug_type($this));
387+
388+
\Closure::bind(function ($data) use ($wakeup) {
389+
foreach ($data as $key => $value) {
390+
$this->{("\0" === $key[0] ?? '') ? substr($key, 1 + strrpos($key, "\0")) : $key} = $value;
391+
}
392+
393+
if ($wakeup) {
394+
$this->__wakeup();
395+
}
396+
}, $this, static::class)($data);
397+
} finally {
398+
if (!$wakeup) {
399+
if (!\is_string($this->string)) {
400+
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
401+
}
402+
403+
normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string);
404+
}
405+
}
406+
}
407+
408+
/**
409+
* @internal since Symfony 7.4, will be removed in 8.0
410+
*
411+
* @final since Symfony 7.4, will be removed in 8.0
412+
*/
369413
public function __wakeup(): void
370414
{
415+
trigger_deprecation('symfony/string', '7.4', 'Calling "%s::__wakeup()" is deprecated, use "__unserialize()" instead.', get_debug_type($this));
416+
371417
if (!\is_string($this->string)) {
372418
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
373419
}

src/Symfony/Component/String/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
],
1818
"require": {
1919
"php": ">=8.2",
20+
"symfony/deprecation-contracts": "^2.5|^3.0",
2021
"symfony/polyfill-ctype": "~1.8",
2122
"symfony/polyfill-intl-grapheme": "~1.33",
2223
"symfony/polyfill-intl-normalizer": "~1.0",

0 commit comments

Comments
 (0)