mirror of
https://github.com/flarum/core.git
synced 2025-07-21 16:51:34 +02:00
Notifications into the queue
Forces notifications into a dedicated SendNotificationsJob and passed to the queue. - One static method re-used in the job ::getAttributes, is that okay or use a trait? - Do we want to use this solution and refactor into a better Hub after stable, postpone this implementation or use it in b11?
This commit is contained in:
committed by
Franz Liedke
parent
20bc1e50fc
commit
8cdcb25fcc
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* For detailed copyright and license information, please view the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Notification\Blueprint;
|
||||||
|
|
||||||
|
abstract class AbstractBlueprint implements BlueprintInterface
|
||||||
|
{
|
||||||
|
public function getAttributes(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'type' => 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
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@@ -9,6 +9,9 @@
|
|||||||
|
|
||||||
namespace Flarum\Notification\Blueprint;
|
namespace Flarum\Notification\Blueprint;
|
||||||
|
|
||||||
|
use Flarum\Database\AbstractModel;
|
||||||
|
use Flarum\User\User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A notification BlueprintInterface, when instantiated, represents a notification about
|
* A notification BlueprintInterface, when instantiated, represents a notification about
|
||||||
* something. The blueprint is used by the NotificationSyncer to commit the
|
* something. The blueprint is used by the NotificationSyncer to commit the
|
||||||
@@ -19,14 +22,14 @@ interface BlueprintInterface
|
|||||||
/**
|
/**
|
||||||
* Get the user that sent the notification.
|
* Get the user that sent the notification.
|
||||||
*
|
*
|
||||||
* @return \Flarum\User\User|null
|
* @return User|null
|
||||||
*/
|
*/
|
||||||
public function getFromUser();
|
public function getFromUser();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the model that is the subject of this activity.
|
* Get the model that is the subject of this activity.
|
||||||
*
|
*
|
||||||
* @return \Flarum\Database\AbstractModel|null
|
* @return AbstractModel|null
|
||||||
*/
|
*/
|
||||||
public function getSubject();
|
public function getSubject();
|
||||||
|
|
||||||
|
39
framework/core/src/Notification/Event/Notifying.php
Normal file
39
framework/core/src/Notification/Event/Notifying.php
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* For detailed copyright and license information, please view the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Notification\Event;
|
||||||
|
|
||||||
|
use Flarum\Notification\Blueprint\BlueprintInterface;
|
||||||
|
|
||||||
|
class Notifying
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The blueprint for the notification.
|
||||||
|
*
|
||||||
|
* @var BlueprintInterface
|
||||||
|
*/
|
||||||
|
public $blueprint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The users that the notification will be sent to.
|
||||||
|
*
|
||||||
|
* @var array|int[]
|
||||||
|
*/
|
||||||
|
public $users;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Flarum\Notification\Blueprint\BlueprintInterface $blueprint
|
||||||
|
* @param \Flarum\User\User[] $users
|
||||||
|
*/
|
||||||
|
public function __construct(BlueprintInterface $blueprint, array &$users)
|
||||||
|
{
|
||||||
|
$this->blueprint = $blueprint;
|
||||||
|
$this->users = &$users;
|
||||||
|
}
|
||||||
|
}
|
@@ -23,7 +23,7 @@ class Sending
|
|||||||
/**
|
/**
|
||||||
* The users that the notification will be sent to.
|
* The users that the notification will be sent to.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array|int[]
|
||||||
*/
|
*/
|
||||||
public $users;
|
public $users;
|
||||||
|
|
||||||
|
73
framework/core/src/Notification/Job/SendNotificationsJob.php
Normal file
73
framework/core/src/Notification/Job/SendNotificationsJob.php
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* For detailed copyright and license information, please view the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Notification\Job;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Flarum\Notification\Blueprint\BlueprintInterface;
|
||||||
|
use Flarum\Notification\Event\Notifying;
|
||||||
|
use Flarum\Notification\Event\Sending;
|
||||||
|
use Flarum\Notification\MailableInterface;
|
||||||
|
use Flarum\Notification\Notification;
|
||||||
|
use Flarum\Notification\NotificationMailer;
|
||||||
|
use Flarum\Queue\AbstractJob;
|
||||||
|
use Flarum\User\User;
|
||||||
|
|
||||||
|
class SendNotificationsJob extends AbstractJob
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var BlueprintInterface
|
||||||
|
*/
|
||||||
|
private $blueprint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $recipientIds;
|
||||||
|
|
||||||
|
public function __construct(BlueprintInterface $blueprint, array $recipientIds = [])
|
||||||
|
{
|
||||||
|
$this->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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -9,10 +9,10 @@
|
|||||||
|
|
||||||
namespace Flarum\Notification;
|
namespace Flarum\Notification;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Flarum\Notification\Blueprint\BlueprintInterface;
|
use Flarum\Notification\Blueprint\BlueprintInterface;
|
||||||
use Flarum\Notification\Event\Sending;
|
use Flarum\Notification\Job\SendNotificationsJob;
|
||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
|
use Illuminate\Contracts\Queue\Queue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Notification Syncer commits notification blueprints to the database, and
|
* The Notification Syncer commits notification blueprints to the database, and
|
||||||
@@ -42,20 +42,16 @@ class NotificationSyncer
|
|||||||
protected $notifications;
|
protected $notifications;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var NotificationMailer
|
* @var Queue
|
||||||
*/
|
*/
|
||||||
protected $mailer;
|
protected $queue;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param NotificationRepository $notifications
|
|
||||||
* @param NotificationMailer $mailer
|
|
||||||
*/
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
NotificationRepository $notifications,
|
NotificationRepository $notifications,
|
||||||
NotificationMailer $mailer
|
Queue $queue
|
||||||
) {
|
) {
|
||||||
$this->notifications = $notifications;
|
$this->notifications = $notifications;
|
||||||
$this->mailer = $mailer;
|
$this->queue = $queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,7 +65,7 @@ class NotificationSyncer
|
|||||||
*/
|
*/
|
||||||
public function sync(Blueprint\BlueprintInterface $blueprint, array $users)
|
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
|
// Find all existing notification records in the database matching this
|
||||||
// blueprint. We will begin by assuming that they all need to be
|
// blueprint. We will begin by assuming that they all need to be
|
||||||
@@ -87,7 +83,7 @@ class NotificationSyncer
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$existing = $toDelete->first(function ($notification, $i) use ($user) {
|
$existing = $toDelete->first(function ($notification) use ($user) {
|
||||||
return $notification->user_id === $user->id;
|
return $notification->user_id === $user->id;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -115,7 +111,7 @@ class NotificationSyncer
|
|||||||
// receiving this notification for the first time (we know because they
|
// receiving this notification for the first time (we know because they
|
||||||
// didn't have a record in the database).
|
// didn't have a record in the database).
|
||||||
if (count($newRecipients)) {
|
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)
|
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)
|
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;
|
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.
|
* Set the deleted status of a list of notification records.
|
||||||
*
|
*
|
||||||
@@ -212,21 +164,4 @@ class NotificationSyncer
|
|||||||
{
|
{
|
||||||
Notification::whereIn('id', $ids)->update(['is_deleted' => $isDeleted]);
|
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
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
22
framework/core/src/Queue/AbstractJob.php
Normal file
22
framework/core/src/Queue/AbstractJob.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* For detailed copyright and license information, please view the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Queue;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class AbstractJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use InteractsWithQueue;
|
||||||
|
use Queueable;
|
||||||
|
use SerializesModels;
|
||||||
|
}
|
Reference in New Issue
Block a user