FcmChannel::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace NotificationChannels\Fcm;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Exception\RequestException;
7
use Illuminate\Notifications\Notification;
8
use NotificationChannels\Fcm\Exceptions\CouldNotSendNotification;
9
10
class FcmChannel
11
{
12
    const DEFAULT_API_URL = 'https://fcm.googleapis.com';
13
    const MAX_TOKEN_PER_REQUEST = 1000;
14
15
    /**
16
     * @var Client
17
     */
18
    protected $client;
19
20
    public function __construct(Client $client)
21
    {
22
        $this->client = $client;
23
    }
24
25
    /**
26
     * Send the given notification.
27
     *
28
     * @param mixed $notifiable
29
     * @param \Illuminate\Notifications\Notification $notification
30
     *
31
     * @throws \NotificationChannels\Fcm\Exceptions\CouldNotSendNotification
32
     */
33
    public function send($notifiable, Notification $notification)
34
    {
35
        // Get the token/s from the model
36
        if (! $notifiable->routeNotificationFor('fcm')) {
37
            return;
38
        }
39
        $tokens = (array) $notifiable->routeNotificationFor('fcm');
40
41
        if (empty($tokens)) {
42
            return;
43
        }
44
45
        // Get the message from the notification class
46
        $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...
47
48
        if (empty($fcmMessage)) {
49
            return;
50
        }
51
52
        if (count($tokens) == 1) {
53
            // Do not use multicast if there is only one recipient
54
            $fcmMessage->setTo($tokens[0]);
55
            $this->sendToFcm($fcmMessage);
56
        } else {
57
            // Use multicast because there are multiple recipients
58
            $partialTokens = array_chunk($tokens, self::MAX_TOKEN_PER_REQUEST, false);
59
            foreach ($partialTokens as $tokens) {
60
                $fcmMessage->setRegistrationIds($tokens);
61
                $this->sendToFcm($fcmMessage);
62
            }
63
        }
64
    }
65
66
    protected function sendToFcm($fcmMessage)
67
    {
68
        try {
69
            $this->client->request('POST', '/fcm/send', [
70
                'headers' => $this->getClientHeaders($fcmMessage),
71
                'body' => $fcmMessage->toJson(),
72
            ]);
73
        } catch (RequestException $requestException) {
74
            throw CouldNotSendNotification::serviceRespondedWithAnError($requestException);
75
        }
76
    }
77
78
    /**
79
     * This is used to get the headers for the FCM request. We can add customization to the headers here.
80
     *
81
     * @param FcmMessage $fcmMessage
82
     * @return array
83
     */
84
    protected function getClientHeaders(FcmMessage $fcmMessage)
85
    {
86
        $headers = [
87
            'Authorization' => sprintf('key=%s', config('broadcasting.connections.fcm.key')),
88
            'Content-Type' => 'application/json',
89
        ];
90
91
        // Override the FCM key from the config
92
        if (! empty($fcmMessage->getFcmKey())) {
93
            $headers['Authorization'] = sprintf('key=%s', $fcmMessage->getFcmKey());
94
        }
95
96
        return $headers;
97
    }
98
}
99