Completed
Push — master ( 26655b...34e7f3 )
by Arthur
01:23 queued 11s
created

Payload   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 426
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
dl 0
loc 426
rs 8.96
c 0
b 0
f 0
wmc 43
lcom 1
cbo 0

25 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A create() 0 4 1
A getAlert() 0 4 1
A setAlert() 0 8 3
A getBadge() 0 4 1
A setBadge() 0 6 1
A getSound() 0 4 1
A setSound() 0 8 3
A setContentAvailability() 0 6 1
A isContentAvailable() 0 4 1
A setMutableContent() 0 6 1
A hasMutableContent() 0 4 1
A getCategory() 0 4 1
A setCategory() 0 6 1
A getThreadId() 0 4 1
A setThreadId() 0 6 1
A getUrlArgs() 0 4 1
A setUrlArgs() 0 6 1
A setCustomValue() 0 10 2
A getCustomValue() 0 8 2
A setPushType() 0 5 1
A getPushType() 0 3 1
A toJson() 0 4 1
F jsonSerialize() 0 42 13
A getDefaultPayloadStructure() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like Payload often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Payload, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * This file is part of the Pushok package.
5
 *
6
 * (c) Arthur Edamov <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Pushok;
13
14
use Countable;
15
use Pushok\Payload\Alert;
16
use Pushok\Payload\Sound;
17
18
// Polyfill for PHP 7.2
19
if (!function_exists('is_countable')) {
20
    function is_countable($var)
21
    {
22
        return (is_array($var) || $var instanceof Countable);
23
    }
24
}
25
26
/**
27
 * Class Payload
28
 *
29
 * @package Pushok
30
 *
31
 * @see     http://bit.ly/payload-key-reference
32
 */
33
class Payload implements \JsonSerializable
34
{
35
    const PAYLOAD_ROOT_KEY = 'aps';
36
    const PAYLOAD_ALERT_KEY = 'alert';
37
    const PAYLOAD_BADGE_KEY = 'badge';
38
    const PAYLOAD_SOUND_KEY = 'sound';
39
    const PAYLOAD_CONTENT_AVAILABLE_KEY = 'content-available';
40
    const PAYLOAD_MUTABLE_CONTENT_KEY = 'mutable-content';
41
    const PAYLOAD_CATEGORY_KEY = 'category';
42
    const PAYLOAD_THREAD_ID_KEY = 'thread-id';
43
    const PAYLOAD_URL_ARGS_KEY = 'url-args';
44
45
    const PAYLOAD_HTTP2_REGULAR_NOTIFICATION_MAXIMUM_SIZE = 4096;
46
    const PAYLOAD_HTTP2_VOIP_NOTIFICATION_MAXIMUM_SIZE = 5120;
47
    const PAYLOAD_BINARY_REGULAR_NOTIFICATION_MAXIMUM_SIZE = 2048;
48
49
    /**
50
     * The notification settings for your app on the user’s device determine whether an alert or banner is displayed.
51
     *
52
     * @var Alert|string
53
     */
54
    private $alert;
55
56
    /**
57
     * The number to display as the badge of the app icon.
58
     * If this property is absent, the badge is not changed.
59
     *
60
     * @var int
61
     */
62
    private $badge;
63
64
    /**
65
     * The name of a sound file in the app bundle or in the Library/Sounds folder of the app’s data container.
66
     *
67
     * @var Sound|string
68
     */
69
    private $sound;
70
71
    /**
72
     * Include this key with a value of true to configure a silent notification.
73
     *
74
     * @var bool
75
     */
76
    private $contentAvailable;
77
78
    /**
79
     * Include this key with a value of true to configure a mutable content notification.
80
     *
81
     * @var bool
82
     */
83
    private $mutableContent;
84
85
    /**
86
     * Provide this key with a string value that represents the notification’s type.
87
     *
88
     * @var string
89
     */
90
    private $category;
91
92
    /**
93
     * Provide this key with a string value that represents the app-specific identifier for grouping notifications.
94
     *
95
     * @var string
96
     */
97
    private $threadId;
98
99
    /**
100
     * Provide this key with an array value that represents the url-args for Safari notifications.
101
     *
102
     * @var string
103
     */
104
    private $urlArgs;
105
106
    /**
107
     * Payload custom values.
108
     *
109
     * @var array
110
     */
111
    private $customValues;
112
113
    /**
114
     * Push notification type
115
     *
116
     * https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns#2947607
117
     *
118
     * @var string
119
     */
120
    private $pushType;
121
122
    protected function __construct()
123
    {
124
    }
125
126
    /**
127
     * @return Payload
128
     */
129
    public static function create(): Payload
130
    {
131
        return new self();
132
    }
133
134
    /**
135
     * Get Alert.
136
     *
137
     * @return Alert|null
138
     */
139
    public function getAlert()
140
    {
141
        return $this->alert;
142
    }
143
144
    /**
145
     * Set Alert.
146
     *
147
     * @param Alert|string $alert
148
     *
149
     * @return Payload
150
     */
151
    public function setAlert($alert): Payload
152
    {
153
        if ($alert instanceof Alert || is_string($alert)) {
154
            $this->alert = $alert;
155
        }
156
157
        return $this;
158
    }
159
160
    /**
161
     * Get badge.
162
     *
163
     * @return int|null
164
     */
165
    public function getBadge()
166
    {
167
        return $this->badge;
168
    }
169
170
    /**
171
     * Set badge.
172
     *
173
     * @param int $value
174
     *
175
     * @return Payload
176
     */
177
    public function setBadge(int $value): Payload
178
    {
179
        $this->badge = $value;
180
181
        return $this;
182
    }
183
184
    /**
185
     * Get sound.
186
     *
187
     * @return string|null
188
     */
189
    public function getSound()
190
    {
191
        return $this->sound;
192
    }
193
194
    /**
195
     * Set sound.
196
     *
197
     * @param Sound|string $sound
198
     *
199
     * @return Payload
200
     */
201
    public function setSound($sound): Payload
202
    {
203
        if ($sound instanceof Sound || is_string($sound)) {
204
            $this->sound = $sound;
205
        }
206
207
        return $this;
208
    }
209
210
    /**
211
     * Set content availability.
212
     *
213
     * @param bool $value
214
     *
215
     * @return Payload
216
     */
217
    public function setContentAvailability(bool $value): Payload
218
    {
219
        $this->contentAvailable = $value;
220
221
        return $this;
222
    }
223
224
    /**
225
     * Get content availability.
226
     *
227
     * @return bool|null
228
     */
229
    public function isContentAvailable()
230
    {
231
        return $this->contentAvailable;
232
    }
233
234
    /**
235
     * Set the mutable-content key for Notification Service Extensions on iOS10.
236
     *
237
     * @see http://bit.ly/mutable-content
238
     *
239
     * @param bool $value
240
     *
241
     * @return Payload
242
     */
243
    public function setMutableContent(bool $value): Payload
244
    {
245
        $this->mutableContent = $value;
246
247
        return $this;
248
    }
249
250
    /**
251
     * Is content mutable.
252
     *
253
     * @return bool|null
254
     */
255
    public function hasMutableContent()
256
    {
257
        return $this->mutableContent;
258
    }
259
260
    /**
261
     * Get category.
262
     *
263
     * @return string|null
264
     */
265
    public function getCategory()
266
    {
267
        return $this->category;
268
    }
269
270
    /**
271
     * Set category.
272
     *
273
     * @param string $value
274
     *
275
     * @return Payload
276
     */
277
    public function setCategory(string $value): Payload
278
    {
279
        $this->category = $value;
280
281
        return $this;
282
    }
283
284
    /**
285
     * Get thread-id.
286
     *
287
     * @return string|null
288
     */
289
    public function getThreadId()
290
    {
291
        return $this->threadId;
292
    }
293
294
    /**
295
     * Set thread-id.
296
     *
297
     * @param string $value
298
     *
299
     * @return Payload
300
     */
301
    public function setThreadId(string $value): Payload
302
    {
303
        $this->threadId = $value;
304
305
        return $this;
306
    }
307
308
    /**
309
     * Get url-args.
310
     *
311
     * @return array|null
312
     */
313
    public function getUrlArgs()
314
    {
315
        return $this->urlArgs;
316
    }
317
318
    /**
319
     * Set url-args.
320
     *
321
     * @param array $value
322
     *
323
     * @return Payload
324
     */
325
    public function setUrlArgs(array $value): Payload
326
    {
327
        $this->urlArgs = $value;
0 ignored issues
show
Documentation Bug introduced by
It seems like $value of type array is incompatible with the declared type string of property $urlArgs.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
328
329
        return $this;
330
    }
331
332
    /**
333
     * Set custom value for Payload.
334
     *
335
     * @param string $key
336
     * @param mixed $value
337
     *
338
     * @return Payload
339
     * @throws InvalidPayloadException
340
     */
341
    public function setCustomValue(string $key, $value): Payload
342
    {
343
        if ($key === self::PAYLOAD_ROOT_KEY) {
344
            throw InvalidPayloadException::reservedKey();
345
        }
346
347
        $this->customValues[$key] = $value;
348
349
        return $this;
350
    }
351
352
    /**
353
     * Get custom value.
354
     *
355
     * @param $key
356
     *
357
     * @return mixed
358
     * @throws InvalidPayloadException
359
     */
360
    public function getCustomValue($key)
361
    {
362
        if (!array_key_exists($key, $this->customValues)) {
363
            throw InvalidPayloadException::notExistingCustomValue($key);
364
        }
365
366
        return $this->customValues[$key];
367
    }
368
369
    /**
370
     * Set push type for Payload.
371
     *
372
     * @param string $pushType
373
     * @return Payload
374
     */
375
    public function setPushType($pushType) {
376
        $this->pushType = $pushType;
377
378
        return $this;
379
    }
380
381
    /**
382
     * Get push type for Payload.
383
     *
384
     * @return string
385
     */
386
    public function getPushType() {
387
        return $this->pushType;
388
    }
389
390
    /**
391
     * Convert Payload to JSON.
392
     *
393
     * @return string
394
     */
395
    public function toJson(): string
396
    {
397
        return json_encode($this, JSON_UNESCAPED_UNICODE);
398
    }
399
400
    /**
401
     * Specify data which should be serialized to JSON.
402
     *
403
     * @return array
404
     * @link   http://php.net/manual/en/jsonserializable.jsonserialize.php
405
     */
406
    public function jsonSerialize()
407
    {
408
        $payload = self::getDefaultPayloadStructure();
409
410
        if ($this->alert instanceof Alert || is_string($this->alert)) {
411
            $payload[self::PAYLOAD_ROOT_KEY]->{self::PAYLOAD_ALERT_KEY} = $this->alert;
412
        }
413
414
        if (is_int($this->badge)) {
415
            $payload[self::PAYLOAD_ROOT_KEY]->{self::PAYLOAD_BADGE_KEY} = $this->badge;
416
        }
417
418
        if ($this->sound instanceof Sound || is_string($this->sound)) {
419
            $payload[self::PAYLOAD_ROOT_KEY]->{self::PAYLOAD_SOUND_KEY} = $this->sound;
420
        }
421
422
        if (is_bool($this->contentAvailable)) {
423
            $payload[self::PAYLOAD_ROOT_KEY]->{self::PAYLOAD_CONTENT_AVAILABLE_KEY} = (int)$this->contentAvailable;
424
        }
425
426
        if (is_bool($this->mutableContent)) {
427
            $payload[self::PAYLOAD_ROOT_KEY]->{self::PAYLOAD_MUTABLE_CONTENT_KEY} = (int)$this->mutableContent;
428
        }
429
430
        if (is_string($this->category)) {
431
            $payload[self::PAYLOAD_ROOT_KEY]->{self::PAYLOAD_CATEGORY_KEY} = $this->category;
432
        }
433
434
        if (is_string($this->threadId)) {
435
            $payload[self::PAYLOAD_ROOT_KEY]->{self::PAYLOAD_THREAD_ID_KEY} = $this->threadId;
436
        }
437
438
        if (is_array($this->urlArgs)) {
439
            $payload[self::PAYLOAD_ROOT_KEY]->{self::PAYLOAD_URL_ARGS_KEY} = $this->urlArgs;
440
        }
441
442
        if (is_countable($this->customValues) && count($this->customValues)) {
443
            $payload = array_merge($payload, $this->customValues);
444
        }
445
446
        return $payload;
447
    }
448
449
    /**
450
     * Get default payload structure.
451
     *
452
     * @return array
453
     */
454
    private static function getDefaultPayloadStructure()
455
    {
456
        return [self::PAYLOAD_ROOT_KEY => new \stdClass];
457
    }
458
}
459