Global subscribers and fix notifications
This commit is contained in:
committed by
Graham Campbell
parent
5abd25c408
commit
05bb91d2d9
@@ -32,13 +32,6 @@ final class SubscribeSubscriberCommand
|
|||||||
*/
|
*/
|
||||||
public $verified;
|
public $verified;
|
||||||
|
|
||||||
/**
|
|
||||||
* The subscriptions that we want to add.
|
|
||||||
*
|
|
||||||
* @var array|null
|
|
||||||
*/
|
|
||||||
public $subscriptions;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The validation rules.
|
* The validation rules.
|
||||||
*
|
*
|
||||||
@@ -53,14 +46,12 @@ final class SubscribeSubscriberCommand
|
|||||||
*
|
*
|
||||||
* @param string $email
|
* @param string $email
|
||||||
* @param bool $verified
|
* @param bool $verified
|
||||||
* @param null|array $subscriptions
|
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct($email, $verified = false, $subscriptions = null)
|
public function __construct($email, $verified = false)
|
||||||
{
|
{
|
||||||
$this->email = $email;
|
$this->email = $email;
|
||||||
$this->verified = $verified;
|
$this->verified = $verified;
|
||||||
$this->subscriptions = $subscriptions;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Cachet.
|
||||||
|
*
|
||||||
|
* (c) Alt Three Services Limited
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CachetHQ\Cachet\Bus\Commands\Subscriber;
|
||||||
|
|
||||||
|
use CachetHQ\Cachet\Models\Subscriber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the subscribe subscriber command.
|
||||||
|
*
|
||||||
|
* @author Joseph Cohen <joe@alt-three.com>
|
||||||
|
*/
|
||||||
|
final class UpdateSubscriberSubscriptionCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The subscriber email.
|
||||||
|
*
|
||||||
|
* @var \CachetHQ\Cachet\Models\Subscriber
|
||||||
|
*/
|
||||||
|
public $subscriber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The subscriptions that we want to add.
|
||||||
|
*
|
||||||
|
* @var array|null
|
||||||
|
*/
|
||||||
|
public $subscriptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new subscribe subscriber command instance.
|
||||||
|
*
|
||||||
|
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
|
||||||
|
* @param null|array $subscriptions
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($subscriber, $subscriptions = null)
|
||||||
|
{
|
||||||
|
$this->subscriber = $subscriber;
|
||||||
|
$this->subscriptions = $subscriptions;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Cachet.
|
|
||||||
*
|
|
||||||
* (c) Alt Three Services Limited
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace CachetHQ\Cachet\Bus\Exceptions\Subscriber;
|
|
||||||
|
|
||||||
use CachetHQ\Cachet\Bus\Exceptions\ExceptionInterface;
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the already subscribed exception class.
|
|
||||||
*
|
|
||||||
* @author Graham Campbell <graham@alt-three.com>
|
|
||||||
* @author James Brooks <james@alt-three.com>
|
|
||||||
*/
|
|
||||||
class AlreadySubscribedException extends Exception implements ExceptionInterface
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
@@ -14,8 +14,7 @@ namespace CachetHQ\Cachet\Bus\Handlers\Commands\Subscriber;
|
|||||||
use CachetHQ\Cachet\Bus\Commands\Subscriber\SubscribeSubscriberCommand;
|
use CachetHQ\Cachet\Bus\Commands\Subscriber\SubscribeSubscriberCommand;
|
||||||
use CachetHQ\Cachet\Bus\Commands\Subscriber\VerifySubscriberCommand;
|
use CachetHQ\Cachet\Bus\Commands\Subscriber\VerifySubscriberCommand;
|
||||||
use CachetHQ\Cachet\Bus\Events\Subscriber\SubscriberHasSubscribedEvent;
|
use CachetHQ\Cachet\Bus\Events\Subscriber\SubscriberHasSubscribedEvent;
|
||||||
use CachetHQ\Cachet\Bus\Events\Subscriber\SubscriberHasUpdatedSubscriptionsEvent;
|
use CachetHQ\Cachet\Models\Component;
|
||||||
use CachetHQ\Cachet\Bus\Exceptions\Subscriber\AlreadySubscribedException;
|
|
||||||
use CachetHQ\Cachet\Models\Subscriber;
|
use CachetHQ\Cachet\Models\Subscriber;
|
||||||
use CachetHQ\Cachet\Models\Subscription;
|
use CachetHQ\Cachet\Models\Subscription;
|
||||||
|
|
||||||
@@ -31,35 +30,27 @@ class SubscribeSubscriberCommandHandler
|
|||||||
*
|
*
|
||||||
* @param \CachetHQ\Cachet\Bus\Commands\Subscriber\SubscribeSubscriberCommand $command
|
* @param \CachetHQ\Cachet\Bus\Commands\Subscriber\SubscribeSubscriberCommand $command
|
||||||
*
|
*
|
||||||
* @throws \CachetHQ\Cachet\Exceptions\AlreadySubscribedException
|
|
||||||
*
|
|
||||||
* @return \CachetHQ\Cachet\Models\Subscriber
|
* @return \CachetHQ\Cachet\Models\Subscriber
|
||||||
*/
|
*/
|
||||||
public function handle(SubscribeSubscriberCommand $command)
|
public function handle(SubscribeSubscriberCommand $command)
|
||||||
{
|
{
|
||||||
if (Subscriber::where('email', $command->email)->first() && $command->subscriptions === null) {
|
if ($subscriber = Subscriber::where('email', $command->email)->first()) {
|
||||||
throw new AlreadySubscribedException("Cannot subscribe {$command->email} because they're already subscribed.");
|
return $subscriber;
|
||||||
}
|
}
|
||||||
|
|
||||||
$subscriber = Subscriber::firstOrCreate(['email' => $command->email]);
|
$subscriber = Subscriber::firstOrCreate(['email' => $command->email]);
|
||||||
|
|
||||||
if ($subscriptions = $command->subscriptions) {
|
foreach (Component::all() as $component) {
|
||||||
foreach ($subscriptions as $subscription => $subscriptionValue) {
|
Subscription::create([
|
||||||
Subscription::firstOrCreate([
|
'subscriber_id' => $subscriber->id,
|
||||||
'subscriber_id' => $subscriber->id,
|
'component_id' => $component->id,
|
||||||
$subscription => $subscriptionValue,
|
]);
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($subscriber->is_verified === false) {
|
if ($command->verified) {
|
||||||
if ($command->verified) {
|
dispatch(new VerifySubscriberCommand($subscriber));
|
||||||
dispatch(new VerifySubscriberCommand($subscriber));
|
|
||||||
} else {
|
|
||||||
event(new SubscriberHasSubscribedEvent($subscriber));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
event(new SubscriberHasUpdatedSubscriptionsEvent($subscriber));
|
event(new SubscriberHasSubscribedEvent($subscriber));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $subscriber;
|
return $subscriber;
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Cachet.
|
||||||
|
*
|
||||||
|
* (c) Alt Three Services Limited
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CachetHQ\Cachet\Bus\Handlers\Commands\Subscriber;
|
||||||
|
|
||||||
|
use CachetHQ\Cachet\Bus\Commands\Subscriber\UpdateSubscriberSubscriptionCommand;
|
||||||
|
use CachetHQ\Cachet\Bus\Events\Subscriber\SubscriberHasUpdatedSubscriptionsEvent;
|
||||||
|
use CachetHQ\Cachet\Models\Component;
|
||||||
|
use CachetHQ\Cachet\Models\Subscriber;
|
||||||
|
use CachetHQ\Cachet\Models\Subscription;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the subscribe subscriber command handler.
|
||||||
|
*
|
||||||
|
* @author Joseph Cohen <joe@alt-three.com>
|
||||||
|
*/
|
||||||
|
class UpdateSubscriberSubscriptionCommandHandler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle the subscribe subscriber command.
|
||||||
|
*
|
||||||
|
* @param \CachetHQ\Cachet\Bus\Commands\Subscriber\UpdateSubscriberSubscriptionCommand $command
|
||||||
|
*
|
||||||
|
* @return \CachetHQ\Cachet\Models\Subscriber
|
||||||
|
*/
|
||||||
|
public function handle(UpdateSubscriberSubscriptionCommand $command)
|
||||||
|
{
|
||||||
|
$subscriber = $command->subscriber;
|
||||||
|
$subscriptions = $command->subscriptions ?: [];
|
||||||
|
|
||||||
|
$components = Component::all();
|
||||||
|
|
||||||
|
$updateSubscriptions = $components->filter(function ($item) use ($subscriptions) {
|
||||||
|
return in_array($item->id, $subscriptions);
|
||||||
|
});
|
||||||
|
|
||||||
|
$subscriber->global = ($updateSubscriptions->count() === $components->count());
|
||||||
|
|
||||||
|
$subscriber->subscriptions()->delete();
|
||||||
|
|
||||||
|
if (!$updateSubscriptions->isEmpty()) {
|
||||||
|
foreach ($updateSubscriptions as $subscription) {
|
||||||
|
Subscription::firstOrCreate([
|
||||||
|
'subscriber_id' => $subscriber->id,
|
||||||
|
'component_id' => $subscription->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$subscriber->save();
|
||||||
|
|
||||||
|
event(new SubscriberHasUpdatedSubscriptionsEvent($subscriber));
|
||||||
|
|
||||||
|
return $subscriber;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,8 +12,8 @@
|
|||||||
namespace CachetHQ\Cachet\Bus\Handlers\Events\Component;
|
namespace CachetHQ\Cachet\Bus\Handlers\Events\Component;
|
||||||
|
|
||||||
use CachetHQ\Cachet\Bus\Events\Component\ComponentWasUpdatedEvent;
|
use CachetHQ\Cachet\Bus\Events\Component\ComponentWasUpdatedEvent;
|
||||||
|
use CachetHQ\Cachet\Models\Subscriber;
|
||||||
use CachetHQ\Cachet\Models\Component;
|
use CachetHQ\Cachet\Models\Component;
|
||||||
use CachetHQ\Cachet\Models\Subscription;
|
|
||||||
use Illuminate\Contracts\Mail\MailQueue;
|
use Illuminate\Contracts\Mail\MailQueue;
|
||||||
use Illuminate\Mail\Message;
|
use Illuminate\Mail\Message;
|
||||||
use McCool\LaravelAutoPresenter\Facades\AutoPresenter;
|
use McCool\LaravelAutoPresenter\Facades\AutoPresenter;
|
||||||
@@ -27,16 +27,25 @@ class SendComponentUpdateEmailNotificationHandler
|
|||||||
*/
|
*/
|
||||||
protected $mailer;
|
protected $mailer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The subscriber instance.
|
||||||
|
*
|
||||||
|
* @var \CachetHQ\Cachet\Models\Subscriber
|
||||||
|
*/
|
||||||
|
protected $subscriber;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new send incident email notification handler.
|
* Create a new send incident email notification handler.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Contracts\Mail\Mailer $mailer
|
* @param \Illuminate\Contracts\Mail\Mailer $mailer
|
||||||
|
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct(MailQueue $mailer)
|
public function __construct(MailQueue $mailer, Subscriber $subscriber)
|
||||||
{
|
{
|
||||||
$this->mailer = $mailer;
|
$this->mailer = $mailer;
|
||||||
|
$this->subscriber = $subscriber;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,24 +59,53 @@ class SendComponentUpdateEmailNotificationHandler
|
|||||||
{
|
{
|
||||||
$component = AutoPresenter::decorate($event->component);
|
$component = AutoPresenter::decorate($event->component);
|
||||||
|
|
||||||
|
// First notify all global subscribers.
|
||||||
|
$globalSubscribers = $this->subscriber->isVerified()->isGlobal()->get();
|
||||||
|
|
||||||
|
foreach ($globalSubscribers as $subscriber) {
|
||||||
|
$this->notify($event, $subscriber);
|
||||||
|
}
|
||||||
|
|
||||||
|
$notified = $globalSubscribers->pluck('id')->all();
|
||||||
|
|
||||||
|
// Notify the remaining component specific subscribers.
|
||||||
|
$componentSubscribers = $this->subscriber
|
||||||
|
->isVerified()
|
||||||
|
->forComponent($component->id)
|
||||||
|
->get()
|
||||||
|
->reject(function ($subscriber) use ($notified) {
|
||||||
|
return in_array($subscriber->id, $notified);
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach ($componentSubscribers as $subscriber) {
|
||||||
|
$this->notify($event, $subscriber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send notification to subscriber.
|
||||||
|
*
|
||||||
|
* @param \CachetHQ\Cachet\Bus\Events\ComponentWasUpdatedEvent $event
|
||||||
|
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Collection
|
||||||
|
*/
|
||||||
|
public function notify(ComponentWasUpdatedEvent $event, $subscriber)
|
||||||
|
{
|
||||||
$mail = [
|
$mail = [
|
||||||
'subject' => trans('cachet.subscriber.email.component.subject'),
|
'subject' => trans('cachet.subscriber.email.component.subject'),
|
||||||
'component_name' => $component->name,
|
'component_name' => $component->name,
|
||||||
'component_human_status' => $component->human_status,
|
'component_human_status' => $component->human_status,
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach (Subscription::isVerifiedForComponent($component->id)->with('subscriber')->get() as $subscription) {
|
$mail['email'] = $subscriber->email;
|
||||||
$subscriber = $subscription->subscriber;
|
$mail['manage_link'] = route('subscribe.manage', ['code' => $subscriber->verify_code]);
|
||||||
$mail['email'] = $subscriber->email;
|
|
||||||
$mail['manage_link'] = route('subscribe.manage', ['code' => $subscriber->verify_code]);
|
|
||||||
$mail['unsubscribe_link'] = route('subscribe.unsubscribe', ['code' => $subscriber->verify_code, 'subscription' => $subscription->id]);
|
|
||||||
|
|
||||||
$this->mailer->queue([
|
$this->mailer->queue([
|
||||||
'html' => 'emails.components.update-html',
|
'html' => 'emails.components.update-html',
|
||||||
'text' => 'emails.components.update-text',
|
'text' => 'emails.components.update-text',
|
||||||
], $mail, function (Message $message) use ($mail) {
|
], $mail, function (Message $message) use ($mail) {
|
||||||
$message->to($mail['email'])->subject($mail['subject']);
|
$message->to($mail['email'])->subject($mail['subject']);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class SendIncidentEmailNotificationHandler
|
|||||||
/**
|
/**
|
||||||
* Handle the event.
|
* Handle the event.
|
||||||
*
|
*
|
||||||
* @param \CachetHQ\Cachet\Bus\Events\Incident\IncidentHasReportedEvent $event
|
* @param \CachetHQ\Cachet\Bus\Events\Incident\IncidentWasReportedEvent $event
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
@@ -60,32 +60,69 @@ class SendIncidentEmailNotificationHandler
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only send emails for public incidents.
|
||||||
|
if ($event->incident->visible === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First notify all global subscribers.
|
||||||
|
$globalSubscribers = $this->subscriber->isVerified()->isGlobal()->get();
|
||||||
|
|
||||||
|
foreach ($globalSubscribers as $subscriber) {
|
||||||
|
$this->notify($event, $subscriber);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$event->incident->component) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$notified = $globalSubscribers->pluck('id')->all();
|
||||||
|
|
||||||
|
// Notify the remaining component specific subscribers.
|
||||||
|
$componentSubscribers = $this->subscriber
|
||||||
|
->isVerified()
|
||||||
|
->forComponent($event->incident->component->id)
|
||||||
|
->get()
|
||||||
|
->reject(function ($subscriber) use ($notified) {
|
||||||
|
return in_array($subscriber->id, $notified);
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach ($componentSubscribers as $subscriber) {
|
||||||
|
$this->notify($event, $subscriber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send notification to subscriber.
|
||||||
|
*
|
||||||
|
* @param \CachetHQ\Cachet\Bus\Events\IncidentWasReportedEvent $event
|
||||||
|
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Collection
|
||||||
|
*/
|
||||||
|
public function notify(IncidentWasReportedEvent $event, $subscriber)
|
||||||
|
{
|
||||||
$incident = AutoPresenter::decorate($event->incident);
|
$incident = AutoPresenter::decorate($event->incident);
|
||||||
$component = AutoPresenter::decorate($event->incident->component);
|
$component = AutoPresenter::decorate($event->incident->component);
|
||||||
|
|
||||||
// Only send emails for public incidents.
|
$mail = [
|
||||||
if ($event->incident->visible === 1) {
|
'email' => $subscriber->email,
|
||||||
foreach ($this->subscriber->isVerified()->get() as $subscriber) {
|
'subject' => 'New incident reported.',
|
||||||
$mail = [
|
'has_component' => ($event->incident->component) ? true : false,
|
||||||
'email' => $subscriber->email,
|
'component_name' => $component ? $component->name : null,
|
||||||
'subject' => 'New incident reported.',
|
'status' => $incident->human_status,
|
||||||
'has_component' => ($event->incident->component) ? true : false,
|
'html_content' => $incident->formattedMessage,
|
||||||
'component_name' => $component ? $component->name : null,
|
'text_content' => $incident->message,
|
||||||
'status' => $incident->human_status,
|
'token' => $subscriber->token,
|
||||||
'html_content' => $incident->formattedMessage,
|
'manage_link' => route('subscribe.manage', ['code' => $subscriber->verify_code]),
|
||||||
'text_content' => $incident->message,
|
'unsubscribe_link' => route('subscribe.unsubscribe', ['code' => $subscriber->verify_code]),
|
||||||
'token' => $subscriber->token,
|
];
|
||||||
'manage_link' => route('subscribe.manage', ['code' => $subscriber->verify_code]),
|
|
||||||
'unsubscribe_link' => route('subscribe.unsubscribe', ['code' => $subscriber->verify_code]),
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->mailer->queue([
|
$this->mailer->queue([
|
||||||
'html' => 'emails.incidents.new-html',
|
'html' => 'emails.incidents.new-html',
|
||||||
'text' => 'emails.incidents.new-text',
|
'text' => 'emails.incidents.new-text',
|
||||||
], $mail, function (Message $message) use ($mail) {
|
], $mail, function (Message $message) use ($mail) {
|
||||||
$message->to($mail['email'])->subject($mail['subject']);
|
$message->to($mail['email'])->subject($mail['subject']);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class SendMaintenanceEmailNotificationHandler
|
|||||||
/**
|
/**
|
||||||
* Handle the event.
|
* Handle the event.
|
||||||
*
|
*
|
||||||
* @param \CachetHQ\Cachet\Bus\Events\MaintenanceHasScheduledEvent $event
|
* @param \CachetHQ\Cachet\Bus\Events\MaintenanceWasScheduledEvent $event
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
@@ -60,27 +60,69 @@ class SendMaintenanceEmailNotificationHandler
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = AutoPresenter::decorate($event->incident);
|
// Only send emails for public incidents.
|
||||||
|
if ($event->incident->visible === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($this->subscriber->isVerified()->get() as $subscriber) {
|
// First notify all global subscribers.
|
||||||
$mail = [
|
$globalSubscribers = $this->subscriber->isVerified()->isGlobal()->get();
|
||||||
'email' => $subscriber->email,
|
|
||||||
'subject' => 'Scheduled maintenance.',
|
|
||||||
'status' => $data->human_status,
|
|
||||||
'html_content' => $data->formattedMessage,
|
|
||||||
'text_content' => $data->message,
|
|
||||||
'scheduled_at' => $data->scheduled_at_formatted,
|
|
||||||
'token' => $subscriber->token,
|
|
||||||
'manage_link' => route('subscribe.manage', ['code' => $subscriber->verify_code]),
|
|
||||||
'unsubscribe_link' => route('subscribe.unsubscribe', ['code' => $subscriber->verify_code]),
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->mailer->queue([
|
foreach ($globalSubscribers as $subscriber) {
|
||||||
'html' => 'emails.incidents.maintenance-html',
|
$this->notify($event, $subscriber);
|
||||||
'text' => 'emails.incidents.maintenance-text',
|
}
|
||||||
], $mail, function (Message $message) use ($mail) {
|
|
||||||
$message->to($mail['email'])->subject($mail['subject']);
|
if (!$event->incident->component) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$notified = $globalSubscribers->pluck('id')->all();
|
||||||
|
|
||||||
|
// Notify the remaining component specific subscribers.
|
||||||
|
$componentSubscribers = $this->subscriber
|
||||||
|
->isVerified()
|
||||||
|
->forComponent($event->incident->component->id)
|
||||||
|
->get()
|
||||||
|
->reject(function ($subscriber) use ($notified) {
|
||||||
|
return in_array($subscriber->id, $notified);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
foreach ($componentSubscribers as $subscriber) {
|
||||||
|
$this->notify($event, $subscriber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send notification to subscriber.
|
||||||
|
*
|
||||||
|
* @param \CachetHQ\Cachet\Bus\Events\MaintenanceWasScheduledEvent $event
|
||||||
|
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Collection
|
||||||
|
*/
|
||||||
|
public function notify(MaintenanceWasScheduledEvent $event, $subscriber)
|
||||||
|
{
|
||||||
|
$incident = AutoPresenter::decorate($event->incident);
|
||||||
|
$component = AutoPresenter::decorate($event->incident->component);
|
||||||
|
|
||||||
|
$mail = [
|
||||||
|
'email' => $subscriber->email,
|
||||||
|
'subject' => 'Scheduled maintenance.',
|
||||||
|
'has_component' => ($event->incident->component) ? true : false,
|
||||||
|
'component_name' => $component ? $component->name : null,
|
||||||
|
'status' => $incident->human_status,
|
||||||
|
'html_content' => $incident->formattedMessage,
|
||||||
|
'text_content' => $incident->message,
|
||||||
|
'token' => $subscriber->token,
|
||||||
|
'manage_link' => route('subscribe.manage', ['code' => $subscriber->verify_code]),
|
||||||
|
'unsubscribe_link' => route('subscribe.unsubscribe', ['code' => $subscriber->verify_code]),
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->mailer->queue([
|
||||||
|
'html' => 'emails.incidents.maintenance-html',
|
||||||
|
'text' => 'emails.incidents.maintenance-text',
|
||||||
|
], $mail, function (Message $message) use ($mail) {
|
||||||
|
$message->to($mail['email'])->subject($mail['subject']);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ class IncidentController extends Controller
|
|||||||
null
|
null
|
||||||
));
|
));
|
||||||
} catch (ValidationException $e) {
|
} catch (ValidationException $e) {
|
||||||
|
dd($e->getMessageBag());
|
||||||
return Redirect::route('dashboard.incidents.add')
|
return Redirect::route('dashboard.incidents.add')
|
||||||
->withInput(Binput::all())
|
->withInput(Binput::all())
|
||||||
->withTitle(sprintf('%s %s', trans('dashboard.notifications.whoops'), trans('dashboard.incidents.add.failure')))
|
->withTitle(sprintf('%s %s', trans('dashboard.notifications.whoops'), trans('dashboard.incidents.add.failure')))
|
||||||
|
|||||||
@@ -15,8 +15,10 @@ use AltThree\Validator\ValidationException;
|
|||||||
use CachetHQ\Cachet\Bus\Commands\Subscriber\SubscribeSubscriberCommand;
|
use CachetHQ\Cachet\Bus\Commands\Subscriber\SubscribeSubscriberCommand;
|
||||||
use CachetHQ\Cachet\Bus\Commands\Subscriber\UnsubscribeSubscriberCommand;
|
use CachetHQ\Cachet\Bus\Commands\Subscriber\UnsubscribeSubscriberCommand;
|
||||||
use CachetHQ\Cachet\Bus\Commands\Subscriber\UnsubscribeSubscriptionCommand;
|
use CachetHQ\Cachet\Bus\Commands\Subscriber\UnsubscribeSubscriptionCommand;
|
||||||
|
use CachetHQ\Cachet\Bus\Commands\Subscriber\UpdateSubscriberSubscriptionCommand;
|
||||||
use CachetHQ\Cachet\Bus\Commands\Subscriber\VerifySubscriberCommand;
|
use CachetHQ\Cachet\Bus\Commands\Subscriber\VerifySubscriberCommand;
|
||||||
use CachetHQ\Cachet\Bus\Exceptions\Subscriber\AlreadySubscribedException;
|
use CachetHQ\Cachet\Bus\Exceptions\Subscriber\AlreadySubscribedException;
|
||||||
|
use CachetHQ\Cachet\Models\Component;
|
||||||
use CachetHQ\Cachet\Models\Subscriber;
|
use CachetHQ\Cachet\Models\Subscriber;
|
||||||
use CachetHQ\Cachet\Models\Subscription;
|
use CachetHQ\Cachet\Models\Subscription;
|
||||||
use GrahamCampbell\Binput\Facades\Binput;
|
use GrahamCampbell\Binput\Facades\Binput;
|
||||||
@@ -57,11 +59,9 @@ class SubscribeController extends Controller
|
|||||||
$subscriptions = Binput::get('subscriptions');
|
$subscriptions = Binput::get('subscriptions');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$subscription = dispatch(new SubscribeSubscriberCommand($email, false, $subscriptions));
|
$verified = false;
|
||||||
} catch (AlreadySubscribedException $e) {
|
|
||||||
return Redirect::route('subscribe.manage', $subscription->id)
|
$subscription = dispatch(new SubscribeSubscriberCommand($email, $verified));
|
||||||
->withTitle(sprintf('<strong>%s</strong> %s', trans('dashboard.notifications.whoops'), trans('cachet.subscriber.email.failure')))
|
|
||||||
->withErrors(trans('cachet.subscriber.email.already-subscribed', ['email' => $email]));
|
|
||||||
} catch (ValidationException $e) {
|
} catch (ValidationException $e) {
|
||||||
return Redirect::route('status-page')
|
return Redirect::route('status-page')
|
||||||
->withInput(Binput::all())
|
->withInput(Binput::all())
|
||||||
@@ -69,8 +69,12 @@ class SubscribeController extends Controller
|
|||||||
->withErrors($e->getMessageBag());
|
->withErrors($e->getMessageBag());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect::route('status-page')
|
$message = $subscription->is_verified ?
|
||||||
->withSuccess(sprintf('<strong>%s</strong> %s', trans('dashboard.notifications.awesome'), trans('cachet.subscriber.email.subscribed')));
|
trans('cachet.subscriber.email.already-subscribed', ['email' => $email]) :
|
||||||
|
trans('cachet.subscriber.email.subscribed');
|
||||||
|
|
||||||
|
return Redirect::route('subscribe.manage', $subscription->verify_code)
|
||||||
|
->withSuccess(sprintf('<strong>%s</strong> %s', trans('dashboard.notifications.awesome'), $message));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,11 +92,13 @@ class SubscribeController extends Controller
|
|||||||
|
|
||||||
$subscriber = Subscriber::where('verify_code', '=', $code)->first();
|
$subscriber = Subscriber::where('verify_code', '=', $code)->first();
|
||||||
|
|
||||||
if (!$subscriber || $subscriber->is_verified) {
|
if (!$subscriber) {
|
||||||
throw new BadRequestHttpException();
|
throw new BadRequestHttpException();
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(new VerifySubscriberCommand($subscriber));
|
if (!$subscriber->is_verified) {
|
||||||
|
dispatch(new VerifySubscriberCommand($subscriber));
|
||||||
|
}
|
||||||
|
|
||||||
return Redirect::route('status-page')
|
return Redirect::route('status-page')
|
||||||
->withSuccess(sprintf('<strong>%s</strong> %s', trans('dashboard.notifications.awesome'), trans('cachet.subscriber.email.verified')));
|
->withSuccess(sprintf('<strong>%s</strong> %s', trans('dashboard.notifications.awesome'), trans('cachet.subscriber.email.verified')));
|
||||||
@@ -143,10 +149,46 @@ class SubscribeController extends Controller
|
|||||||
|
|
||||||
$subscriber = Subscriber::where('verify_code', '=', $code)->first();
|
$subscriber = Subscriber::where('verify_code', '=', $code)->first();
|
||||||
|
|
||||||
if (!$subscriber || !$subscriber->is_verified) {
|
if (!$subscriber) {
|
||||||
throw new BadRequestHttpException();
|
throw new BadRequestHttpException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return View::make('subscribe.manage')->withSubscriber($subscriber);
|
return View::make('subscribe.manage')
|
||||||
|
->withComponents(Component::all())
|
||||||
|
->withSubscriber($subscriber)
|
||||||
|
->withSubscriptions($subscriber->subscriptions->pluck('component_id')->all());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the subscription manager for a subscriber.
|
||||||
|
*
|
||||||
|
* @param string|null $code
|
||||||
|
*
|
||||||
|
* @return \Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function postManage($code = null)
|
||||||
|
{
|
||||||
|
if ($code === null) {
|
||||||
|
throw new NotFoundHttpException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$subscriber = Subscriber::where('verify_code', '=', $code)->first();
|
||||||
|
|
||||||
|
if (!$subscriber) {
|
||||||
|
throw new BadRequestHttpException();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
dispatch(new UpdateSubscriberSubscriptionCommand($subscriber, Binput::get('subscriptions')));
|
||||||
|
} catch (ValidationException $e) {
|
||||||
|
dd($e->getMessageBag());
|
||||||
|
return Redirect::route('subscribe.manage', $subscriber->verify_code)
|
||||||
|
->withInput(Binput::all())
|
||||||
|
->withTitle(sprintf('<strong>%s</strong> %s', trans('dashboard.notifications.whoops'), trans('cachet.subscriber.email.failure')))
|
||||||
|
->withErrors($e->getMessageBag());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Redirect::route('subscribe.manage', $subscriber->verify_code)
|
||||||
|
->withSuccess(sprintf('<strong>%s</strong> %s', trans('dashboard.notifications.awesome'), trans('cachet.subscriber.email.subscribed')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ class SubscribeRoutes
|
|||||||
'uses' => 'SubscribeController@showManage',
|
'uses' => 'SubscribeController@showManage',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$router->post('subscribe/manage/{code}', [
|
||||||
|
'as' => 'manage',
|
||||||
|
'uses' => 'SubscribeController@postManage',
|
||||||
|
]);
|
||||||
|
|
||||||
$router->get('subscribe/verify/{code}', [
|
$router->get('subscribe/verify/{code}', [
|
||||||
'as' => 'verify',
|
'as' => 'verify',
|
||||||
'uses' => 'SubscribeController@getVerify',
|
'uses' => 'SubscribeController@getVerify',
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class Subscriber extends Model implements HasPresenter
|
|||||||
'email' => 'string',
|
'email' => 'string',
|
||||||
'verify_code' => 'string',
|
'verify_code' => 'string',
|
||||||
'verified_at' => 'date',
|
'verified_at' => 'date',
|
||||||
|
'global' => 'bool',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -91,6 +92,33 @@ class Subscriber extends Model implements HasPresenter
|
|||||||
return $query->whereNotNull('verified_at');
|
return $query->whereNotNull('verified_at');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope global subscribers.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
public function scopeIsGlobal(Builder $query)
|
||||||
|
{
|
||||||
|
return $query->where('global', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds all verified subscriptions for a component.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||||
|
* @param int $component_id
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
public function scopeForComponent(Builder $query, $component_id)
|
||||||
|
{
|
||||||
|
return $query->select('subscribers.*')
|
||||||
|
->join('subscriptions', 'subscribers.id', '=', 'subscriptions.subscriber_id')
|
||||||
|
->where('subscriptions.component_id', $component_id);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the subscriber is verified.
|
* Determines if the subscriber is verified.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -107,7 +107,10 @@ class Subscription extends Model
|
|||||||
{
|
{
|
||||||
return $query->select('subscriptions.*')
|
return $query->select('subscriptions.*')
|
||||||
->join('subscribers', 'subscriptions.subscriber_id', '=', 'subscribers.id')
|
->join('subscribers', 'subscriptions.subscriber_id', '=', 'subscribers.id')
|
||||||
->where('component_id', $component_id)
|
->where(function ($query) {
|
||||||
|
$query->where('subscriptions.component_id', $component_id)
|
||||||
|
->orWhere('subscribers.global');
|
||||||
|
})
|
||||||
->whereNotNull('subscribers.verified_at');
|
->whereNotNull('subscribers.verified_at');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class AlterTableSubscribersAddGlobalColumn extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('subscribers', function (Blueprint $table) {
|
||||||
|
$table->boolean('global')->after('verified_at')->default(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('subscribers', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('global');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
8
resources/assets/sass/_helpers.scss
vendored
8
resources/assets/sass/_helpers.scss
vendored
@@ -1,3 +1,11 @@
|
|||||||
.uppercase {
|
.uppercase {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.margin-top {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-bottom {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,7 +13,4 @@
|
|||||||
<p>
|
<p>
|
||||||
<small><a href="{{ $manage_link }}">{!! trans('cachet.subscriber.email.manage') !!}</a></small>
|
<small><a href="{{ $manage_link }}">{!! trans('cachet.subscriber.email.manage') !!}</a></small>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
|
||||||
<small><a href="{{ $unsubscribe_link }}">{!! trans('cachet.subscriber.email.unsubscribe') !!}</a></small>
|
|
||||||
</p>
|
|
||||||
@stop
|
@stop
|
||||||
|
|||||||
@@ -5,5 +5,3 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
{!! trans('cachet.subscriber.email.manage') !!} {{ $manage_link }}
|
{!! trans('cachet.subscriber.email.manage') !!} {{ $manage_link }}
|
||||||
|
|
||||||
{!! trans('cachet.subscriber.email.unsubscribe') !!} {{ $unsubscribe_link }}
|
|
||||||
|
|||||||
@@ -9,21 +9,51 @@
|
|||||||
|
|
||||||
@include('dashboard.partials.errors')
|
@include('dashboard.partials.errors')
|
||||||
|
|
||||||
<div class="panel panel-default">
|
<div class="row">
|
||||||
<div class="panel-heading"><strong>{{ $subscriber->email }}</strong></div>
|
<div class="col-xs-12 col-lg-offset-2 col-lg-8">
|
||||||
@if($subscriber->subscriptions->count() > 0)
|
<div class="text-center margin-bottom">
|
||||||
<div class="panel-body">
|
<h1>{{ $app_name }} Notifications</h1>
|
||||||
<p>{{ trans('cachet.subscriber.manage.my_subscriptions') }}</p>
|
<p>
|
||||||
|
Manage notifications for {{ $subscriber->email }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
@if($components->count() > 0)
|
||||||
|
<form action="{{ route('subscribe.manage', $subscriber->verify_code) }}" method="post">
|
||||||
|
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
{{ trans('cachet.subscriber.manage.my_subscriptions') }}
|
||||||
|
</div>
|
||||||
|
<div class="list-group">
|
||||||
|
@foreach($components as $component)
|
||||||
|
<div class="list-group-item">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label for="component-{{ $component->id }}">
|
||||||
|
<input type="checkbox"
|
||||||
|
id="component-{{ $component->id }}"
|
||||||
|
name="subscriptions[]"
|
||||||
|
value="{{ $component->id }}"
|
||||||
|
@if (in_array($component->id, $subscriptions) || $subscriber->global)
|
||||||
|
checked="checked"
|
||||||
|
@endif>
|
||||||
|
{{ $component->name }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-right">
|
||||||
|
<button type="submit" class="btn btn-success">Update Subscription</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
@else
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-body">
|
||||||
|
<p>{{ trans('cachet.subscriber.manage.no_subscriptions') }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="list-group">
|
|
||||||
@foreach($subscriber->subscriptions as $subscription)
|
|
||||||
<div class="list-group-item">{{ $subscription->component->name }}</div>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
@else
|
|
||||||
<div class="panel-body">
|
|
||||||
<p>{{ trans('cachet.subscriber.manage.no_subscriptions') }}</p>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
</div>
|
</div>
|
||||||
@stop
|
@stop
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ class SubscribeSubscriberCommandTest extends AbstractTestCase
|
|||||||
|
|
||||||
protected function getObjectAndParams()
|
protected function getObjectAndParams()
|
||||||
{
|
{
|
||||||
$params = ['email' => 'support@cachethq.io', 'verified' => true, 'subscriptions' => null];
|
$params = ['email' => 'support@cachethq.io', 'verified' => true];
|
||||||
$object = new SubscribeSubscriberCommand($params['email'], $params['verified'], $params['subscriptions']);
|
$object = new SubscribeSubscriberCommand($params['email'], $params['verified']);
|
||||||
|
|
||||||
return compact('params', 'object');
|
return compact('params', 'object');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user