Completed
Push — master ( 6ee4e9...166b13 )
by dan
02:00
created

ChannelManager.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace IrishDan\NotificationBundle;
4
5
use InvalidArgumentException;
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\Debug\TraceableEventDispatcher;
13
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
14
15
/**
16
 * Class ChannelManager
17
 *
18
 * @package NotificationBundle\Utils
19
 */
20
class ChannelManager
21
{
22
    /**
23
     * @var array
24
     */
25
    protected $channels = [];
26
    protected $eventDispatcher;
27
    /**
28
     * @var array
29
     */
30
    protected $configuredChannels;
31
32
    public function __construct(EventDispatcherInterface $eventDispatcher, array $configuredChannels)
33
    {
34
        $this->eventDispatcher    = $eventDispatcher;
35
        $this->configuredChannels = $configuredChannels;
36
        // @TODO:
37
        $this->configuredChannels[] = 'slack_channel';
38
    }
39
40
    /**
41
     * @param array $recipients
42
     *
43
     * @return array
44
     */
45
    protected function formatRecipients(array $recipients)
46
    {
47
        foreach ($recipients as $key => $recipient) {
48
            if (!$recipient instanceof NotifiableInterface) {
49
                unset($recipients[$key]);
50
            }
51
        }
52
53
        return $recipients;
54
    }
55
56
    /**
57
     * @param array                 $notifiables
58
     * @param NotificationInterface $notification
59
     */
60
    public function send(array $notifiables, NotificationInterface $notification)
61
    {
62
        $notifiables = $this->formatRecipients($notifiables);
63
        $this->sendNow($notifiables, $notification);
64
    }
65
66
    public function sendNow(array $recipients, NotificationInterface $notification)
67
    {
68
        // Clone the original notification as will need a copy for each recipient;
69
        $original = clone $notification;
70
71
        // Set a uuid so notifications from different channels can be grouped.
72
        // Needed when marking as read across all channels.
73
        $uuid = uniqid();
74
75
76
        foreach ($recipients as $notifiable) {
77
            // Get all of the channels the notification would like to be send on.
78
            // Then check each channel against what is configured in the system,
79
            // and which channels the notifiable is subscribed to.
80
            $viaChannels = $notification->getChannels();
81
            if (empty($viaChannels)) {
82
                $viaChannels = $this->configuredChannels;
83
            }
84
85
            foreach ($viaChannels as $channel) {
86
                if (!$this->shouldSendNotification($notifiable, $notification, $channel)) {
87
                    continue;
88
                }
89
90
                $currentNotification = clone $original;
91
                $this->formatNotification($notifiable, $currentNotification, $channel, $uuid);
92
93
                try {
94
                    // Dispatch sending event.
95
                    $sendingEvent = new NotificationSendingEvent($currentNotification);
96
                    $this->eventDispatcher->dispatch(NotificationSendingEvent::NAME, $sendingEvent);
97
98
99
                    // @TODO: Perhaps send is the only method that should be in the interface
100
                    // @TODO: or, use formatthe message and dispatch
101
                    // ->formatAndDispatch
102
                    // $response = $this->channels[$channel]->send($currentNotification);
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
103
                    $message  = $this->channels[$channel]->format($currentNotification);
104
                    $response = $this->channels[$channel]->dispatch($message);
105
106
107
                    if ($response) {
108
                        // Dispatch sent event.
109
                        $successEvent = new NotificationSentEvent($currentNotification);
110
                        $this->eventDispatcher->dispatch(NotificationSentEvent::NAME, $successEvent);
111
                    }
112
                } catch (\Exception $exception) {
113
                    // Dispatch sending failed event.
114
                    $successEvent = new NotificationFailedEvent($currentNotification);
115
                    $this->eventDispatcher->dispatch(NotificationFailedEvent::NAME, $successEvent);
116
117
                    throw $exception;
118
                }
119
            }
120
        }
121
    }
122
123
    /**
124
     * Based on the available channels (configured in system),
125
     * the notifiable's subscribed channels,
126
     * and the nofications
127
     * determines if the notification can be sent.
128
     *
129
     * @param  mixed  $notifiable
130
     * @param  mixed  $notification
131
     * @param  string $channel
132
     *
133
     * @return bool
134
     */
135
    protected function shouldSendNotification(NotifiableInterface $notifiable, NotificationInterface $notification, $channel)
136
    {
137
        $notifiableChannels = $notifiable->getSubscribedChannels();
138
        $configuredChannels = $notification->getChannels();
139
140
        if (
141
            in_array($channel, $configuredChannels)
142
            && in_array($channel, $notifiableChannels)
143
            && in_array($channel . '_channel', $this->configuredChannels)
144
            && in_array($channel, array_keys($this->channels))
145
        ) {
146
            return true;
147
        }
148
149
        return false;
150
    }
151
152
    /**
153
     * @param NotifiableInterface   $notifiable
154
     * @param NotificationInterface $notification
155
     * @param                       $channel
156
     */
157
    protected function formatNotification(NotifiableInterface $notifiable, NotificationInterface $notification, $channel, $uuid)
158
    {
159
        $notification->setNotifiable($notifiable);
160
        $notification->setChannel($channel);
161
        $notification->setUuid($uuid);
162
    }
163
164
    /**
165
     * Get a channel service
166
     *
167
     * @param  string|null $name
168
     *
169
     * @return mixed
170
     */
171
    public function getChannel($name = null)
172
    {
173
        return empty($this->channels[$name]) ? null : $this->channels[$name];
174
    }
175
176
    /**
177
     * @param                  $channelName
178
     * @param ChannelInterface $channel
179
     */
180
    public function setChannel($channelName, ChannelInterface $channel)
181
    {
182
        $this->channels[$channelName] = $channel;
183
    }
184
}
185