Skip to content

Commit 32db679

Browse files
feature symfony#61423 [Mime] Deprecate implementing __sleep/wakeup() on AbstractPart implementations (nicolas-grekas)
This PR was merged into the 7.4 branch. Discussion ---------- [Mime] Deprecate implementing `__sleep/wakeup()` on `AbstractPart` implementations | Q | A | ------------- | --- | Branch? | 7.4 | Bug fix? | no | New feature? | yes | Deprecations? | yes | Issues | - | License | MIT The last step to get rid of sleep/wakeup in 8.0 What a mess! Commits ------- 34e9408 [Mime] Deprecate implementing `__sleep/wakeup()` on `AbstractPart` implementations
2 parents f2acd82 + 34e9408 commit 32db679

File tree

20 files changed

+425
-17
lines changed

20 files changed

+425
-17
lines changed

UPGRADE-7.4.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ HttpKernel
5959
* Deprecate implementing `__sleep/wakeup()` on data collectors; use `__(un)serialize()` instead
6060
* Make `Profile` final and `Profiler::__sleep()` internal
6161

62+
Mime
63+
----
64+
65+
* Deprecate implementing `__sleep/wakeup()` on `AbstractPart` implementations; use `__(un)serialize()` instead
66+
6267
Security
6368
--------
6469

src/Symfony/Bridge/PhpUnit/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"php": ">=8.1.0"
2424
},
2525
"require-dev": {
26-
"symfony/deprecation-contracts": "^2.5|^3.0",
26+
"symfony/deprecation-contracts": "^2.5|^3",
2727
"symfony/error-handler": "^6.4.3|^7.0.3|^8.0"
2828
},
2929
"autoload": {

src/Symfony/Component/Cache/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"psr/cache": "^2.0|^3.0",
2626
"psr/log": "^1.1|^2|^3",
2727
"symfony/cache-contracts": "^3.6",
28-
"symfony/deprecation-contracts": "^2.5|^3.0",
28+
"symfony/deprecation-contracts": "^2.5|^3",
2929
"symfony/service-contracts": "^2.5|^3",
3030
"symfony/var-exporter": "^6.4|^7.0|^8.0"
3131
},

src/Symfony/Component/HttpFoundation/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
],
1818
"require": {
1919
"php": ">=8.2",
20-
"symfony/deprecation-contracts": "^2.5|^3.0",
20+
"symfony/deprecation-contracts": "^2.5|^3",
2121
"symfony/polyfill-mbstring": "~1.1",
2222
"symfony/polyfill-php83": "^1.27"
2323
},

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ protected function getCasters(): array
8686

8787
public function __serialize(): array
8888
{
89-
if (self::class === (new \ReflectionMethod($this, '__sleep'))->class) {
89+
if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) {
9090
return ['data' => $this->data];
9191
}
9292

@@ -108,7 +108,7 @@ public function __serialize(): array
108108

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

src/Symfony/Component/HttpKernel/Kernel.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ private function preBoot(): ContainerInterface
777777

778778
public function __serialize(): array
779779
{
780-
if (self::class === (new \ReflectionMethod($this, '__sleep'))->class) {
780+
if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) {
781781
return [
782782
'environment' => $this->environment,
783783
'debug' => $this->debug,
@@ -802,7 +802,7 @@ public function __serialize(): array
802802

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

src/Symfony/Component/Mime/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 `AbstractPart` implementations; use `__(un)serialize()` instead
8+
49
7.0
510
---
611

src/Symfony/Component/Mime/Part/AbstractPart.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,55 @@ abstract public function bodyToIterable(): iterable;
6262
abstract public function getMediaType(): string;
6363

6464
abstract public function getMediaSubtype(): string;
65+
66+
public function __serialize(): array
67+
{
68+
if (!method_exists($this, '__sleep')) {
69+
return ['headers' => $this->headers];
70+
}
71+
72+
trigger_deprecation('symfony/mime', '7.4', 'Implementing "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this));
73+
74+
$data = [];
75+
foreach ($this->__sleep() as $key) {
76+
try {
77+
if (($r = new \ReflectionProperty($this, $key))->isInitialized($this)) {
78+
$data[$key] = $r->getValue($this);
79+
}
80+
} catch (\ReflectionException) {
81+
$data[$key] = $this->$key;
82+
}
83+
}
84+
85+
return $data;
86+
}
87+
88+
public function __unserialize(array $data): void
89+
{
90+
if ($wakeup = method_exists($this, '__wakeup') && self::class === (new \ReflectionMethod($this, '__unserialize'))->class) {
91+
trigger_deprecation('symfony/mime', '7.4', 'Implementing "%s::__wakeup()" is deprecated, use "__unserialize()" instead.', get_debug_type($this));
92+
}
93+
94+
if (['headers'] === array_keys($data)) {
95+
$this->headers = $data['headers'];
96+
97+
if ($wakeup) {
98+
$this->__wakeup();
99+
}
100+
101+
return;
102+
}
103+
104+
trigger_deprecation('symfony/mime', '7.4', 'Passing more than just key "headers" to "%s::__unserialize()" is deprecated, populate properties in "%s::__unserialize()" instead.', self::class, get_debug_type($this));
105+
106+
\Closure::bind(function ($data) use ($wakeup) {
107+
foreach ($data as $key => $value) {
108+
$this->{("\0" === $key[0] ?? '') ? substr($key, 1 + strrpos($key, "\0")) : $key} = $value;
109+
}
110+
111+
if ($wakeup) {
112+
$this->__wakeup();
113+
}
114+
}, $this, static::class)($data);
115+
}
65116
}

src/Symfony/Component/Mime/Part/DataPart.php

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
*/
2020
class DataPart extends TextPart
2121
{
22-
/** @internal */
22+
/** @internal, to be removed in 8.0 */
2323
protected array $_parent;
2424

2525
private ?string $filename = null;
@@ -129,8 +129,86 @@ private function generateContentId(): string
129129
return bin2hex(random_bytes(16)).'@symfony';
130130
}
131131

132+
public function __serialize(): array
133+
{
134+
if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) {
135+
$parent = parent::__serialize();
136+
$headers = $parent['_headers'];
137+
unset($parent['_headers']);
138+
139+
return [
140+
'_headers' => $headers,
141+
'_parent' => $parent,
142+
'filename' => $this->filename,
143+
'mediaType' => $this->mediaType,
144+
];
145+
}
146+
147+
trigger_deprecation('symfony/mime', '7.4', 'Implementing "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this));
148+
149+
$data = [];
150+
foreach ($this->__sleep() as $key) {
151+
try {
152+
if (($r = new \ReflectionProperty($this, $key))->isInitialized($this)) {
153+
$data[$key] = $r->getValue($this);
154+
}
155+
} catch (\ReflectionException) {
156+
$data[$key] = $this->$key;
157+
}
158+
}
159+
160+
return $data;
161+
}
162+
163+
public function __unserialize(array $data): void
164+
{
165+
if ($wakeup = self::class !== (new \ReflectionMethod($this, '__wakeup'))->class && self::class === (new \ReflectionMethod($this, '__unserialize'))->class) {
166+
trigger_deprecation('symfony/mime', '7.4', 'Implementing "%s::__wakeup()" is deprecated, use "__unserialize()" instead.', get_debug_type($this));
167+
}
168+
169+
if (['_headers', '_parent', 'filename', 'mediaType'] === array_keys($data)) {
170+
parent::__unserialize(['_headers' => $data['_headers'], ...$data['_parent']]);
171+
$this->filename = $data['filename'];
172+
$this->mediaType = $data['mediaType'];
173+
174+
if ($wakeup) {
175+
$this->__wakeup();
176+
}
177+
178+
return;
179+
}
180+
181+
if (["\0*\0_headers", "\0*\0_parent", "\0".self::class."\0filename", "\0".self::class."\0mediaType"] === array_keys($data)) {
182+
parent::__unserialize(['_headers' => $data["\0*\0_headers"], ...$data["\0*\0_parent"]]);
183+
$this->filename = $data["\0".self::class."\0filename"];
184+
$this->mediaType = $data["\0".self::class."\0mediaType"];
185+
186+
if ($wakeup) {
187+
$this->__wakeup();
188+
}
189+
190+
return;
191+
}
192+
193+
trigger_deprecation('symfony/mime', '7.4', 'Passing extra keys to "%s::__unserialize()" is deprecated, populate properties in "%s::__unserialize()" instead.', self::class, get_debug_type($this));
194+
195+
\Closure::bind(function ($data) use ($wakeup) {
196+
foreach ($data as $key => $value) {
197+
$this->{("\0" === $key[0] ?? '') ? substr($key, 1 + strrpos($key, "\0")) : $key} = $value;
198+
}
199+
200+
if ($wakeup) {
201+
$this->__wakeup();
202+
}
203+
}, $this, static::class)($data);
204+
}
205+
206+
/**
207+
* @deprecated since Symfony 7.4, will be replaced by `__serialize()` in 8.0
208+
*/
132209
public function __sleep(): array
133210
{
211+
trigger_deprecation('symfony/mime', '7.4', 'Calling "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this));
134212
// converts the body to a string
135213
parent::__sleep();
136214

@@ -144,6 +222,9 @@ public function __sleep(): array
144222
return ['_headers', '_parent', 'filename', 'mediaType'];
145223
}
146224

225+
/**
226+
* @deprecated since Symfony 7.4, will be replaced by `__unserialize()` in 8.0
227+
*/
147228
public function __wakeup(): void
148229
{
149230
$r = new \ReflectionProperty(AbstractPart::class, 'headers');

src/Symfony/Component/Mime/Part/MessagePart.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,78 @@ public function bodyToIterable(): iterable
5757
return $this->message->toIterable();
5858
}
5959

60+
public function __serialize(): array
61+
{
62+
if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) {
63+
return ['message' => $this->message];
64+
}
65+
66+
trigger_deprecation('symfony/mime', '7.4', 'Implementing "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this));
67+
68+
$data = [];
69+
foreach ($this->__sleep() as $key) {
70+
try {
71+
if (($r = new \ReflectionProperty($this, $key))->isInitialized($this)) {
72+
$data[$key] = $r->getValue($this);
73+
}
74+
} catch (\ReflectionException) {
75+
$data[$key] = $this->$key;
76+
}
77+
}
78+
79+
return $data;
80+
}
81+
82+
public function __unserialize(array $data): void
83+
{
84+
if ($wakeup = self::class !== (new \ReflectionMethod($this, '__wakeup'))->class && self::class === (new \ReflectionMethod($this, '__unserialize'))->class) {
85+
trigger_deprecation('symfony/mime', '7.4', 'Implementing "%s::__wakeup()" is deprecated, use "__unserialize()" instead.', get_debug_type($this));
86+
}
87+
88+
if (\in_array(array_keys($data), [['message'], ["\0".self::class."\0message"]], true)) {
89+
$this->message = $data['message'] ?? $data["\0".self::class."\0message"];
90+
91+
if ($wakeup) {
92+
$this->__wakeup();
93+
} else {
94+
$this->__construct($this->message);
95+
}
96+
97+
return;
98+
}
99+
100+
trigger_deprecation('symfony/mime', '7.4', 'Passing more than just key "message" to "%s::__unserialize()" is deprecated, populate properties in "%s::__unserialize()" instead.', self::class, get_debug_type($this));
101+
102+
\Closure::bind(function ($data) use ($wakeup) {
103+
foreach ($data as $key => $value) {
104+
$this->{("\0" === $key[0] ?? '') ? substr($key, 1 + strrpos($key, "\0")) : $key} = $value;
105+
}
106+
107+
if ($wakeup) {
108+
$this->__wakeup();
109+
} else {
110+
$this->__construct($this->message);
111+
}
112+
}, $this, static::class)($data);
113+
}
114+
115+
/**
116+
* @deprecated since Symfony 7.4, will be replaced by `__unserialize()` in 8.0
117+
*/
60118
public function __sleep(): array
61119
{
120+
trigger_deprecation('symfony/mime', '7.4', 'Calling "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this));
121+
62122
return ['message'];
63123
}
64124

125+
/**
126+
* @deprecated since Symfony 7.4, will be replaced by `__unserialize()` in 8.0
127+
*/
65128
public function __wakeup(): void
66129
{
130+
trigger_deprecation('symfony/mime', '7.4', 'Calling "%s::__wakeup()" is deprecated, use "__unserialize()" instead.', get_debug_type($this));
131+
67132
$this->__construct($this->message);
68133
}
69134
}

0 commit comments

Comments
 (0)