Completed
Push — master ( f8f3cb...e8d4bf )
by Romain
9s
created

Fcm::_checkParameters()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 1
1
<?php
2
3
namespace Kerox\Push\Adapter;
4
5
use Cake\Core\Configure;
6
use Cake\Http\Client;
7
use Cake\Http\Client\Message;
8
use Cake\Utility\Hash;
9
10
class Fcm extends AbstractAdapter
11
{
12
13
    const PRIORITY_NORMAL = 'normal';
14
    const PRIORITY_HIGH = 'high';
15
16
    /**
17
     * Array for devices's token
18
     *
19
     * @var array
20
     */
21
    protected $tokens = [];
22
23
    /**
24
     * Array for the notification
25
     *
26
     * @var array
27
     */
28
    protected $notification = [];
29
30
    /**
31
     * Array of datas
32
     *
33
     * @var array
34
     */
35
    protected $datas = [];
36
37
    /**
38
     * Array of request parameters
39
     *
40
     * @var array
41
     */
42
    protected $parameters = [];
43
44
    /**
45
     * Array of payload
46
     *
47
     * @var array
48
     */
49
    protected $payload = [];
50
51
    /**
52
     * Default config
53
     *
54
     * @var array
55
     */
56
    protected $_defaultConfig = [
57
        'parameters' => [
58
            'collapse_key' => null,
59
            'priority' => self::PRIORITY_NORMAL,
60
            'content_available' => false,
61
            'mutable_content' => false,
62
            'time_to_live' => 0,
63
            'restricted_package_name' => null,
64
            'dry_run' => false,
65
        ],
66
        'http' => [],
67
    ];
68
69
    /**
70
     * List of keys allowed to be used in notification array.
71
     *
72
     * @var array
73
     */
74
    protected $_allowedNotificationKeys = [
75
        'title',
76
        'body',
77
        'icon',
78
        'sound',
79
        'badge',
80
        'tag',
81
        'color',
82
        'click_action',
83
        'body_loc_key',
84
        'body_loc_args',
85
        'title_loc_key',
86
        'title_loc_args',
87
    ];
88
89
    /**
90
     * FcmAdapter constructor.
91
     *
92
     * @throws \Exception
93
     */
94
    public function __construct()
95
    {
96
        $config = Configure::read('Push.adapters.Fcm');
97
98
        parent::__construct($config);
99
    }
100
101
    /**
102
     * Getter for tokens
103
     *
104
     * @return array
105
     */
106
    public function getTokens()
107
    {
108
        return $this->tokens;
109
    }
110
111
    /**
112
     * Setter for tokens
113
     *
114
     * @param array $tokens Array of devices's token
115
     * @return $this
116
     */
117
    public function setTokens(array $tokens)
118
    {
119
        $this->_checkTokens($tokens);
120
        $this->tokens = $tokens;
121
122
        return $this;
123
    }
124
125
    /**
126
     * Getter for notification
127
     *
128
     * @return array
129
     */
130
    public function getNotification()
131
    {
132
        return $this->notification;
133
    }
134
135
    /**
136
     * Setter for notification
137
     *
138
     * @param array $notification Array of keys for the notification
139
     * @return $this
140
     */
141
    public function setNotification(array $notification)
142
    {
143
        $this->_checkNotification($notification);
144
        if (!isset($notification['icon'])) {
145
            $notification['icon'] = 'myicon';
146
        }
147
        $this->notification = $notification;
148
149
        return $this;
150
    }
151
152
    /**
153
     * Getter for datas
154
     *
155
     * @return array
156
     */
157
    public function getDatas()
158
    {
159
        return $this->datas;
160
    }
161
162
    /**
163
     * Setter for datas
164
     *
165
     * @param array $datas Array of datas for the push
166
     * @return $this
167
     */
168
    public function setDatas(array $datas)
169
    {
170
        $this->_checkDatas($datas);
171
        foreach ($datas as $key => $value) {
172
            if (is_bool($value)) {
173
                $value = ($value) ? 'true' : 'false';
174
            }
175
            $datas[$key] = (string)$value;
176
        }
177
        $this->datas = $datas;
178
179
        return $this;
180
    }
181
182
    /**
183
     * Getter for parameters
184
     *
185
     * @return array
186
     */
187
    public function getParameters()
188
    {
189
        return $this->parameters;
190
    }
191
192
    /**
193
     * Setter for parameters
194
     *
195
     * @param array $parameters Array of parameters for the push
196
     * @return $this
197
     */
198
    public function setParameters(array $parameters)
199
    {
200
        $this->_checkParameters($parameters);
201
        $this->parameters = Hash::merge($this->getConfig('parameters'), $parameters);
202
203
        return $this;
204
    }
205
206
    /**
207
     * Getter for payload
208
     *
209
     * @return array
210
     */
211
    public function getPayload()
212
    {
213
        $notification = $this->getNotification();
214
        if (!empty($notification)) {
215
            $this->payload['notification'] = $notification;
216
        }
217
218
        $datas = $this->getDatas();
219
        if (!empty($datas)) {
220
            $this->payload['data'] = $datas;
221
        }
222
223
        return $this->payload;
224
    }
225
226
    /**
227
     * Execute the push
228
     *
229
     * @return bool
230
     */
231
    public function send()
232
    {
233
        $message = $this->_buildMessage();
234
        $options = $this->_getHttpOptions();
235
236
        $http = new Client();
237
        $this->response = $http->post($this->getConfig('api.url'), $message, $options);
238
239
        return $this->response->getStatusCode() === Message::STATUS_OK;
240
    }
241
242
    /**
243
     * Check tokens's array
244
     *
245
     * @param array $tokens Token's array
246
     * @return void
247
     * @throws \InvalidArgumentException
248
     */
249
    private function _checkTokens(array $tokens)
250
    {
251
        if (empty($tokens) || count($tokens) > 1000) {
252
            throw new \InvalidArgumentException("Array must contain at least 1 and at most 1000 tokens.");
253
        }
254
    }
255
256
    /**
257
     * Check notification's array
258
     *
259
     * @param array $notification Notification's array
260
     * @return void
261
     * @throws \InvalidArgumentException
262
     */
263
    private function _checkNotification(array $notification)
264
    {
265
        if (empty($notification) || !isset($notification['title'])) {
266
            throw new \InvalidArgumentException("Array must contain at least a key title.");
267
        }
268
269
        $notAllowedKeys = [];
270
        foreach ($notification as $key => $value) {
271
            if (!in_array($key, $this->_allowedNotificationKeys)) {
272
                $notAllowedKeys[] = $key;
273
            }
274
        }
275
276
        if (!empty($notAllowedKeys)) {
277
            $notAllowedKeys = implode(', ', $notAllowedKeys);
278
            throw new \InvalidArgumentException("The following keys are not allowed: {$notAllowedKeys}");
279
        }
280
    }
281
282
    /**
283
     * Check datas's array
284
     *
285
     * @param array $datas Datas's array
286
     * @return void
287
     * @throws \InvalidArgumentException
288
     */
289
    private function _checkDatas(array $datas)
290
    {
291
        if (empty($datas)) {
292
            throw new \InvalidArgumentException("Array can not be empty.");
293
        }
294
    }
295
296
    /**
297
     * Check parameters's array
298
     *
299
     * @param array $parameters Parameters's array
300
     * @return void
301
     * @throws \InvalidArgumentException
302
     */
303
    private function _checkParameters(array $parameters)
304
    {
305
        if (empty($parameters)) {
306
            throw new \InvalidArgumentException("Array can not be empty.");
307
        }
308
    }
309
310
    /**
311
     * Build the message
312
     *
313
     * @return string
314
     */
315
    private function _buildMessage()
316
    {
317
        $tokens = $this->getTokens();
318
        $message = (count($tokens) > 1) ? ['registration_ids' => $tokens] : ['to' => current($tokens)];
319
320
        $payload = $this->getPayload();
321
        if (!empty($payload)) {
322
            $message += $payload;
323
        }
324
325
        $parameters = $this->getParameters();
326
        if (!empty($parameters)) {
327
            $message += $parameters;
328
        }
329
330
        return json_encode($message);
331
    }
332
333
    /**
334
     * Return options for the HTTP request
335
     *
336
     * @return array $options
337
     */
338
    private function _getHttpOptions()
339
    {
340
        $options = Hash::merge($this->getConfig('http'), [
341
            'type' => 'json',
342
            'headers' => [
343
                'Authorization' => 'key=' . $this->getConfig('api.key'),
344
                'Content-Type' => 'application/json',
345
            ],
346
        ]);
347
348
        return $options;
349
    }
350
}
351