Revert BC breaks around notification blueprints

No need for breaking backwards compatibility here - encapsulating the
logic for `getAttributes()` in one place turns out to be quite useful.

Refs #1931.
This commit is contained in:
Franz Liedke 2020-04-03 11:33:33 +02:00
parent 0ff870c02c
commit e43f091582
5 changed files with 54 additions and 69 deletions

View File

@ -22,7 +22,6 @@ interface BlueprintInterface
/** /**
* Get the user that sent the notification. * Get the user that sent the notification.
* *
* @deprecated Will be removed for beta.14
* @return User|null * @return User|null
*/ */
public function getFromUser(); public function getFromUser();
@ -30,7 +29,6 @@ interface BlueprintInterface
/** /**
* Get the model that is the subject of this activity. * Get the model that is the subject of this activity.
* *
* @deprecated Will be removed for beta.14
* @return AbstractModel|null * @return AbstractModel|null
*/ */
public function getSubject(); public function getSubject();
@ -38,19 +36,10 @@ interface BlueprintInterface
/** /**
* Get the data to be stored in the notification. * Get the data to be stored in the notification.
* *
* @deprecated Will be removed for beta.14
* @return array|null * @return array|null
*/ */
public function getData(); public function getData();
/**
* Get the attributes that uniquely identify a notification, plus metadata.
* TODO: Uncomment this for beta.14.
*
* @return array
*/
//public function getAttributes(): array;
/** /**
* Get the serialized type of this activity. * Get the serialized type of this activity.
* *

View File

@ -1,36 +0,0 @@
<?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;
use Flarum\Notification\Blueprint\BlueprintInterface;
/**
* A backwards compatibility layer for notification blueprints.
*
* Will be removed for Beta 14 in favor of BlueprintInterface::getAttributes().
*
* @deprecated
*/
class BlueprintBC
{
public static function getAttributes(BlueprintInterface $blueprint): array
{
if (method_exists($blueprint, 'getAttributes')) {
return $blueprint->getAttributes();
} else {
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
];
}
}
}

View File

@ -9,9 +9,7 @@
namespace Flarum\Notification\Job; namespace Flarum\Notification\Job;
use Carbon\Carbon;
use Flarum\Notification\Blueprint\BlueprintInterface; use Flarum\Notification\Blueprint\BlueprintInterface;
use Flarum\Notification\BlueprintBC;
use Flarum\Notification\Event\Sending; use Flarum\Notification\Event\Sending;
use Flarum\Notification\Notification; use Flarum\Notification\Notification;
use Flarum\Queue\AbstractJob; use Flarum\Queue\AbstractJob;
@ -37,19 +35,8 @@ class SendNotificationsJob extends AbstractJob
public function handle() public function handle()
{ {
$now = Carbon::now('utc')->toDateTimeString();
event(new Sending($this->blueprint, $this->recipients)); event(new Sending($this->blueprint, $this->recipients));
$attributes = BlueprintBC::getAttributes($this->blueprint); Notification::notify($this->recipients, $this->blueprint);
Notification::insert(
array_map(function (User $user) use ($attributes, $now) {
return $attributes + [
'user_id' => $user->id,
'created_at' => $now
];
}, $this->recipients)
);
} }
} }

View File

@ -12,6 +12,7 @@ namespace Flarum\Notification;
use Carbon\Carbon; use Carbon\Carbon;
use Flarum\Database\AbstractModel; use Flarum\Database\AbstractModel;
use Flarum\Event\ScopeModelVisibility; use Flarum\Event\ScopeModelVisibility;
use Flarum\Notification\Blueprint\BlueprintInterface;
use Flarum\User\User; use Flarum\User\User;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
@ -141,10 +142,11 @@ class Notification extends AbstractModel
* to the given user. * to the given user.
* *
* @param Builder $query * @param Builder $query
* @return Builder
*/ */
public function scopeWhereSubjectVisibleTo(Builder $query, User $actor) public function scopeWhereSubjectVisibleTo(Builder $query, User $actor)
{ {
$query->where(function ($query) use ($actor) { return $query->where(function ($query) use ($actor) {
$classes = []; $classes = [];
foreach (static::$subjectModels as $type => $class) { foreach (static::$subjectModels as $type => $class) {
@ -174,10 +176,11 @@ class Notification extends AbstractModel
* *
* @param Builder $query * @param Builder $query
* @param object $model * @param object $model
* @return Builder
*/ */
public function scopeWhereSubject(Builder $query, $model) public function scopeWhereSubject(Builder $query, $model)
{ {
$query->whereSubjectModel(get_class($model)) return $query->whereSubjectModel(get_class($model))
->where('subject_id', $model->id); ->where('subject_id', $model->id);
} }
@ -187,6 +190,7 @@ class Notification extends AbstractModel
* *
* @param Builder $query * @param Builder $query
* @param string $class * @param string $class
* @return Builder
*/ */
public function scopeWhereSubjectModel(Builder $query, string $class) public function scopeWhereSubjectModel(Builder $query, string $class)
{ {
@ -194,7 +198,40 @@ class Notification extends AbstractModel
return $modelClass === $class or is_subclass_of($class, $modelClass); return $modelClass === $class or is_subclass_of($class, $modelClass);
}); });
$query->whereIn('type', array_keys($notificationTypes)); return $query->whereIn('type', array_keys($notificationTypes));
}
/**
* Scope the query to find all records matching the given blueprint.
*
* @param Builder $query
* @param BlueprintInterface $blueprint
* @return Builder
*/
public function scopeMatchingBlueprint(Builder $query, BlueprintInterface $blueprint)
{
return $query->where(static::getBlueprintAttributes($blueprint));
}
/**
* Send notifications to the given recipients.
*
* @param User[] $recipients
* @param BlueprintInterface $blueprint
*/
public static function notify(array $recipients, BlueprintInterface $blueprint)
{
$attributes = static::getBlueprintAttributes($blueprint);
$now = Carbon::now('utc')->toDateTimeString();
static::insert(
array_map(function (User $user) use ($attributes, $now) {
return $attributes + [
'user_id' => $user->id,
'created_at' => $now
];
}, $recipients)
);
} }
/** /**
@ -219,4 +256,14 @@ class Notification extends AbstractModel
{ {
static::$subjectModels[$type] = $subjectModel; static::$subjectModels[$type] = $subjectModel;
} }
private static function getBlueprintAttributes(BlueprintInterface $blueprint): array
{
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
];
}
} }

View File

@ -58,12 +58,10 @@ class NotificationSyncer
*/ */
public function sync(Blueprint\BlueprintInterface $blueprint, array $users) public function sync(Blueprint\BlueprintInterface $blueprint, array $users)
{ {
$attributes = BlueprintBC::getAttributes($blueprint);
// 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
// deleted in order to match the provided list of users. // deleted in order to match the provided list of users.
$toDelete = Notification::where($attributes)->get(); $toDelete = Notification::matchingBlueprint($blueprint)->get();
$toUndelete = []; $toUndelete = [];
$newRecipients = []; $newRecipients = [];
@ -121,7 +119,7 @@ class NotificationSyncer
*/ */
public function delete(BlueprintInterface $blueprint) public function delete(BlueprintInterface $blueprint)
{ {
Notification::where(BlueprintBC::getAttributes($blueprint))->update(['is_deleted' => true]); Notification::matchingBlueprint($blueprint)->update(['is_deleted' => true]);
} }
/** /**
@ -132,7 +130,7 @@ class NotificationSyncer
*/ */
public function restore(BlueprintInterface $blueprint) public function restore(BlueprintInterface $blueprint)
{ {
Notification::where(BlueprintBC::getAttributes($blueprint))->update(['is_deleted' => false]); Notification::matchingBlueprint($blueprint)->update(['is_deleted' => false]);
} }
/** /**