Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Notification extender beforeSending method #2533

Merged
merged 7 commits into from
Jan 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/Extend/Notification.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
namespace Flarum\Extend;

use Flarum\Extension\Extension;
use Flarum\Foundation\ContainerUtil;
use Flarum\Notification\NotificationSyncer;
use Illuminate\Contracts\Container\Container;

class Notification implements ExtenderInterface
Expand All @@ -18,6 +20,7 @@ class Notification implements ExtenderInterface
private $serializers = [];
private $drivers = [];
private $typesEnabledByDefault = [];
private $beforeSendingCallbacks = [];

/**
* @param string $blueprint The ::class attribute of the blueprint class.
Expand Down Expand Up @@ -51,6 +54,17 @@ public function driver(string $driverName, string $driver, array $typesEnabledBy
return $this;
}

/**
* @param callable|string $callback
* @return self
*/
public function beforeSending($callback)
{
$this->beforeSendingCallbacks[] = $callback;

return $this;
}

public function extend(Container $container, Extension $extension = null)
{
$container->extend('flarum.notification.blueprints', function ($existingBlueprints) {
Expand All @@ -74,5 +88,9 @@ public function extend(Container $container, Extension $extension = null)
$container->extend('flarum.notification.drivers', function ($existingDrivers) {
return array_merge($existingDrivers, $this->drivers);
});

foreach ($this->beforeSendingCallbacks as $callback) {
NotificationSyncer::beforeSending(ContainerUtil::wrapCallback($callback, $container));
}
}
}
17 changes: 17 additions & 0 deletions src/Notification/NotificationSyncer.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ class NotificationSyncer
*/
protected static $notificationDrivers = [];

/**
* @var array
*/
protected static $beforeSendingCallbacks = [];

/**
* Sync a notification so that it is visible to the specified users, and not
* visible to anyone else. If it is being made visible for the first time,
Expand Down Expand Up @@ -94,6 +99,10 @@ public function sync(Blueprint\BlueprintInterface $blueprint, array $users)
$this->setDeleted($toUndelete, false);
}

foreach (static::$beforeSendingCallbacks as $callback) {
$newRecipients = $callback($blueprint, $newRecipients);
}

// Create a notification record, and send an email, for all users
// receiving this notification for the first time (we know because they
// didn't have a record in the database). As both operations can be
Expand Down Expand Up @@ -176,4 +185,12 @@ public static function getNotificationDrivers(): array
{
return static::$notificationDrivers;
}

/**
* @param callable|string $callback
*/
public static function beforeSending($callback): void
{
static::$beforeSendingCallbacks[] = $callback;
}
}
52 changes: 48 additions & 4 deletions tests/integration/extenders/NotificationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@
use Flarum\Notification\Driver\NotificationDriverInterface;
use Flarum\Notification\Notification;
use Flarum\Notification\NotificationSyncer;
use Flarum\Tests\integration\RetrievesAuthorizedUsers;
use Flarum\Tests\integration\TestCase;
use Flarum\User\User;

class NotificationTest extends TestCase
{
use RetrievesAuthorizedUsers;

/**
* @test
*/
Expand Down Expand Up @@ -119,23 +123,61 @@ public function notification_driver_enabled_types_exist_if_added()
$this->assertContains('secondCustomDriver', $blueprints[SecondCustomNotificationType::class]);
$this->assertEmpty($blueprints[ThirdCustomNotificationType::class]);
}

/**
* @test
*/
public function notification_before_sending_callback_works_if_added()
{
$this->extend(
(new Extend\Notification)
->type(CustomNotificationType::class, 'customNotificationTypeSerializer')
->driver('customNotificationDriver', CustomNotificationDriver::class)
->beforeSending(function ($blueprint, $users) {
if ($blueprint instanceof CustomNotificationType) {
unset($users[1]);
}

return $users;
})
);

$this->prepareDatabase([
'users' => [
$this->adminUser(),
$this->normalUser(),
['id' => 3, 'username' => 'hani']
],
]);

$this->app();

$users = User::whereIn('id', [1, 2, 3])->get()->all();

$notificationSyncer = $this->app()->getContainer()->make(NotificationSyncer::class);
$notificationSyncer->sync(new CustomNotificationType(), $users);

$this->assertEquals('potato', $users[0]->username);
$this->assertEquals('normal', $users[1]->username);
$this->assertEquals('potato', $users[2]->username);
}
}

class CustomNotificationType implements BlueprintInterface
{
public function getFromUser()
{
// ...
return null;
}

public function getSubject()
{
// ...
return null;
}

public function getData()
{
// ...
return [];
}

public static function getType()
Expand Down Expand Up @@ -169,7 +211,9 @@ class CustomNotificationDriver implements NotificationDriverInterface
{
public function send(BlueprintInterface $blueprint, array $users): void
{
// ...
foreach ($users as $user) {
$user->username = 'potato';
}
}

public function registerType(string $blueprintClass, array $driversEnabledByDefault): void
Expand Down