diff --git a/framework/core/src/Notification/Blueprint/AbstractBlueprint.php b/framework/core/src/Notification/Blueprint/AbstractBlueprint.php new file mode 100644 index 000000000..23eb893d5 --- /dev/null +++ b/framework/core/src/Notification/Blueprint/AbstractBlueprint.php @@ -0,0 +1,23 @@ + static::getType(), + 'from_user_id' => ($fromUser = $this->getFromUser()) ? $fromUser->id : null, + 'subject_id' => ($subject = $this->getSubject()) ? $subject->getKey() : null, + 'data' => ($data = $this->getData()) ? json_encode($data) : null + ]; + } +} diff --git a/framework/core/src/Notification/Blueprint/BlueprintInterface.php b/framework/core/src/Notification/Blueprint/BlueprintInterface.php index 68b1d8553..38f5ed060 100644 --- a/framework/core/src/Notification/Blueprint/BlueprintInterface.php +++ b/framework/core/src/Notification/Blueprint/BlueprintInterface.php @@ -9,6 +9,9 @@ namespace Flarum\Notification\Blueprint; +use Flarum\Database\AbstractModel; +use Flarum\User\User; + /** * A notification BlueprintInterface, when instantiated, represents a notification about * something. The blueprint is used by the NotificationSyncer to commit the @@ -19,14 +22,14 @@ interface BlueprintInterface /** * Get the user that sent the notification. * - * @return \Flarum\User\User|null + * @return User|null */ public function getFromUser(); /** * Get the model that is the subject of this activity. * - * @return \Flarum\Database\AbstractModel|null + * @return AbstractModel|null */ public function getSubject(); diff --git a/framework/core/src/Notification/Event/Notifying.php b/framework/core/src/Notification/Event/Notifying.php new file mode 100644 index 000000000..5fb3ad5b2 --- /dev/null +++ b/framework/core/src/Notification/Event/Notifying.php @@ -0,0 +1,39 @@ +blueprint = $blueprint; + $this->users = &$users; + } +} diff --git a/framework/core/src/Notification/Event/Sending.php b/framework/core/src/Notification/Event/Sending.php index 4484cddc2..de2e1ca6e 100644 --- a/framework/core/src/Notification/Event/Sending.php +++ b/framework/core/src/Notification/Event/Sending.php @@ -23,7 +23,7 @@ class Sending /** * The users that the notification will be sent to. * - * @var array + * @var array|int[] */ public $users; diff --git a/framework/core/src/Notification/Job/SendNotificationsJob.php b/framework/core/src/Notification/Job/SendNotificationsJob.php new file mode 100644 index 000000000..c1d329e18 --- /dev/null +++ b/framework/core/src/Notification/Job/SendNotificationsJob.php @@ -0,0 +1,73 @@ +blueprint = $blueprint; + $this->recipientIds = $recipientIds; + } + + public function handle(NotificationMailer $mailer) + { + $now = Carbon::now('utc')->toDateTimeString(); + $recipients = $this->recipientIds; + + event(new Sending($this->blueprint, $recipients)); + + $attributes = $this->blueprint->getAttributes(); + + Notification::insert( + array_map(function (User $user) use ($attributes, $now) { + return $attributes + [ + 'user_id' => $user->id, + 'created_at' => $now + ]; + }, $recipients) + ); + + event(new Notifying($this->blueprint, $recipients)); + + if ($this->blueprint instanceof MailableInterface) { + $this->email($mailer, $this->blueprint, $recipients); + } + } + + protected function email(NotificationMailer $mailer, MailableInterface $blueprint, array $recipients) + { + foreach ($recipients as $user) { + if ($user->shouldEmail($blueprint::getType())) { + $mailer->send($blueprint, $user); + } + } + } +} diff --git a/framework/core/src/Notification/NotificationSyncer.php b/framework/core/src/Notification/NotificationSyncer.php index 12a987fec..5fd2ead77 100644 --- a/framework/core/src/Notification/NotificationSyncer.php +++ b/framework/core/src/Notification/NotificationSyncer.php @@ -9,10 +9,10 @@ namespace Flarum\Notification; -use Carbon\Carbon; use Flarum\Notification\Blueprint\BlueprintInterface; -use Flarum\Notification\Event\Sending; +use Flarum\Notification\Job\SendNotificationsJob; use Flarum\User\User; +use Illuminate\Contracts\Queue\Queue; /** * The Notification Syncer commits notification blueprints to the database, and @@ -42,20 +42,16 @@ class NotificationSyncer protected $notifications; /** - * @var NotificationMailer + * @var Queue */ - protected $mailer; + protected $queue; - /** - * @param NotificationRepository $notifications - * @param NotificationMailer $mailer - */ public function __construct( NotificationRepository $notifications, - NotificationMailer $mailer + Queue $queue ) { $this->notifications = $notifications; - $this->mailer = $mailer; + $this->queue = $queue; } /** @@ -69,7 +65,7 @@ class NotificationSyncer */ public function sync(Blueprint\BlueprintInterface $blueprint, array $users) { - $attributes = $this->getAttributes($blueprint); + $attributes = $blueprint->getAttributes(); // Find all existing notification records in the database matching this // blueprint. We will begin by assuming that they all need to be @@ -87,7 +83,7 @@ class NotificationSyncer continue; } - $existing = $toDelete->first(function ($notification, $i) use ($user) { + $existing = $toDelete->first(function ($notification) use ($user) { return $notification->user_id === $user->id; }); @@ -115,7 +111,7 @@ class NotificationSyncer // receiving this notification for the first time (we know because they // didn't have a record in the database). if (count($newRecipients)) { - $this->sendNotifications($blueprint, $newRecipients); + $this->queue->push(new SendNotificationsJob($blueprint, $newRecipients)); } } @@ -127,7 +123,7 @@ class NotificationSyncer */ public function delete(BlueprintInterface $blueprint) { - Notification::where($this->getAttributes($blueprint))->update(['is_deleted' => true]); + Notification::where($blueprint->getAttributes())->update(['is_deleted' => true]); } /** @@ -138,7 +134,7 @@ class NotificationSyncer */ public function restore(BlueprintInterface $blueprint) { - Notification::where($this->getAttributes($blueprint))->update(['is_deleted' => false]); + Notification::where($blueprint->getAttributes())->update(['is_deleted' => false]); } /** @@ -158,50 +154,6 @@ class NotificationSyncer static::$onePerUser = false; } - /** - * Create a notification record and send an email (depending on user - * preference) from a blueprint to a list of recipients. - * - * @param \Flarum\Notification\Blueprint\BlueprintInterface $blueprint - * @param User[] $recipients - */ - protected function sendNotifications(Blueprint\BlueprintInterface $blueprint, array $recipients) - { - $now = Carbon::now('utc')->toDateTimeString(); - - event(new Sending($blueprint, $recipients)); - - $attributes = $this->getAttributes($blueprint); - - Notification::insert( - array_map(function (User $user) use ($attributes, $now) { - return $attributes + [ - 'user_id' => $user->id, - 'created_at' => $now - ]; - }, $recipients) - ); - - if ($blueprint instanceof MailableInterface) { - $this->mailNotifications($blueprint, $recipients); - } - } - - /** - * Mail a notification to a list of users. - * - * @param MailableInterface $blueprint - * @param User[] $recipients - */ - protected function mailNotifications(MailableInterface $blueprint, array $recipients) - { - foreach ($recipients as $user) { - if ($user->shouldEmail($blueprint::getType())) { - $this->mailer->send($blueprint, $user); - } - } - } - /** * Set the deleted status of a list of notification records. * @@ -212,21 +164,4 @@ class NotificationSyncer { Notification::whereIn('id', $ids)->update(['is_deleted' => $isDeleted]); } - - /** - * Construct an array of attributes to be stored in a notification record in - * the database, given a notification blueprint. - * - * @param \Flarum\Notification\Blueprint\BlueprintInterface $blueprint - * @return array - */ - protected function getAttributes(Blueprint\BlueprintInterface $blueprint) - { - return [ - 'type' => $blueprint::getType(), - 'from_user_id' => ($fromUser = $blueprint->getFromUser()) ? $fromUser->id : null, - 'subject_id' => ($subject = $blueprint->getSubject()) ? $subject->id : null, - 'data' => ($data = $blueprint->getData()) ? json_encode($data) : null - ]; - } } diff --git a/framework/core/src/Queue/AbstractJob.php b/framework/core/src/Queue/AbstractJob.php new file mode 100644 index 000000000..6ec8235a8 --- /dev/null +++ b/framework/core/src/Queue/AbstractJob.php @@ -0,0 +1,22 @@ +