Completed
Push — master ( df9f00...ccd20f )
by dan
01:37
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
27
    protected $eventDispatcher;
28
    /**
29
     * @var array
30
     */
31
    protected $configuredChannels;
32
33
    public function __construct(EventDispatcherInterface $eventDispatcher, array $configuredChannels)
34
    {
35
        $this->eventDispatcher = $eventDispatcher;
36
        $this->configuredChannels = $configuredChannels;
37
    }
38
39
    /**
40
     * @param array $recipients
41
     * @return array
42
     */
43
    protected function formatRecipients(array $recipients)
44
    {
45
        foreach ($recipients as $key => $recipient) {
46
            if (!$recipient instanceof NotifiableInterface) {
47
                unset($recipients[$key]);
48
            }
49
        }
50
51
        return $recipients;
52
    }
53
54
    /**
55
     * @param array                 $notifiables
56
     * @param NotificationInterface $notification
57
     */
58
    public function send(array $notifiables, NotificationInterface $notification)
59
    {
60
        $notifiables = $this->formatRecipients($notifiables);
61
        $this->sendNow($notifiables, $notification);
62
    }
63
64
    public function sendNow(array $recipients, NotificationInterface $notification)
65
    {
66
        // Clone the original notification as will need a copy for each recipient;
67
        $original = clone $notification;
68
69
        // Set a uuid so notifications from different channels can be grouped.
70
        // Needed when marking as read across all channels.
71
        $uuid = uniqid();
72
73
        foreach ($recipients as $notifiable) {
74
            // Get all of the channels the notification would like to be send on.
75
            // Then check each channel against what is configured in the system,
76
            // and which channels the notifiable is subscribed to.
77
            $viaChannels = $notification->getChannels();
78
            if (empty($viaChannels)) {
79
                $viaChannels = $this->configuredChannels;
80
            }
81
82
            foreach ($viaChannels as $channel) {
83
                if (!$this->shouldSendNotification($notifiable, $notification, $channel)) {
84
                    continue;
85
                }
86
87
                $currentNotification = clone $original;
88
                $this->formatNotification($notifiable, $currentNotification, $channel, $uuid);
89
90
                try {
91
                    // Dispatch sending event.
92
                    $sendingEvent = new NotificationSendingEvent($currentNotification);
93
                    $this->eventDispatcher->dispatch(NotificationSendingEvent::NAME, $sendingEvent);
94
95
96
                    // @TODO: Perhaps send is the only method that should be in the interface
97
                    // @TODO: or, use formatthe message and dispatch
98
                    // $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...
99
                    $message = $this->channels[$channel]->format($currentNotification);
100
                    $response = $this->channels[$channel]->dispatch($message);
101
102
103
                    if ($response) {
104
                        // Dispatch sent event.
105
                        $successEvent = new NotificationSentEvent($currentNotification);
106
                        $this->eventDispatcher->dispatch(NotificationSentEvent::NAME, $successEvent);
107
                    }
108
                } catch (\Exception $exception) {
109
                    // Dispatch sending failed event.
110
                    $successEvent = new NotificationFailedEvent($currentNotification);
111
                    $this->eventDispatcher->dispatch(NotificationFailedEvent::NAME, $successEvent);
112
113
                    throw $exception;
114
                }
115
            }
116
        }
117
    }
118
119
    /**
120
     * Based on the available channels (configured in system),
121
     * the notifiable's subscribed channels,
122
     * and the nofications
123
     * determines if the notification can be sent.
124
     *
125
     * @param  mixed  $notifiable
126
     * @param  mixed  $notification
127
     * @param  string $channel
128
     * @return bool
129
     */
130
    protected function shouldSendNotification(NotifiableInterface $notifiable, NotificationInterface $notification, $channel)
131
    {
132
        $notifiableChannels = $notifiable->getSubscribedChannels();
133
        $configuredChannels = $notification->getChannels();
134
135
        if (
136
            in_array($channel, $configuredChannels)
137
            && in_array($channel, $notifiableChannels)
138
            && in_array($channel . '_channel', $this->configuredChannels)
139
            && in_array($channel, array_keys($this->channels))
140
        ) {
141
            return true;
142
        }
143
144
        return false;
145
    }
146
147
    /**
148
     * @param NotifiableInterface   $notifiable
149
     * @param NotificationInterface $notification
150
     * @param                       $channel
151
     */
152
    protected function formatNotification(NotifiableInterface $notifiable, NotificationInterface $notification, $channel, $uuid)
153
    {
154
        $notification->setNotifiable($notifiable);
155
        $notification->setChannel($channel);
156
        $notification->setUuid($uuid);
157
    }
158
159
    /**
160
     * Get a channel service
161
     *
162
     * @param  string|null $name
163
     * @return mixed
164
     */
165
    public function getChannel($name = null)
166
    {
167
        return empty($this->channels[$name]) ? null : $this->channels[$name];
168
    }
169
170
    /**
171
     * @param                  $channelName
172
     * @param ChannelInterface $channel
173
     */
174
    public function setChannel($channelName, ChannelInterface $channel)
175
    {
176
        $this->channels[$channelName] = $channel;
177
    }
178
}
179