Completed
Pull Request — develop (#7)
by Romain
01:41
created

Fcm   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 298
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
wmc 21
lcom 1
cbo 8
dl 0
loc 298
rs 10
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 2
A getTokens() 0 4 1
A setTokens() 0 7 1
A getNotification() 0 4 1
A setNotification() 0 6 1
A getData() 0 4 1
A setData() 0 6 1
A getOptions() 0 4 1
A setOptions() 0 6 1
A getPayload() 0 14 3
A _checkTokens() 0 6 3
A _getMessage() 0 17 4
A _getHttpOptions() 0 12 1
1
<?php
2
namespace ker0x\Push\Adapter\Fcm;
3
4
use Cake\Core\Configure;
5
use Cake\Core\InstanceConfigTrait;
6
use Cake\Utility\Hash;
7
use ker0x\Push\Adapter\Fcm\Message\Data;
8
use ker0x\Push\Adapter\Fcm\Message\Exception\InvalidTokenException;
9
use ker0x\Push\Adapter\Fcm\Message\Notification;
10
use ker0x\Push\Adapter\Fcm\Message\Options;
11
use ker0x\Push\Adapter\InvalidAdapterException;
12
13
class Fcm
14
{
15
16
    use InstanceConfigTrait;
17
18
    /**
19
     * Array for devices's token
20
     *
21
     * @var array
22
     */
23
    protected $tokens = [];
24
25
    /**
26
     * Array for the notification
27
     *
28
     * @var array
29
     */
30
    protected $notification = [];
31
32
    /**
33
     * Array of data
34
     *
35
     * @var array
36
     */
37
    protected $data = [];
38
39
    /**
40
     * Array of request options
41
     *
42
     * @var array
43
     */
44
    protected $options = [];
45
46
    /**
47
     * Array of payload
48
     *
49
     * @var array
50
     */
51
    protected $payload = [];
52
53
    /**
54
     * Response of the request
55
     *
56
     * @var \Cake\Http\Client\Response
57
     */
58
    protected $response;
59
60
    /**
61
     * Default config
62
     *
63
     * @var array
64
     */
65
    protected $_defaultConfig = [
66
        'options' => [
67
            'collapse_key' => null,
68
            'priority' => 'normal',
69
            'dry_run' => false,
70
            'time_to_live' => 0,
71
            'restricted_package_name' => null,
72
        ],
73
        'http' => [],
74
    ];
75
76
    /**
77
     * List of keys allowed to be used in notification array.
78
     *
79
     * @var array
80
     */
81
    protected $_allowedNotificationKeys = [
82
        'title',
83
        'body',
84
        'icon',
85
        'sound',
86
        'badge',
87
        'tag',
88
        'color',
89
        'click_action',
90
        'body_loc_key',
91
        'body_loc_args',
92
        'title_loc_key',
93
        'title_loc_args',
94
    ];
95
96
    /**
97
     * FcmAdapter constructor.
98
     *
99
     * @throws \ker0x\Push\Adapter\Exception\InvalidAdapterException
100
     */
101
    public function __construct()
102
    {
103
        $config = Configure::read('Push.adapters.Fcm');
104
        $this->config($config);
105
106
        if ($this->config('api.key') === null) {
107
            throw InvalidAdapterException::noApiKey();
108
        }
109
    }
110
111
    /**
112
     * Getter for tokens
113
     *
114
     * @return array
115
     */
116
    public function getTokens()
117
    {
118
        return $this->tokens;
119
    }
120
121
    /**
122
     * Setter for tokens
123
     *
124
     * @param array $tokens Array of devices's token
125
     * @return $this
126
     */
127
    public function setTokens(array $tokens)
128
    {
129
        $this->_checkTokens($tokens);
130
        $this->tokens = $tokens;
131
132
        return $this;
133
    }
134
135
    /**
136
     * Getter for payload notification
137
     *
138
     * @return array
139
     */
140
    public function getNotification()
141
    {
142
        return $this->notification;
143
    }
144
145
    /**
146
     * Setter for payload notification
147
     *
148
     * Authorized keys for the notification are:
149
     *
150
     * - `title` Indicates notification title.
151
     * - `body` Indicates notification body text.
152
     * - `badge` Indicates the badge on the client app home icon. (iOS)
153
     * - `icon` Indicates notification icon. (Android)
154
     * - `sound` Indicates a sound to play when the device receives a notification.
155
     * - `tag` Indicates whether each notification results in a new entry in the
156
     *   notification drawer on Android. (Android)
157
     * - `color` Indicates color of the icon, expressed in #rrggbb format. (Android)
158
     * - `click_action` Indicates the action associated with a user click on the notification.
159
     * - `body_loc_key` Indicates the key to the body string for localization.
160
     * - `body_loc_args` Indicates the string value to replace format specifiers in the
161
     *   body string for localization.
162
     * - `title_loc_key` Indicates the key to the title string for localization.
163
     * - `title_loc_args` Indicates the string value to replace format specifiers in
164
     *   the title string for localization.
165
     *
166
     * @param array|\ker0x\Push\Adapter\Fcm\Message\NotificationBuilder $notification Array of keys for the notification
167
     * @return $this
168
     */
169
    public function setNotification($notification)
170
    {
171
        $this->notification = (new Notification($notification))->build();
172
173
        return $this;
174
    }
175
176
    /**
177
     * Getter for payload data
178
     *
179
     * @return array
180
     */
181
    public function getData()
182
    {
183
        return $this->data;
184
    }
185
186
    /**
187
     * Setter for payload data
188
     *
189
     * @param array $data Array of data for the push
190
     * @return $this
191
     */
192
    public function setData($data)
193
    {
194
        $this->data = (new Data($data))->build();
195
196
        return $this;
197
    }
198
199
    /**
200
     * Getter for payload options
201
     *
202
     * @return array
203
     */
204
    public function getOptions()
205
    {
206
        return $this->options;
207
    }
208
209
    /**
210
     * Setter for payload options
211
     *
212
     * Authorized keys for options's array are:
213
     *
214
     * - `collapse_key` This parameter identifies a group of messages.
215
     * - `priority` Sets the priority of the message.
216
     * - `content_available` When a notification or message is sent and
217
     *   this is set to true, an inactive client app is awoken.
218
     * - `time_to_live` This parameter specifies how long (in seconds)
219
     *   the message should be kept in FCM storage if the device is offline.
220
     * - `restricted_package_name` This parameter specifies the package name
221
     *   of the application where the registration tokens must match in order
222
     *   to receive the message.
223
     * - `dry_run` This parameter, when set to true, allows developers to test
224
     *   a request without actually sending a message.
225
     *
226
     * @param array|\ker0x\Push\Adapter\Fcm\Message\OptionsBuilder $options Options for the push
227
     * @return $this
228
     */
229
    public function setOptions($options)
230
    {
231
        $this->options = (new Options($options))->build();
232
233
        return $this;
234
    }
235
236
    /**
237
     * Getter for payload
238
     *
239
     * @return array
240
     */
241
    public function getPayload()
242
    {
243
        $notification = $this->getNotification();
244
        if (!empty($notification)) {
245
            $this->payload['notification'] = $notification;
246
        }
247
248
        $data = $this->getData();
249
        if (!empty($data)) {
250
            $this->payload['data'] = $data;
251
        }
252
253
        return $this->payload;
254
    }
255
256
    /**
257
     * Check tokens's array
258
     *
259
     * @param array $tokens Token's array
260
     * @return void
261
     * @throws \ker0x\Push\Adapter\Fcm\Message\Exception\InvalidTokenException
262
     */
263
    private function _checkTokens($tokens)
264
    {
265
        if (empty($tokens) || count($tokens) > 1000) {
266
            throw new InvalidTokenException("Array must contain at least 1 and at most 1000 tokens.");
267
        }
268
    }
269
270
    /**
271
     * Build the message
272
     *
273
     * @return string
274
     */
275
    protected function _getMessage()
276
    {
277
        $tokens = $this->getTokens();
278
        $message = (count($tokens) > 1) ? ['registration_ids' => $tokens] : ['to' => current($tokens)];
279
280
        $payload = $this->getPayload();
281
        if (!empty($payload)) {
282
            $message += $payload;
283
        }
284
285
        $options = $this->getOptions();
286
        if (!empty($options)) {
287
            $message += $options;
288
        }
289
290
        return json_encode($message);
291
    }
292
293
    /**
294
     * Return options for the HTTP request
295
     *
296
     * @return array $options
297
     */
298
    protected function _getHttpOptions()
299
    {
300
        $options = Hash::merge($this->config('http'), [
301
            'type' => 'json',
302
            'headers' => [
303
                'Authorization' => 'key=' . $this->config('api.key'),
304
                'Content-Type' => 'application/json',
305
            ],
306
        ]);
307
308
        return $options;
309
    }
310
}
311