ChannelManager::formatNotification()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 4
1
<?php
2
3
namespace IrishDan\NotificationBundle;
4
5
6
use IrishDan\NotificationBundle\Channel\ChannelInterface;
7
use IrishDan\NotificationBundle\Event\NotificationFailedEvent;
8
use IrishDan\NotificationBundle\Event\NotificationSentEvent;
9
use IrishDan\NotificationBundle\Notification\NotifiableInterface;
10
use IrishDan\NotificationBundle\Notification\NotificationInterface;
11
use IrishDan\NotificationBundle\Event\NotificationSendingEvent;
12
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
13
14
/**
15
 * Class ChannelManager
16
 *
17
 * @package NotificationBundle\Utils
18
 */
19
class ChannelManager
20
{
21
    protected $channels = [];
22
    protected $eventDispatcher;
23
    protected $configuredChannels;
24
25
    public function __construct(EventDispatcherInterface $eventDispatcher, array $configuredChannels)
26
    {
27
        $this->eventDispatcher = $eventDispatcher;
28
        $this->configuredChannels = $configuredChannels;
29
    }
30
31
    /**
32
     * @param array $recipients
33
     * @return array
34
     */
35
    protected function formatRecipients(array $recipients)
36
    {
37
        foreach ($recipients as $key => $recipient) {
38
            if (!$recipient instanceof NotifiableInterface) {
39
                unset($recipients[$key]);
40
            }
41
        }
42
43
        return $recipients;
44
    }
45
46
    /**
47
     * @param array                 $notifiables
48
     * @param NotificationInterface $notification
49
     */
50
    public function send(array $notifiables, NotificationInterface $notification)
51
    {
52
        $notifiables = $this->formatRecipients($notifiables);
53
        $this->sendNow($notifiables, $notification);
54
    }
55
56
    public function sendNow(array $recipients, NotificationInterface $notification)
57
    {
58
        // Clone the original notification as will need a copy for each recipient;
59
        $original = clone $notification;
60
61
        // Set a uuid so notifications from different channels can be grouped.
62
        // Needed when marking as read across all channels.
63
        $uuid = uniqid();
64
65
        foreach ($recipients as $notifiable) {
66
            // Get all of the channels the notification would like to be send on.
67
            // Then check each channel against what is configured in the system,
68
            // and which channels the notifiable is subscribed to.
69
            $viaChannels = $notification->getChannels();
70
            foreach ($viaChannels as $channel) {
71
                if (!$this->shouldSendNotification($notifiable, $notification, $channel)) {
72
                    continue;
73
                }
74
75
                $currentNotification = clone $original;
76
                $this->formatNotification($notifiable, $currentNotification, $channel, $uuid);
77
78
                try {
79
                    // Dispatch sending event.
80
                    $sendingEvent = new NotificationSendingEvent($currentNotification);
81
                    $this->eventDispatcher->dispatch(NotificationSendingEvent::NAME, $sendingEvent);
82
83
                    $response = $this->channels[$channel]->formatAndDispatch($currentNotification);
84
85
                    if ($response) {
86
                        // Dispatch sent event.
87
                        $successEvent = new NotificationSentEvent($currentNotification);
88
                        $this->eventDispatcher->dispatch(NotificationSentEvent::NAME, $successEvent);
89
                    }
90
                } catch (\Exception $exception) {
91
                    // Dispatch sending failed event.
92
                    $successEvent = new NotificationFailedEvent($currentNotification);
93
                    $this->eventDispatcher->dispatch(NotificationFailedEvent::NAME, $successEvent);
94
95
                    throw $exception;
96
                }
97
            }
98
        }
99
    }
100
101
    /**
102
     * Based on the available channels (configured in system) the notifiable's subscribed channels,
103
     * and the nofications determines if the notification can be sent.
104
     *
105
     * @param  mixed  $notifiable
106
     * @param  mixed  $notification
107
     * @param  string $channel
108
     * @return bool
109
     */
110
    protected function shouldSendNotification(NotifiableInterface $notifiable, NotificationInterface $notification, $channel)
111
    {
112
        $notifiableChannels = $notifiable->getSubscribedChannels();
113
        $configuredChannels = $notification->getChannels();
114
115
        if (
116
            in_array($channel, $configuredChannels)
117
            && in_array($channel, $notifiableChannels)
118
            && in_array($channel, $this->configuredChannels)
119
            && in_array($channel, array_keys($this->channels))
120
        ) {
121
            return true;
122
        }
123
124
        return false;
125
    }
126
127
    /**
128
     * @param NotifiableInterface   $notifiable
129
     * @param NotificationInterface $notification
130
     * @param                       $channel
131
     */
132
    protected function formatNotification(NotifiableInterface $notifiable, NotificationInterface $notification, $channel, $uuid)
133
    {
134
        $notification->setNotifiable($notifiable);
135
        $notification->setChannel($channel);
136
        $notification->setUuid($uuid);
137
    }
138
139
    /**
140
     * Get a channel service
141
     *
142
     * @param  string|null $name
143
     * @return mixed
144
     */
145
    public function getChannel($name = null)
146
    {
147
        return empty($this->channels[$name]) ? null : $this->channels[$name];
148
    }
149
150
    /**
151
     * @param                  $channelName
152
     * @param ChannelInterface $channel
153
     */
154
    public function setChannel($channelName, ChannelInterface $channel)
155
    {
156
        $this->channels[$channelName] = $channel;
157
    }
158
}
159