Notifier::getChannelInstance()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 9
rs 10
cc 3
nc 3
nop 1
1
<?php
2
/**
3
 * @copyright Anton Tuyakhov <[email protected]>
4
 */
5
6
namespace tuyakhov\notifications;
7
use tuyakhov\notifications\channels\ChannelInterface;
8
use tuyakhov\notifications\events\NotificationEvent;
9
use yii\base\Component;
10
use yii\base\InvalidConfigException;
11
12
/**
13
 * Class Notifier is a component that can send multiple notifications to multiple recipients using available channels
14
 *
15
 * The following example shows how to create a Notifier instance and send your first notification:
16
 *
17
 * ```php
18
 * $notifier = new \tuyakhov\notifications\Notifier([
19
 *     'channels' => [...],
20
 * ]);
21
 * $notifier->send($recipients, $notifications);
22
 * ```
23
 *
24
 * Notifier is often used as an application component and configured in the application configuration like the following:
25
 *
26
 * ```php
27
 * [
28
 *      'components' => [
29
 *          'notifier' => [
30
 *              'class' => '\tuyakhov\notifications\Notifier',
31
 *              'channels' => [
32
 *                  'mail' => [
33
 *                      'class' => '\tuyakhov\notifications\channels\MailChannel',
34
 *                  ]
35
 *              ],
36
 *          ],
37
 *      ],
38
 * ]
39
 * ```
40
 * @package common\notifications
41
 */
42
class Notifier extends Component
43
{
44
    /**
45
     * @event NotificationEvent an event raised right after notification has been sent.
46
     */
47
    const EVENT_AFTER_SEND = 'afterSend';
48
49
    /**
50
     * @var array defines available channels
51
     * The syntax is like the following:
52
     *
53
     * ```php
54
     * [
55
     *     'mail' => [
56
     *         'class' => 'MailChannel',
57
     *     ],
58
     * ]
59
     * ```
60
     */
61
    public $channels = [];
62
63
    /**
64
     * Sends the given notifications through available channels to the given notifiable entities.
65
     * You may pass an array in order to send multiple notifications to multiple recipients.
66
     * 
67
     * @param array|NotifiableInterface $recipients the recipients that can receive given notifications.
68
     * @param array|NotificationInterface $notifications the notification that should be delivered.
69
     * @return void
70
     * @throws InvalidConfigException
71
     */
72
    public function send($recipients, $notifications)
73
    {
74
        if (!is_array($recipients)) {
75
            /**
76
             * @var $recipients NotifiableInterface[]
77
             */
78
            $recipients = [$recipients];
79
        }
80
        
81
        if (!is_array($notifications)){
82
            /**
83
             * @var $notifications NotificationInterface[]
84
             */
85
            $notifications = [$notifications];
86
        }
87
        
88
        foreach ($recipients as $recipient) {
89
            $channels = array_intersect($recipient->viaChannels(), array_keys($this->channels));
90
            foreach ($notifications as $notification) {
91
                if (!$recipient->shouldReceiveNotification($notification)) {
92
                    continue;
93
                }
94
95
                $channels = array_intersect($channels, $notification->broadcastOn());
96
                foreach ($channels as $channel) {
97
                    $channelInstance = $this->getChannelInstance($channel);
98
                    try {
99
                        \Yii::info("Sending notification " . get_class($notification) . " to " . get_class($recipient) . " via {$channel}", __METHOD__);
100
                        $response = $channelInstance->send($recipient, $notification);
101
                    } catch (\Exception $e) {
102
                        $response = $e;
103
                    }
104
                    $this->trigger(self::EVENT_AFTER_SEND, new NotificationEvent([
105
                        'notification' => $notification,
106
                        'recipient' => $recipient,
107
                        'channel' => $channel,
108
                        'response' => $response
109
                    ]));
110
                }
111
            }
112
        }
113
    }
114
115
    /**
116
     * Returns channel instance
117
     * @param string $channel the channel name
118
     * @return ChannelInterface
119
     * @throws InvalidConfigException
120
     */
121
    protected function getChannelInstance($channel)
122
    {
123
        if (!isset($this->channels[$channel])) {
124
            throw new InvalidConfigException("Notification channel `{$channel}` is not available or configuration is missing");
125
        }
126
        if (!$this->channels[$channel] instanceof ChannelInterface) {
127
            $this->channels[$channel] = \Yii::createObject($this->channels[$channel]);
128
        }
129
        return $this->channels[$channel];
130
    }
131
}