Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[10.x] Allow serialization of NotificationSent #47375

Merged
merged 4 commits into from
Jun 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 8 additions & 14 deletions src/Illuminate/Mail/Events/MessageSent.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,10 @@ public function __serialize()
{
$hasAttachments = collect($this->message->getAttachments())->isNotEmpty();

return $hasAttachments ? [
'sent' => base64_encode(serialize($this->sent)),
'data' => base64_encode(serialize($this->data)),
'hasAttachments' => true,
] : [
return [
'sent' => $this->sent,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This never needs to be base 64 encoded and serialized anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Admittedly, I don't know all of the use cases here, but my thinking is: if SentMessage is being base64_encoded for attachments when it is serialized, then there's no need to encode it again when MessageSent is being serialized.

Do you see a flaw in that thinking?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that could be true.

'data' => $this->data,
'hasAttachments' => false,
'data' => $hasAttachments ? base64_encode(serialize($this->data)) : $this->data,
'hasAttachments' => $hasAttachments,
];
}

Expand All @@ -65,13 +61,11 @@ public function __serialize()
*/
public function __unserialize(array $data)
{
if (isset($data['hasAttachments']) && $data['hasAttachments'] === true) {
$this->sent = unserialize(base64_decode($data['sent']));
$this->data = unserialize(base64_decode($data['data']));
} else {
$this->sent = $data['sent'];
$this->data = $data['data'];
}
$this->sent = $data['sent'];

$this->data = (($data['hasAttachments'] ?? false) === true)
? unserialize(base64_decode($data['data']))
: $data['data'];
}

/**
Expand Down
28 changes: 28 additions & 0 deletions src/Illuminate/Mail/SentMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,32 @@ public function __call($method, $parameters)
{
return $this->forwardCallTo($this->sentMessage, $method, $parameters);
}

/**
* Get the serializable representation of the object.
*
* @return array
*/
public function __serialize()
{
$hasAttachments = collect($this->sentMessage->getOriginalMessage()->getAttachments())->isNotEmpty();

return [
'hasAttachments' => $hasAttachments,
'sentMessage' => $hasAttachments ? base64_encode(serialize($this->sentMessage)) : $this->sentMessage,
];
}

/**
* Marshal the object from its serialized data.
*
* @param array $data
* @return void
*/
public function __unserialize(array $data)
{
$hasAttachments = ($data['hasAttachments'] ?? false) === true;

$this->sentMessage = $hasAttachments ? unserialize(base64_decode($data['sentMessage'])) : $data['sentMessage'];
}
}
Binary file added tests/Integration/Mail/Fixtures/blank_document.pdf
Binary file not shown.
78 changes: 78 additions & 0 deletions tests/Integration/Mail/SentMessageMailTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

namespace Illuminate\Tests\Integration\Mail;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Notifications\Events\NotificationSent;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notifiable;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Schema;
use Orchestra\Testbench\TestCase;

class SentMessageMailTest extends TestCase
{
public function setUp(): void
{
parent::setUp();

Schema::create('sent_message_users', function (Blueprint $table) {
$table->increments('id');
});
}

public function testDispatchesNotificationSent()
{
$notificationWasSent = false;

$user = SentMessageUser::create();

Event::listen(
NotificationSent::class,
function(NotificationSent $notification) use (&$notificationWasSent, $user) {
$notificationWasSent = true;
/**
* Confirm that NotificationSent can be serialized/unserialized as
* will happen if the listener implements ShouldQueue.
*/
/** @var NotificationSent $afterSerialization */
$afterSerialization = unserialize(serialize($notification));

$this->assertTrue($user->is($afterSerialization->notifiable));

$this->assertEqualsCanonicalizing($notification->notification, $afterSerialization->notification);
});

$user->notify(new SentMessageMailNotification());

$this->assertTrue($notificationWasSent);
}
}

class SentMessageUser extends Model
{
use Notifiable;

public $timestamps = false;
}


class SentMessageMailNotification extends Notification
{
public function via(): array
{
return ['mail'];
}

public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->line('Example notification with attachment.')
->attach(__DIR__ . '/Fixtures/blank_document.pdf', [
'as' => 'blank_document.pdf',
'mime' => 'application/pdf',
]);
}
}