Skip to content

Commit

Permalink
Merge pull request #94 from feat/93/add-example-for-event-listener
Browse files Browse the repository at this point in the history
Add example for event listener
  • Loading branch information
FaisalBudiono authored Jan 2, 2024
2 parents 89571f3 + 2e2d04a commit 049c2da
Show file tree
Hide file tree
Showing 10 changed files with 454 additions and 5 deletions.
3 changes: 3 additions & 0 deletions app/Core/User/UserCore.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use App\Exceptions\Core\User\UserEmailDuplicatedException;
use App\Models\Permission\Enum\RoleName;
use App\Core\User\Enum\UserExceptionCode;
use App\Events\User\UserCreated;
use App\Models\User\User;
use App\Port\Core\User\CreateUserPort;
use App\Port\Core\User\DeleteUserPort;
Expand Down Expand Up @@ -48,6 +49,8 @@ public function create(CreateUserPort $request): User

$user->syncRoles(RoleName::NORMAL);

UserCreated::dispatch($user);

DB::commit();

return $user;
Expand Down
38 changes: 38 additions & 0 deletions app/Events/User/UserCreated.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace App\Events\User;

use App\Models\User\User;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class UserCreated
{
use Dispatchable, InteractsWithSockets, SerializesModels;

/**
* Create a new event instance.
*/
public function __construct(
public readonly User $user,
) {
//
}

/**
* Get the channels the event should broadcast on.
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [
new PrivateChannel('channel-name'),
];
}
}
28 changes: 28 additions & 0 deletions app/Listeners/User/SendWelcomeMail.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace App\Listeners\User;

use App\Events\User\UserCreated;
use App\Mail\User\WelcomeMail;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Mail;

class SendWelcomeMail implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct()
{
//
}

/**
* Handle the event.
*/
public function handle(UserCreated $event): void
{
Mail::send(new WelcomeMail($event->user));
}
}
63 changes: 63 additions & 0 deletions app/Mail/User/WelcomeMail.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

namespace App\Mail\User;

use App\Models\User\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class WelcomeMail extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;

/**
* Create a new message instance.
*/
public function __construct(
public readonly User $user,
) {
//
}

/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'Welcome Mail',
from: new Address('[email protected]', 'Mr. Example'),
to: [new Address($this->user->email, $this->user->name)],
);
}

/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
html: "mail.user.welcome-mail",
with: [
'name' => $this->user->name,
],
);
}

/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
}
9 changes: 4 additions & 5 deletions app/Providers/EventServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@

namespace App\Providers;

use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use App\Events\User\UserCreated;
use App\Listeners\User\SendWelcomeMail;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;

class EventServiceProvider extends ServiceProvider
{
Expand All @@ -17,8 +16,8 @@ class EventServiceProvider extends ServiceProvider
* @var array<class-string, array<int, class-string>>
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
UserCreated::class => [
SendWelcomeMail::class,
],
];

Expand Down
173 changes: 173 additions & 0 deletions resources/views/mail/user/welcome-mail.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">

<head>
<!--[if gte mso 9]>
<xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
<![endif]-->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="x-apple-disable-message-reformatting">
<!--[if !mso]><!-->
<meta http-equiv="X-UA-Compatible" content="IE=edge"><!--<![endif]-->
<title></title>

<style type="text/css">
@media only screen and (min-width: 520px) {
.u-row {
width: 500px !important;
}

.u-row .u-col {
vertical-align: top;
}

.u-row .u-col-100 {
width: 500px !important;
}

}

@media (max-width: 520px) {
.u-row-container {
max-width: 100% !important;
padding-left: 0px !important;
padding-right: 0px !important;
}

.u-row .u-col {
min-width: 320px !important;
max-width: 100% !important;
display: block !important;
}

.u-row {
width: 100% !important;
}

.u-col {
width: 100% !important;
}

.u-col>div {
margin: 0 auto;
}
}

body {
margin: 0;
padding: 0;
}

table,
tr,
td {
vertical-align: top;
border-collapse: collapse;
}

p {
margin: 0;
}

.ie-container table,
.mso-container table {
table-layout: fixed;
}

* {
line-height: inherit;
}

a[x-apple-data-detectors='true'] {
color: inherit !important;
text-decoration: none !important;
}

table,
td {
color: #000000;
}
</style>



</head>

<body class="clean-body u_body" style="margin: 0;padding: 0;-webkit-text-size-adjust: 100%;background-color: #e7e7e7;color: #000000">
<!--[if IE]><div class="ie-container"><![endif]-->
<!--[if mso]><div class="mso-container"><![endif]-->
<table style="border-collapse: collapse;table-layout: fixed;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;vertical-align: top;min-width: 320px;Margin: 0 auto;background-color: #e7e7e7;width:100%" cellpadding="0" cellspacing="0">
<tbody>
<tr style="vertical-align: top">
<td style="word-break: break-word;border-collapse: collapse !important;vertical-align: top">
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td align="center" style="background-color: #e7e7e7;"><![endif]-->



<div class="u-row-container" style="padding: 0px;background-color: transparent">
<div class="u-row" style="margin: 0 auto;min-width: 320px;max-width: 500px;overflow-wrap: break-word;word-wrap: break-word;word-break: break-word;background-color: transparent;">
<div style="border-collapse: collapse;display: table;width: 100%;height: 100%;background-color: transparent;">
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding: 0px;background-color: transparent;" align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:500px;"><tr style="background-color: transparent;"><![endif]-->

<!--[if (mso)|(IE)]><td align="center" width="500" style="width: 500px;padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;border-radius: 0px;-webkit-border-radius: 0px; -moz-border-radius: 0px;" valign="top"><![endif]-->
<div class="u-col u-col-100" style="max-width: 320px;min-width: 500px;display: table-cell;vertical-align: top;">
<div style="height: 100%;width: 100% !important;border-radius: 0px;-webkit-border-radius: 0px; -moz-border-radius: 0px;">
<!--[if (!mso)&(!IE)]><!-->
<div style="box-sizing: border-box; height: 100%; padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;border-radius: 0px;-webkit-border-radius: 0px; -moz-border-radius: 0px;"><!--<![endif]-->

<table style="font-family:arial,helvetica,sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody>
<tr>
<td style="overflow-wrap:break-word;word-break:break-word;padding:10px;font-family:arial,helvetica,sans-serif;" align="left">

<!--[if mso]><table width="100%"><tr><td><![endif]-->
<h1 style="margin: 0px; line-height: 140%; text-align: center; word-wrap: break-word; font-family: inherit; font-size: 22px; font-weight: 400;"><span>Unleash Your Creativity with Our Dummy</span></h1>
<!--[if mso]></td></tr></table><![endif]-->

</td>
</tr>
</tbody>
</table>

<table style="font-family:arial,helvetica,sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody>
<tr>
<td style="overflow-wrap:break-word;word-break:break-word;padding:10px;font-family:arial,helvetica,sans-serif;" align="left">

<div style="font-size: 14px; line-height: 140%; text-align: left; word-wrap: break-word;">
<p style="line-height: 140%;">Welcome, <?= $name ?></p>
</div>

</td>
</tr>
</tbody>
</table>

<!--[if (!mso)&(!IE)]><!-->
</div><!--<![endif]-->
</div>
</div>
<!--[if (mso)|(IE)]></td><![endif]-->
<!--[if (mso)|(IE)]></tr></table></td></tr></table><![endif]-->
</div>
</div>
</div>



<!--[if (mso)|(IE)]></td></tr></table><![endif]-->
</td>
</tr>
</tbody>
</table>
<!--[if mso]></div><![endif]-->
<!--[if IE]></div><![endif]-->
</body>

</html>
15 changes: 15 additions & 0 deletions tests/Unit/Core/User/UserCore/UserCore_Create_Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
use App\Models\Permission\Enum\RoleName;
use App\Models\Permission\Role;
use App\Core\User\Enum\UserExceptionCode;
use App\Events\User\UserCreated;
use App\Models\User\User;
use App\Port\Core\User\CreateUserPort;
use Database\Seeders\Base\RoleSeeder;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Hash;
use Mockery\MockInterface;
use PHPUnit\Framework\AssertionFailedError;
Expand All @@ -28,6 +30,8 @@ protected function setUp(): void
$this->mockRequest = $this->mock(CreateUserPort::class);

$this->seed(RoleSeeder::class);

Event::fake();
}

#[Test]
Expand Down Expand Up @@ -57,6 +61,8 @@ public function should_throw_error_when_user_email_already_registered(): void
UserExceptionCode::DUPLICATED->value,
));
$this->assertEquals($expectedException, $e);

Event::assertNotDispatched(UserCreated::class);
}
}

Expand Down Expand Up @@ -100,5 +106,14 @@ public function should_successfully_save_and_return_user_data(): void
'model_type' => User::class,
'role_id' => $role->id,
]);

Event::assertDispatched(
UserCreated::class,
function (UserCreated $event) use ($result) {
$this->assertTrue($event->user->is($result));

return true;
}
);
}
}
Loading

0 comments on commit 049c2da

Please sign in to comment.