Completed
Push — master ( 8b95cd...58fbcc )
by Atymic
01:03
created

FcmChannel::messaging()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
3
namespace NotificationChannels\Fcm;
4
5
use Illuminate\Contracts\Container\BindingResolutionException;
6
use Illuminate\Contracts\Events\Dispatcher;
7
use Illuminate\Notifications\Events\NotificationFailed;
8
use Illuminate\Notifications\Notification;
9
use Kreait\Firebase\Exception\MessagingException;
10
use Kreait\Firebase\Messaging\CloudMessage;
11
use Kreait\Firebase\Messaging\Message;
12
use NotificationChannels\Fcm\Exceptions\CouldNotSendNotification;
13
use Throwable;
14
15
class FcmChannel
16
{
17
    const MAX_TOKEN_PER_REQUEST = 500;
18
19
    /**
20
     * @var \Illuminate\Contracts\Events\Dispatcher
21
     */
22
    protected $events;
23
24
    /**
25
     * FcmChannel constructor.
26
     *
27
     * @param \Illuminate\Contracts\Events\Dispatcher $dispatcher
28
     */
29
    public function __construct(Dispatcher $dispatcher)
30
    {
31
        $this->events = $dispatcher;
32
    }
33
34
    /**
35
     * @var string|null
36
     */
37
    protected $fcmProject = null;
38
39
    /**
40
     * Send the given notification.
41
     *
42
     * @param mixed $notifiable
43
     * @param \Illuminate\Notifications\Notification $notification
44
     *
45
     * @return array
46
     * @throws \NotificationChannels\Fcm\Exceptions\CouldNotSendNotification
47
     * @throws \Kreait\Firebase\Exception\FirebaseException
48
     */
49
    public function send($notifiable, Notification $notification)
50
    {
51
        $token = $notifiable->routeNotificationFor('fcm', $notification);
52
53
        if (empty($token)) {
54
            return [];
55
        }
56
57
        // Get the message from the notification class
58
        $fcmMessage = $notification->toFcm($notifiable);
0 ignored issues
show
Bug introduced by
The method toFcm() does not seem to exist on object<Illuminate\Notifications\Notification>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
59
60
        if (! $fcmMessage instanceof Message) {
61
            throw CouldNotSendNotification::invalidMessage();
62
        }
63
64
        $this->fcmProject = null;
65
        if (method_exists($notification, 'fcmProject')) {
66
            $this->fcmProject = $notification->fcmProject($notifiable, $fcmMessage);
0 ignored issues
show
Bug introduced by
The method fcmProject() does not seem to exist on object<Illuminate\Notifications\Notification>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
67
        }
68
69
        $responses = [];
70
71
        try {
72
            if (is_array($token)) {
73
                // Use multicast when there are multiple recipients
74
                $partialTokens = array_chunk($token, self::MAX_TOKEN_PER_REQUEST, false);
75
                foreach ($partialTokens as $tokens) {
76
                    $responses[] = $this->sendToFcmMulticast($fcmMessage, $tokens);
77
                }
78
            } else {
79
                $responses[] = $this->sendToFcm($fcmMessage, $token);
80
            }
81
        } catch (MessagingException $exception) {
82
            $this->failedNotification($notifiable, $notification, $exception);
83
            throw CouldNotSendNotification::serviceRespondedWithAnError($exception);
84
        }
85
86
        return $responses;
87
    }
88
89
    /**
90
     * @return \Kreait\Firebase\Messaging
91
     */
92
    protected function messaging()
93
    {
94
        try {
95
            $messaging = app('firebase.manager')->project($this->fcmProject)->messaging();
96
        } catch (BindingResolutionException $e) {
97
            $messaging = app('firebase.messaging');
98
        }
99
100
        return $messaging;
101
    }
102
103
    /**
104
     * @param \Kreait\Firebase\Messaging\Message $fcmMessage
105
     * @param $token
106
     * @return array
107
     * @throws \Kreait\Firebase\Exception\MessagingException
108
     * @throws \Kreait\Firebase\Exception\FirebaseException
109
     */
110
    protected function sendToFcm(Message $fcmMessage, $token)
111
    {
112
        if ($fcmMessage instanceof CloudMessage) {
113
            $fcmMessage = $fcmMessage->withChangedTarget('token', $token);
114
        }
115
116
        if ($fcmMessage instanceof FcmMessage) {
117
            $fcmMessage->setToken($token);
118
        }
119
120
        return $this->messaging()->send($fcmMessage);
121
    }
122
123
    /**
124
     * @param $fcmMessage
125
     * @param array $tokens
126
     * @return \Kreait\Firebase\Messaging\MulticastSendReport
127
     * @throws \Kreait\Firebase\Exception\MessagingException
128
     * @throws \Kreait\Firebase\Exception\FirebaseException
129
     */
130
    protected function sendToFcmMulticast($fcmMessage, array $tokens)
131
    {
132
        return $this->messaging()->sendMulticast($fcmMessage, $tokens);
133
    }
134
135
    /**
136
     * Dispatch failed event.
137
     *
138
     * @param mixed $notifiable
139
     * @param \Illuminate\Notifications\Notification $notification
140
     * @param \Throwable $exception
141
     * @return array|null
142
     */
143
    protected function failedNotification($notifiable, Notification $notification, Throwable $exception)
144
    {
145
        return $this->events->dispatch(new NotificationFailed(
146
            $notifiable,
147
            $notification,
148
            self::class,
149
            [
150
                'message' => $exception->getMessage(),
151
                'exception' => $exception,
152
            ]
153
        ));
154
    }
155
}
156