391 Notification refactorings (#441)

* Refactor notifications to allow easier plugins

* Notification refactoring

* Formatting

* Move news to NewsService; cleanup of events

* More refactoring; added send email out for news item and the template

* Formatting

* Formatting
This commit is contained in:
Nabeel S
2019-11-20 10:16:01 -05:00
committed by GitHub
parent 02973a0f22
commit ea3ab21beb
66 changed files with 754 additions and 718 deletions

View File

@@ -1,61 +0,0 @@
<?php
namespace App\Notifications\Admin;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class UserRegistered extends Notification implements ShouldQueue
{
use Queueable;
private $user;
/**
* Create a new notification instance.
*
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address'))
->markdown('mail.admin.user.registered')
->subject('A new user registered')
->with(['user' => $this->user]);
}
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Log;
class BaseNotification extends Notification implements ShouldQueue
{
use Queueable;
public $channels = [];
public function __construct()
{
// Look in the notifications.channels config and see where this particular
// notification can go. Map it to $channels
$klass = get_class($this);
$notif_config = config('notifications.channels', []);
if (!array_key_exists($klass, $notif_config)) {
Log::error('Notification type '.$klass.' missing from notifications config');
return;
}
$this->channels = $notif_config[$klass];
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return $this->channels;
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace App\Notifications\Channels;
use Illuminate\Notifications\Messages\MailMessage;
trait MailChannel
{
private $mailSubject;
private $mailTemplate;
private $mailTemplateArgs;
/**
* Set the arguments for the toMail() method
*
* @param string $subject Email subject
* @param string $template Markdown template to use
* @param array $args Arguments to pass to the template
*/
public function setMailable($subject, $template, $args)
{
$this->mailSubject = $subject;
$this->mailTemplate = $template;
$this->mailTemplateArgs = $args;
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address', 'no-reply@phpvms.net'))
->subject($this->mailSubject)
->markdown($this->mailTemplate, $this->mailTemplateArgs);
}
}

View File

@@ -0,0 +1,176 @@
<?php
namespace App\Notifications;
use App\Contracts\Listener;
use App\Events\NewsAdded;
use App\Events\PirepAccepted;
use App\Events\PirepFiled;
use App\Events\PirepRejected;
use App\Events\UserRegistered;
use App\Events\UserStateChanged;
use App\Models\Enums\UserState;
use App\Models\User;
use App\Notifications\Messages\PirepSubmitted;
use App\Notifications\Messages\UserPending;
use App\Notifications\Messages\UserRejected;
use App\Notifications\Notifiables\Broadcast;
use Exception;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
/**
* Listen for different events and map them to different notifications
*/
class EventHandler extends Listener
{
private static $broadcastNotifyable;
public static $callbacks = [
PirepAccepted::class => 'onPirepAccepted',
PirepFiled::class => 'onPirepFile',
PirepRejected::class => 'onPirepRejected',
UserRegistered::class => 'onUserRegister',
UserStateChanged::class => 'onUserStateChange',
];
public function __construct()
{
static::$broadcastNotifyable = app(Broadcast::class);
}
/**
* Send a notification to all of the admins
*
* @param \Illuminate\Notifications\Notification $notification
*/
protected function notifyAdmins($notification)
{
$admin_users = User::whereRoleIs('admin')->get();
try {
Notification::send($admin_users, $notification);
} catch (Exception $e) {
Log::emergency('Error emailing admins, malformed email='.$e->getMessage());
}
}
/**
* @param User $user
* @param \Illuminate\Notifications\Notification $notification
*/
protected function notifyUser($user, $notification)
{
try {
$user->notify($notification);
} catch (Exception $e) {
Log::emergency('Error emailing admins, malformed email='.$e->getMessage());
}
}
/**
* Send a notification to all users
*
* @param $notification
*/
protected function notifyAllUsers($notification)
{
$users = User::all()->get();
try {
Notification::send($users, $notification);
} catch (Exception $e) {
Log::emergency('Error emailing admins, malformed email='.$e->getMessage());
}
}
/**
* Send an email when the user registered
*
* @param UserRegistered $event
*/
public function onUserRegister(UserRegistered $event): void
{
Log::info('NotificationEvents::onUserRegister: '
.$event->user->ident.' is '
.UserState::label($event->user->state).', sending active email');
/*
* Send all of the admins a notification that a new user registered
*/
$this->notifyAdmins(new Messages\AdminUserRegistered($event->user));
/*
* Send the user a confirmation email
*/
if ($event->user->state === UserState::ACTIVE) {
$this->notifyUser($event->user, new Messages\UserRegistered($event->user));
} elseif ($event->user->state === UserState::PENDING) {
$this->notifyUser($event->user, new UserPending($event->user));
}
}
/**
* When a user's state changes, send an email out
*
* @param UserStateChanged $event
*/
public function onUserStateChange(UserStateChanged $event): void
{
Log::info('NotificationEvents::onUserStateChange: New user state='.$event->user->state);
if ($event->old_state === UserState::PENDING) {
if ($event->user->state === UserState::ACTIVE) {
$this->notifyUser($event->user, new Messages\UserRegistered($event->user));
} elseif ($event->user->state === UserState::REJECTED) {
$this->notifyUser($event->user, new UserRejected($event->user));
}
} elseif ($event->old_state === UserState::ACTIVE) {
Log::info('User state change from active to ??');
}
}
/**
* Notify the admins that a new PIREP has been filed
*
* @param \App\Events\PirepFiled $event
*/
public function onPirepFile(PirepFiled $event): void
{
Log::info('NotificationEvents::onPirepFile: '.$event->pirep->id.' filed ');
$this->notifyAdmins(new PirepSubmitted($event->pirep));
}
/**
* Notify the user that their PIREP has been accepted
*
* @param \App\Events\PirepAccepted $event
*/
public function onPirepAccepted(PirepAccepted $event): void
{
Log::info('NotificationEvents::onPirepAccepted: '.$event->pirep->id.' accepted');
$this->notifyUser($event->pirep->user, new Messages\PirepAccepted($event->pirep));
}
/**
* Notify the user that their PIREP has been accepted
*
* @param \App\Events\PirepRejected $event
*/
public function onPirepRejected(PirepRejected $event): void
{
Log::info('NotificationEvents::onPirepRejected: '.$event->pirep->id.' rejected');
$this->notifyUser($event->pirep->user, new Messages\PirepRejected($event->pirep));
}
/**
* Notify all users of a news event
*
* @param \App\Events\NewsAdded $event
*/
public function onNewsAdded(NewsAdded $event): void
{
Log::info('NotificationEvents::onNewsAdded');
$this->notifyAllUsers(new Messages\NewsAdded($event->news));
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace App\Notifications\Messages;
use App\Models\User;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
class AdminUserRegistered extends BaseNotification
{
use MailChannel;
private $user;
/**
* Create a new notification instance.
*
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
parent::__construct();
$this->user = $user;
$this->setMailable(
'A new user registered',
'notifications.mail.admin.user.registered',
['user' => $user]
);
}
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Notifications\Messages;
use App\Models\News;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
class NewsAdded extends BaseNotification
{
use MailChannel;
private $news;
public function __construct(News $news)
{
parent::__construct();
$this->news = $news;
$this->setMailable(
$news->subject,
'notifications.mail.news',
['news' => $news]
);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'news_id' => $this->news->id,
];
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace App\Notifications\Messages;
use App\Models\Pirep;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
/**
* Send the PIREP accepted message to a particular user
*/
class PirepAccepted extends BaseNotification
{
use MailChannel;
private $pirep;
/**
* Create a new notification instance.
*
* @param \App\Models\Pirep $pirep
*/
public function __construct(Pirep $pirep)
{
parent::__construct();
$this->pirep = $pirep;
$this->setMailable(
'PIREP Accepted!',
'notifications.mail.pirep.accepted',
['pirep' => $this->pirep]
);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'pirep_id' => $this->pirep->id,
'user_id' => $this->pirep->user_id,
];
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace App\Notifications\Messages;
use App\Models\Pirep;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
class PirepRejected extends BaseNotification
{
use MailChannel;
private $pirep;
/**
* Create a new notification instance.
*
* @param \App\Models\Pirep $pirep
*/
public function __construct(Pirep $pirep)
{
parent::__construct();
$this->pirep = $pirep;
$this->setMailable(
'PIREP Rejected!',
'notifications.mail.pirep.rejected',
['pirep' => $this->pirep]
);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'pirep_id' => $this->pirep->id,
'user_id' => $this->pirep->user_id,
];
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace App\Notifications\Messages;
use App\Models\Pirep;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
class PirepSubmitted extends BaseNotification
{
use MailChannel;
private $pirep;
/**
* Create a new notification instance.
*
* @param \App\Models\Pirep $pirep
*/
public function __construct(Pirep $pirep)
{
parent::__construct();
$this->pirep = $pirep;
$this->setMailable(
'New PIREP Submitted',
'notifications.mail.admin.pirep.submitted',
['pirep' => $this->pirep]
);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'pirep_id' => $this->pirep->id,
'user_id' => $this->pirep->user_id,
];
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace App\Notifications\Messages;
use App\Models\User;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
class UserPending extends BaseNotification
{
use MailChannel;
private $user;
/**
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
$this->user = $user;
$this->setMailable(
'Your registration is pending',
'notifications.mail.user.pending',
['user' => $this->user]
);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace App\Notifications\Messages;
use App\Models\User;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
class UserRegistered extends BaseNotification
{
use MailChannel;
private $user;
/**
* Create a new notification instance.
*
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
parent::__construct();
$this->user = $user;
$this->setMailable(
'Welcome to '.config('app.name').'!',
'notifications.mail.user.registered',
['user' => $this->user]
);
}
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace App\Notifications\Messages;
use App\Models\User;
use App\Notifications\BaseNotification;
use App\Notifications\Channels\MailChannel;
class UserRejected extends BaseNotification
{
use MailChannel;
private $user;
/**
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
parent::__construct();
$this->user = $user;
$this->setMailable(
'Your registration has been denied',
'notifications.mail.user.rejected',
['user' => $this->user]
);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -1,6 +1,6 @@
<?php
namespace App\Notifications;
namespace App\Notifications\Notifiables;
use Illuminate\Notifications\Notifiable;

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Notifications\Notifiables;
use Illuminate\Notifications\Notifiable;
/**
* These are notifications that get broadcasted, not to a single person
* (e.g, on Discord, Slack or Telegram or something)
*
* $notifyable = app(Broadcast::class);
* $notifyable->notify($eventclass);
*/
class Broadcast
{
use Notifiable;
/**
* Routing for Discord - the public channel ID that's used
*/
public function routeNotificationForDiscord()
{
return setting('notifications.discord_public_channel_id');
}
}

View File

@@ -1,68 +0,0 @@
<?php
namespace App\Notifications;
use App\Models\Pirep;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class PirepAccepted extends Notification implements ShouldQueue
{
use Queueable;
private $pirep;
/**
* Create a new notification instance.
*
* @param \App\Models\Pirep $pirep
*/
public function __construct(Pirep $pirep)
{
$this->pirep = $pirep;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address', 'no-reply@phpvms.net'))
->subject('PIREP Accepted!')
->markdown('mail.pirep.accepted', ['pirep' => $this->pirep]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'pirep_id' => $this->pirep->id,
'user_id' => $this->pirep->user_id,
];
}
}

View File

@@ -1,68 +0,0 @@
<?php
namespace App\Notifications;
use App\Models\Pirep;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class PirepRejected extends Notification implements ShouldQueue
{
use Queueable;
private $pirep;
/**
* Create a new notification instance.
*
* @param \App\Models\Pirep $pirep
*/
public function __construct(Pirep $pirep)
{
$this->pirep = $pirep;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address', 'no-reply@phpvms.net'))
->subject('PIREP Rejected!')
->markdown('mail.pirep.rejected', ['pirep' => $this->pirep]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'pirep_id' => $this->pirep->id,
'user_id' => $this->pirep->user_id,
];
}
}

View File

@@ -1,68 +0,0 @@
<?php
namespace App\Notifications;
use App\Models\Pirep;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class PirepSubmitted extends Notification implements ShouldQueue
{
use Queueable;
private $pirep;
/**
* Create a new notification instance.
*
* @param \App\Models\Pirep $pirep
*/
public function __construct(Pirep $pirep)
{
$this->pirep = $pirep;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address', 'no-reply@phpvms.net'))
->subject('New PIREP Submitted')
->markdown('mail.admin.pirep.submitted', ['pirep' => $this->pirep]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'pirep_id' => $this->pirep->id,
'user_id' => $this->pirep->user_id,
];
}
}

View File

@@ -1,65 +0,0 @@
<?php
namespace App\Notifications;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class UserPending extends Notification implements ShouldQueue
{
use Queueable;
private $user;
/**
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address', 'no-reply@phpvms.net'))
->subject('Your registration is pending')
->markdown('mail.user.pending', ['user' => $this->user]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -1,60 +0,0 @@
<?php
namespace App\Notifications;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class UserRegistered extends Notification implements ShouldQueue
{
use Queueable;
private $user;
/**
* Create a new notification instance.
*
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address', 'no-reply@phpvms.net'))
->subject('Welcome to '.config('app.name').'!')
->markdown('mail.user.registered', ['user' => $this->user]);
}
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -1,65 +0,0 @@
<?php
namespace App\Notifications;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class UserRejected extends Notification implements ShouldQueue
{
use Queueable;
private $user;
/**
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage())
->from(config('mail.from.address', 'no-reply@phpvms.net'))
->subject('Your registration has been denied')
->markdown('mail.user.rejected', ['user' => $this->user]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}