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 Channel Extender #2432

Merged
merged 15 commits into from
Nov 5, 2020
46 changes: 43 additions & 3 deletions src/Extend/Notification.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,63 @@ class Notification implements ExtenderInterface
{
private $blueprints = [];
private $serializers = [];
private $drivers = [];
private $typesEnabledByDefault = [];

public function type(string $blueprint, string $serializer, array $channelsEnabledByDefault = [])
/**
* @param string $blueprint The ::class attribute of the blueprint class.
* This blueprint should implement \Flarum\Notification\Blueprint\BlueprintInterface.
* @param string $serializer The ::class attribute of the serializer class.
* This serializer should extend from \Flarum\Api\Serializer\AbstractSerializer.
* @param string[] $driversEnabledByDefault The names of the drivers enabled by default for this notification type.
* (example: alert, email).
* @return self
*/
public function type(string $blueprint, string $serializer, array $driversEnabledByDefault = [])
{
$this->blueprints[$blueprint] = $channelsEnabledByDefault;
$this->blueprints[$blueprint] = $driversEnabledByDefault;
$this->serializers[$blueprint::getType()] = $serializer;

return $this;
}

/**
* @param string $driverName The name of the notification driver.
* @param string $driver The ::class attribute of the driver class.
* This driver should implement \Flarum\Notification\Driver\NotificationDriverInterface.
* @param string[] $typesEnabledByDefault The names of blueprint classes of types enabled by default for this driver.
* @return self
*/
public function driver(string $driverName, string $driver, array $typesEnabledByDefault = [])
{
$this->drivers[$driverName] = $driver;
$this->typesEnabledByDefault[$driverName] = $typesEnabledByDefault;

return $this;
}

public function extend(Container $container, Extension $extension = null)
{
$container->extend('flarum.notification.blueprints', function ($existingBlueprints) {
return array_merge($existingBlueprints, $this->blueprints);
$existingBlueprints = array_merge($existingBlueprints, $this->blueprints);

foreach ($this->typesEnabledByDefault as $driverName => $typesEnabledByDefault) {
foreach ($typesEnabledByDefault as $blueprintClass) {
if (isset($existingBlueprints[$blueprintClass]) && (! in_array($driverName, $existingBlueprints[$blueprintClass]))) {
$existingBlueprints[$blueprintClass][] = $driverName;
}
}
}

return $existingBlueprints;
});

$container->extend('flarum.api.notification_serializers', function ($existingSerializers) {
return array_merge($existingSerializers, $this->serializers);
});

$container->extend('flarum.notification.drivers', function ($existingDrivers) {
return array_merge($existingDrivers, $this->drivers);
});
}
}
50 changes: 50 additions & 0 deletions src/Notification/Driver/AlertNotificationDriver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?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\Driver;

use Flarum\Notification\Blueprint\BlueprintInterface;
use Flarum\Notification\Job\SendNotificationsJob;
use Flarum\User\User;
use Illuminate\Contracts\Queue\Queue;

class AlertNotificationDriver implements NotificationDriverInterface
{
/**
* @var Queue
*/
private $queue;

public function __construct(Queue $queue)
{
$this->queue = $queue;
}

/**
* {@inheritDoc}
*/
public function send(BlueprintInterface $blueprint, array $users): void
{
if (count($users)) {
$this->queue->push(new SendNotificationsJob($blueprint, $users));
}
}

/**
* {@inheritdoc}
*/
public function registerType(string $blueprintClass, bool $default): void
{
User::addPreference(
User::getNotificationPreferenceKey($blueprintClass::getType(), 'alert'),
'boolval',
$default
);
}
}
69 changes: 69 additions & 0 deletions src/Notification/Driver/EmailNotificationDriver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?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\Driver;

use Flarum\Notification\Blueprint\BlueprintInterface;
use Flarum\Notification\Job\SendEmailNotificationJob;
use Flarum\Notification\MailableInterface;
use Flarum\User\User;
use Illuminate\Contracts\Queue\Queue;
use ReflectionClass;

class EmailNotificationDriver implements NotificationDriverInterface
{
/**
* @var Queue
*/
private $queue;

public function __construct(Queue $queue)
{
$this->queue = $queue;
}

/**
* {@inheritDoc}
*/
public function send(BlueprintInterface $blueprint, array $users): void
{
if ($blueprint instanceof MailableInterface) {
$this->mailNotifications($blueprint, $users);
}
}

/**
* 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->queue->push(new SendEmailNotificationJob($blueprint, $user));
}
}
}

/**
* {@inheritdoc}
*/
public function registerType(string $blueprintClass, bool $default): void
{
if ((new ReflectionClass($blueprintClass))->implementsInterface(MailableInterface::class)) {
askvortsov1 marked this conversation as resolved.
Show resolved Hide resolved
User::addPreference(
User::getNotificationPreferenceKey($blueprintClass::getType(), 'email'),
'boolval',
$default
);
}
}
}
34 changes: 34 additions & 0 deletions src/Notification/Driver/NotificationDriverInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?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\Driver;

use Flarum\Notification\Blueprint\BlueprintInterface;
use Flarum\User\User;

interface NotificationDriverInterface
{
/**
* Conditionally sends a notification to users, generally using a queue.
*
* @param BlueprintInterface $blueprint
* @param User[] $users
* @return void
*/
public function send(BlueprintInterface $blueprint, array $users): void;

/**
* Logic for registering a notification type, generally used for adding a user preference.
*
* @param string $blueprintClass
* @param bool $default
* @return void
*/
public function registerType(string $blueprintClass, bool $default): void;
}
3 changes: 3 additions & 0 deletions src/Notification/Event/Sending.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

use Flarum\Notification\Blueprint\BlueprintInterface;

/**
* @deprecated in beta 15, removed in beta 16
*/
class Sending
{
/**
Expand Down
3 changes: 0 additions & 3 deletions src/Notification/Job/SendNotificationsJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
namespace Flarum\Notification\Job;

use Flarum\Notification\Blueprint\BlueprintInterface;
use Flarum\Notification\Event\Sending;
use Flarum\Notification\Notification;
use Flarum\Queue\AbstractJob;
use Flarum\User\User;
Expand All @@ -35,8 +34,6 @@ public function __construct(BlueprintInterface $blueprint, array $recipients = [

public function handle()
{
event(new Sending($this->blueprint, $this->recipients));

Notification::notify($this->recipients, $this->blueprint);
}
}
41 changes: 25 additions & 16 deletions src/Notification/NotificationServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
use Flarum\Event\ConfigureNotificationTypes;
use Flarum\Foundation\AbstractServiceProvider;
use Flarum\Notification\Blueprint\DiscussionRenamedBlueprint;
use Flarum\User\User;
use ReflectionClass;

class NotificationServiceProvider extends AbstractServiceProvider
{
Expand All @@ -22,6 +20,13 @@ class NotificationServiceProvider extends AbstractServiceProvider
*/
public function register()
{
$this->app->singleton('flarum.notification.drivers', function () {
return [
'alert' => Driver\AlertNotificationDriver::class,
'email' => Driver\EmailNotificationDriver::class,
];
});

$this->app->singleton('flarum.notification.blueprints', function () {
return [
DiscussionRenamedBlueprint::class => ['alert']
Expand All @@ -34,9 +39,20 @@ public function register()
*/
public function boot()
{
$this->setNotificationDrivers();
$this->setNotificationTypes();
}

/**
* Register notification drivers.
*/
protected function setNotificationDrivers()
{
foreach ($this->app->make('flarum.notification.drivers') as $driverName => $driver) {
NotificationSyncer::addNotificationDriver($driverName, $this->app->make($driver));
}
}

/**
* Register notification types.
*/
Expand All @@ -49,29 +65,22 @@ protected function setNotificationTypes()
new ConfigureNotificationTypes($blueprints)
);

foreach ($blueprints as $blueprint => $channelsEnabledByDefault) {
$this->addType($blueprint, $channelsEnabledByDefault);
foreach ($blueprints as $blueprint => $driversEnabledByDefault) {
$this->addType($blueprint, $driversEnabledByDefault);
}
}

protected function addType(string $blueprint, array $channelsEnabledByDefault)
protected function addType(string $blueprint, array $driversEnabledByDefault)
{
Notification::setSubjectModel(
$type = $blueprint::getType(),
$blueprint::getSubjectModel()
);

User::addPreference(
User::getNotificationPreferenceKey($type, 'alert'),
'boolval',
in_array('alert', $channelsEnabledByDefault)
);

if ((new ReflectionClass($blueprint))->implementsInterface(MailableInterface::class)) {
User::addPreference(
User::getNotificationPreferenceKey($type, 'email'),
'boolval',
in_array('email', $channelsEnabledByDefault)
foreach (NotificationSyncer::getNotificationDrivers() as $driverName => $driver) {
$driver->registerType(
$blueprint,
in_array($driverName, $driversEnabledByDefault)
SychO9 marked this conversation as resolved.
Show resolved Hide resolved
);
}
}
Expand Down
Loading