mirror of
https://github.com/flarum/framework.git
synced 2025-02-18 08:32:45 +08:00
Rework notifications architecture
- The recipient(s) are the concern of the notifier/sender, not the notification itself - Allow “retraction” of notifications (e.g. if a discussion is stickied, but then it is unstickied) - Misc. cleanup
This commit is contained in:
parent
6517b1ec3e
commit
3925e5892c
|
@ -27,10 +27,16 @@ class DiscussionRenamedNotifier
|
||||||
{
|
{
|
||||||
$post = $this->createPost($event);
|
$post = $this->createPost($event);
|
||||||
|
|
||||||
$event->discussion->addPost($post);
|
$post = $event->discussion->addPost($post);
|
||||||
|
|
||||||
if ($event->discussion->start_user_id !== $event->user->id) {
|
if ($event->discussion->start_user_id !== $event->user->id) {
|
||||||
$this->sendNotification($event, $post);
|
$notification = new DiscussionRenamedNotification($event->discussion, $post->user, $post);
|
||||||
|
|
||||||
|
if ($post->exists) {
|
||||||
|
$this->notifier->send($notification, [$post->discussion->startUser]);
|
||||||
|
} else {
|
||||||
|
$this->notifier->retract($notification);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,16 +49,4 @@ class DiscussionRenamedNotifier
|
||||||
$event->discussion->title
|
$event->discussion->title
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function sendNotification(DiscussionWasRenamed $event, DiscussionRenamedPost $post)
|
|
||||||
{
|
|
||||||
$notification = new DiscussionRenamedNotification(
|
|
||||||
$event->discussion->startUser,
|
|
||||||
$event->user,
|
|
||||||
$post,
|
|
||||||
$event->oldTitle
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->notifier->send($notification);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ class Notification extends Model
|
||||||
*/
|
*/
|
||||||
public function setDataAttribute($value)
|
public function setDataAttribute($value)
|
||||||
{
|
{
|
||||||
$this->attributes['data'] = json_encode($value);
|
$this->attributes['data'] = $value ? json_encode($value) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php namespace Flarum\Core\Notifications;
|
<?php namespace Flarum\Core\Notifications;
|
||||||
|
|
||||||
use Flarum\Core\Notifications\Types\Notification;
|
use Flarum\Core\Notifications\Types\Notification;
|
||||||
|
use Flarum\Core\Notifications\Senders\RetractableSender;
|
||||||
use Flarum\Core\Models\Notification as NotificationModel;
|
use Flarum\Core\Models\Notification as NotificationModel;
|
||||||
use Flarum\Core\Models\User;
|
use Flarum\Core\Models\User;
|
||||||
use Illuminate\Container\Container;
|
use Illuminate\Container\Container;
|
||||||
|
@ -18,12 +19,28 @@ class Notifier
|
||||||
$this->container = $container;
|
$this->container = $container;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function send(Notification $notification)
|
public function send(Notification $notification, array $users)
|
||||||
{
|
{
|
||||||
foreach ($this->methods as $method => $sender) {
|
foreach ($this->methods as $method => $sender) {
|
||||||
$sender = $this->container->make($sender);
|
$sender = $this->container->make($sender);
|
||||||
if ($notification->getRecipient()->shouldNotify($notification::getType(), $method) && $sender::compatibleWith($notification)) {
|
|
||||||
$sender->send($notification);
|
if ($sender::compatibleWith($notification)) {
|
||||||
|
foreach ($users as $user) {
|
||||||
|
if ($user->shouldNotify($notification::getType(), $method)) {
|
||||||
|
$sender->send($notification, $user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function retract(Notification $notification)
|
||||||
|
{
|
||||||
|
foreach ($this->methods as $method => $sender) {
|
||||||
|
$sender = $this->container->make($sender);
|
||||||
|
|
||||||
|
if ($sender instanceof RetractableSender && $sender::compatibleWith($notification)) {
|
||||||
|
$sender->retract($notification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,22 +2,31 @@
|
||||||
|
|
||||||
use Flarum\Core\Notifications\Types\Notification;
|
use Flarum\Core\Notifications\Types\Notification;
|
||||||
use Flarum\Core\Models\Notification as NotificationModel;
|
use Flarum\Core\Models\Notification as NotificationModel;
|
||||||
|
use Flarum\Core\Models\User;
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
|
|
||||||
class NotificationAlerter implements NotificationSender
|
class NotificationAlerter implements NotificationSender, RetractableSender
|
||||||
{
|
{
|
||||||
public function send(Notification $notification)
|
public function send(Notification $notification, User $user)
|
||||||
{
|
{
|
||||||
$model = NotificationModel::alert(
|
$model = NotificationModel::alert(
|
||||||
$notification->getRecipient()->id,
|
$user->id,
|
||||||
$notification::getType(),
|
$notification::getType(),
|
||||||
$notification->getSender()->id,
|
$notification->getSender()->id,
|
||||||
$notification->getSubject()->id,
|
$notification->getSubject()->id,
|
||||||
$notification->getAlertData()
|
$notification->getAlertData()
|
||||||
);
|
);
|
||||||
|
|
||||||
$model->save();
|
$model->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function retract(Notification $notification)
|
||||||
|
{
|
||||||
|
$models = NotificationModel::where('type', $notification::getType())
|
||||||
|
->where('subject_id', $notification->getSubject()->id)
|
||||||
|
->delete();
|
||||||
|
}
|
||||||
|
|
||||||
public static function compatibleWith($className)
|
public static function compatibleWith($className)
|
||||||
{
|
{
|
||||||
return (new ReflectionClass($className))->implementsInterface('Flarum\Core\Notifications\Types\AlertableNotification');
|
return (new ReflectionClass($className))->implementsInterface('Flarum\Core\Notifications\Types\AlertableNotification');
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php namespace Flarum\Core\Notifications\Senders;
|
<?php namespace Flarum\Core\Notifications\Senders;
|
||||||
|
|
||||||
use Flarum\Core\Notifications\Types\Notification;
|
use Flarum\Core\Notifications\Types\Notification;
|
||||||
|
use Flarum\Core\Models\User;
|
||||||
use Flarum\Core\Models\Forum;
|
use Flarum\Core\Models\Forum;
|
||||||
use Illuminate\Mail\Mailer;
|
use Illuminate\Mail\Mailer;
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
|
@ -13,10 +14,9 @@ class NotificationEmailer implements NotificationSender
|
||||||
$this->forum = $forum;
|
$this->forum = $forum;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function send(Notification $notification)
|
public function send(Notification $notification, User $user)
|
||||||
{
|
{
|
||||||
$this->mailer->send($notification->getEmailView(), ['notification' => $notification], function ($message) use ($notification) {
|
$this->mailer->send($notification->getEmailView(), ['notification' => $notification], function ($message) use ($notification, $recipient) {
|
||||||
$recipient = $notification->getRecipient();
|
|
||||||
$message->to($recipient->email, $recipient->username)
|
$message->to($recipient->email, $recipient->username)
|
||||||
->subject('['.$this->forum->title.'] '.$notification->getEmailSubject());
|
->subject('['.$this->forum->title.'] '.$notification->getEmailSubject());
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
<?php namespace Flarum\Core\Notifications\Senders;
|
<?php namespace Flarum\Core\Notifications\Senders;
|
||||||
|
|
||||||
use Flarum\Core\Notifications\Types\Notification;
|
use Flarum\Core\Notifications\Types\Notification;
|
||||||
|
use Flarum\Core\Models\User;
|
||||||
|
|
||||||
interface NotificationSender
|
interface NotificationSender
|
||||||
{
|
{
|
||||||
public function send(Notification $notification);
|
public function send(Notification $notification, User $user);
|
||||||
|
|
||||||
public static function compatibleWith($class);
|
public static function compatibleWith($class);
|
||||||
}
|
}
|
||||||
|
|
8
src/Core/Notifications/Senders/RetractableSender.php
Normal file
8
src/Core/Notifications/Senders/RetractableSender.php
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?php namespace Flarum\Core\Notifications\Senders;
|
||||||
|
|
||||||
|
use Flarum\Core\Notifications\Types\Notification;
|
||||||
|
|
||||||
|
interface RetractableSender
|
||||||
|
{
|
||||||
|
public function retract(Notification $notification);
|
||||||
|
}
|
|
@ -1,8 +0,0 @@
|
||||||
<?php namespace Flarum\Core\Notifications\Types;
|
|
||||||
|
|
||||||
interface AlertableNotification
|
|
||||||
{
|
|
||||||
public function getAlertData();
|
|
||||||
|
|
||||||
public static function getType();
|
|
||||||
}
|
|
|
@ -1,33 +1,37 @@
|
||||||
<?php namespace Flarum\Core\Notifications\Types;
|
<?php namespace Flarum\Core\Notifications\Types;
|
||||||
|
|
||||||
use Flarum\Core\Models\User;
|
use Flarum\Core\Models\User;
|
||||||
|
use Flarum\Core\Models\Discussion;
|
||||||
use Flarum\Core\Models\DiscussionRenamedPost;
|
use Flarum\Core\Models\DiscussionRenamedPost;
|
||||||
|
|
||||||
class DiscussionRenamedNotification extends Notification implements AlertableNotification
|
class DiscussionRenamedNotification extends Notification implements AlertableNotification
|
||||||
{
|
{
|
||||||
public $post;
|
protected $discussion;
|
||||||
|
|
||||||
public $oldTitle;
|
protected $sender;
|
||||||
|
|
||||||
public function __construct(User $recipient, User $sender, DiscussionRenamedPost $post, $oldTitle)
|
protected $post;
|
||||||
|
|
||||||
|
public function __construct(Discussion $discussion, User $sender, DiscussionRenamedPost $post = null)
|
||||||
{
|
{
|
||||||
|
$this->discussion = $discussion;
|
||||||
|
$this->sender = $sender;
|
||||||
$this->post = $post;
|
$this->post = $post;
|
||||||
$this->oldTitle = $oldTitle;
|
|
||||||
|
|
||||||
parent::__construct($recipient, $sender);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSubject()
|
public function getSubject()
|
||||||
{
|
{
|
||||||
return $this->post->discussion;
|
return $this->discussion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSender()
|
||||||
|
{
|
||||||
|
return $this->sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAlertData()
|
public function getAlertData()
|
||||||
{
|
{
|
||||||
return [
|
return ['postNumber' => $this->post->number];
|
||||||
'number' => $this->post->number,
|
|
||||||
'oldTitle' => $this->oldTitle
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getType()
|
public static function getType()
|
||||||
|
|
|
@ -1,36 +1,6 @@
|
||||||
<?php namespace Flarum\Core\Notifications\Types;
|
<?php namespace Flarum\Core\Notifications\Types;
|
||||||
|
|
||||||
use Flarum\Core\Models\User;
|
|
||||||
|
|
||||||
abstract class Notification
|
abstract class Notification
|
||||||
{
|
{
|
||||||
protected $recipient;
|
abstract public static function getType();
|
||||||
|
|
||||||
protected $sender;
|
|
||||||
|
|
||||||
public function __construct(User $recipient, User $sender)
|
|
||||||
{
|
|
||||||
$this->recipient = $recipient;
|
|
||||||
$this->sender = $sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRecipient()
|
|
||||||
{
|
|
||||||
return $this->recipient;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSender()
|
|
||||||
{
|
|
||||||
return $this->sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getType()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getSubjectModel()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,15 +5,15 @@ use DB;
|
||||||
|
|
||||||
class EloquentNotificationRepository implements NotificationRepositoryInterface
|
class EloquentNotificationRepository implements NotificationRepositoryInterface
|
||||||
{
|
{
|
||||||
public function findByUser($userId, $count = null, $start = 0)
|
public function findByUser($userId, $limit = null, $offset = 0)
|
||||||
{
|
{
|
||||||
$primaries = Notification::select(DB::raw('MAX(id) AS id'), DB::raw('SUM(is_read = 0) AS unread_count'))
|
$primaries = Notification::select(DB::raw('MAX(id) AS id'), DB::raw('SUM(is_read = 0) AS unread_count'))
|
||||||
->where('user_id', $userId)
|
->where('user_id', $userId)
|
||||||
->whereIn('type', array_keys(Notification::getTypes()))
|
->whereIn('type', array_keys(Notification::getTypes()))
|
||||||
->groupBy('type', 'subject_id')
|
->groupBy('type', 'subject_id')
|
||||||
->orderBy('time', 'desc')
|
->orderBy('time', 'desc')
|
||||||
->skip($start)
|
->skip($offset)
|
||||||
->take($count);
|
->take($limit);
|
||||||
|
|
||||||
return Notification::with('subject')
|
return Notification::with('subject')
|
||||||
->select('notifications.*', 'p.unread_count')
|
->select('notifications.*', 'p.unread_count')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user