Completed
Push — master ( bda6dc...f45485 )
by Elf
23:03
created

XgPusher::getParameterAsArray()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 2
dl 0
loc 4
ccs 0
cts 2
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace App\Support\Tencent;
4
5
use ElfSundae\XgPush\ClickAction;
6
use ElfSundae\XgPush\Message;
7
use ElfSundae\XgPush\MessageIOS;
8
use ElfSundae\XgPush\Style;
9
use ElfSundae\XgPush\TagTokenPair;
10
use ElfSundae\XgPush\XingeApp;
11
use InvalidArgumentException;
12
13
class XgPusher
14
{
15
    /**
16
     * The XingeApp instance.
17
     *
18
     * @var \ElfSundae\XgPush\XingeApp
19
     */
20
    protected $xinge;
21
22
    /**
23
     * The pusher environment.
24
     *
25
     * 向iOS设备推送时必填,1表示推送生产环境;2表示推送开发环境。推送Android平台不填或填0.
26
     *
27
     * @var int
28
     */
29
    protected $environment = XingeApp::IOSENV_DEV;
30
31
    /**
32
     * The key of custom payload.
33
     *
34
     * @var string
35
     */
36
    protected $customKey;
37
38
    /**
39
     * Xinge account prefix.
40
     *
41
     * @warning 信鸽不允许使用简单的账号,例如纯数字的id。
42
     *
43
     * @var string
44
     */
45
    protected $accountPrefix;
46
47
    /**
48
     * Create a new instance.
49
     *
50
     * @param  string  $appKey
51
     * @param  string  $appSecret
52
     */
53
    public function __construct($appKey, $appSecret)
54
    {
55
        $this->xinge = new XingeApp($appKey, $appSecret);
56
    }
57
58
    /**
59
     * Get the XingeApp instance.
60
     *
61
     * @return \ElfSundae\XgPush\XingeApp
62
     */
63
    public function xinge()
64
    {
65
        return $this->xinge;
66
    }
67
68
    /**
69
     * Get the app key.
70
     *
71
     * @return string
72
     */
73
    public function getAppKey()
74
    {
75
        return $this->xinge->accessId;
76
    }
77
78
    /**
79
     * Get the app secret.
80
     *
81
     * @return string
82
     */
83
    public function getAppSecret()
84
    {
85
        return $this->xinge->secretKey;
86
    }
87
88
    /**
89
     * Get the pusher environment.
90
     *
91
     * @return int
92
     */
93
    public function getEnvironment()
94
    {
95
        return $this->environment;
96
    }
97
98
    /**
99
     * Set the pusher environment.
100
     *
101
     * @param  mixed  $env
102
     * @return $this
103
     */
104
    public function setEnvironment($env)
105
    {
106
        if (is_string($env)) {
107
            $env = $env == 'production' ? XingeApp::IOSENV_PROD : XingeApp::IOSENV_DEV;
108
        }
109
110
        if (is_int($env)) {
111
            $this->environment = $env;
112
        }
113
114
        return $this;
115
    }
116
117
    /**
118
     * Get the key of custom payload.
119
     *
120
     * @return string|null
121
     */
122
    public function getCustomKey()
123
    {
124
        return $this->customKey;
125
    }
126
127
    /**
128
     * Set the key of custom payload.
129
     *
130
     * @param  string|null  $key
131
     * @return $this
132
     */
133
    public function setCustomKey($key)
134
    {
135
        $this->customKey = $key;
136
137
        return $this;
138
    }
139
140
    /**
141
     * Get the account prefix.
142
     *
143
     * @return string
144
     */
145
    public function getAccountPrefix()
146
    {
147
        return $this->accountPrefix;
148
    }
149
150
    /**
151
     * Set the account prefix.
152
     *
153
     * @param  string  $prefix
154
     * @return $this
155
     */
156
    public function setAccountPrefix($prefix)
157
    {
158
        $this->accountPrefix = $prefix;
159
160
        return $this;
161
    }
162
163
    /**
164
     * Determine if the Xinge response is success.
165
     *
166
     * @see http://developer.qq.com/wiki/xg/%E6%9C%8D%E5%8A%A1%E7%AB%AFAPI%E6%8E%A5%E5%85%A5/Rest%20API%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/Rest%20API%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97.html
167
     *
168
     * @param  mixed  $response
169
     * @return bool
170
     */
171
    public function succeed($response)
172
    {
173
        return $this->code($response) === 0;
174
    }
175
176
    /**
177
     * Get the code of Xinge response.
178
     *
179
     * @param  mixed  $response
180
     * @return int|null
181
     */
182
    public function code($response)
183
    {
184
        if (is_array($response)) {
185
            return array_get($response, 'ret_code');
186
        }
187
    }
188
189
    /**
190
     * Get the error message of Xinge response.
191
     *
192
     * @param  mixed  $response
193
     * @return string|null
194
     */
195
    public function message($response)
196
    {
197
        if (is_array($response)) {
198
            return array_get($response, 'err_msg');
199
        }
200
    }
201
202
    /**
203
     * Get the result data of Xinge response.
204
     *
205
     * @param  mixed  $response
206
     * @param  string  $key
207
     * @param  mixed  $default
208
     * @return mixed
209
     */
210
    public function result($response, $key = null, $default = null)
211
    {
212
        if (is_array($response)) {
213
            return array_get($response, $key ? "result.{$key}" : 'result', $default);
214
        }
215
    }
216
217
    /**
218
     * Encode the custom data.
219
     *
220
     * @param  mixed  $data
221
     * @return array
222
     */
223
    public function encodeCustomData($data)
224
    {
225
        if ($this->customKey && $data) {
226
            return [$this->customKey => $data];
227
        }
228
229
        return $data ?: [];
230
    }
231
232
    /**
233
     * Get Xinge account for the given user.
234
     *
235
     * @param  mixed  $user
236
     * @return string
237
     */
238
    public function accountForUser($user)
239
    {
240
        if ($this->accountPrefix && is_string($user) && starts_with($user, $this->accountPrefix)) {
241
            return $user;
242
        }
243
244 View Code Duplication
        if (is_object($user)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
245
            $user = $user->id;
246
        } elseif (is_array($user)) {
247
            $user = $user['id'];
248
        }
249
250
        return $this->accountPrefix.$user;
251
    }
252
253
    /**
254
     * Creates a new MessageIOS instance.
255
     *
256
     * @param  string  $alert
257
     * @param  mixed  $custom
258
     * @param  int  $badge
259
     * @param  string  $sound
260
     * @return \ElfSundae\XgPush\MessageIOS
261
     */
262
    public function createIOSMessage($alert = '', $custom = null, $badge = 1, $sound = 'default')
263
    {
264
        $message = new MessageIOS();
265
        $message->setAlert($alert);
266
        $message->setCustom($this->encodeCustomData($custom));
267
        if (is_int($badge) && $badge >= 0) {
268
            $message->setBadge($badge);
269
        }
270
        if ($sound) {
271
            $message->setSound($sound);
272
        }
273
274
        return $message;
275
    }
276
277
    /**
278
     * Create a new Message instance.
279
     *
280
     * @param  string  $title
281
     * @param  string  $content
282
     * @param  mixed  $custom
283
     * @param  int  $type
284
     * @return \ElfSundae\XgPush\Message
285
     */
286
    public function createAndroidMessage($title = '', $content = '', $custom = null, $type = Message::TYPE_MESSAGE)
287
    {
288
        $message = new Message();
289
        $message->setTitle($title);
290
        $message->setContent($content);
291
        $message->setCustom($this->encodeCustomData($custom));
292
        $message->setType($type);
293
294
        return $message;
295
    }
296
297
    /**
298
     * Create a new Message instance for notification.
299
     * The default action is opening app.
300
     *
301
     * @param  string  $title
302
     * @param  string  $content
303
     * @param  mixed  $custom
304
     * @return \ElfSundae\XgPush\Message
305
     */
306
    public function createAndroidNotification($title = '', $content = '', $custom = null)
307
    {
308
        $message = $this->createAndroidMessage($title, $content, $custom, Message::TYPE_NOTIFICATION);
309
310
        $message->setStyle(new Style(0, 1, 1, 1, 0));
311
        $action = new ClickAction();
312
        $action->setActionType(ClickAction::TYPE_ACTIVITY);
313
        $message->setAction($action);
314
315
        return $message;
316
    }
317
318
    /**
319
     * Push message to a device.
320
     *
321
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
322
     * @param  string  $deviceToken
323
     * @return array
324
     */
325
    public function toDevice($message, $deviceToken)
326
    {
327
        return $this->xinge->PushSingleDevice($deviceToken, $message, $this->environment);
328
    }
329
330
    /**
331
     * Push message to all devices.
332
     *
333
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
334
     * @return array
335
     */
336
    public function toAllDevices($message)
337
    {
338
        return $this->xinge->PushAllDevices(0, $message, $this->environment);
339
    }
340
341
    /**
342
     * Push message to users.
343
     *
344
     * @warning 用户数限制 100 个。
345
     *
346
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
347
     * @param  mixed  $users
348
     * @return array
349
     */
350
    public function toUser($message, $users)
351
    {
352
        $users = $this->getParameterAsArray(func_get_args(), 1);
353
354
        $accounts = array_map([$this, 'accountForUser'], $users);
355
356
        if (count($accounts) == 1) {
357
            return $this->xinge->PushSingleAccount(0, $accounts[0], $message, $this->environment);
358
        }
359
360
        return $this->xinge->PushAccountList(0, $accounts, $message, $this->environment);
361
    }
362
363
    /**
364
     * Push message to tagged devices.
365
     *
366
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
367
     * @param  string|string[]  $tags
368
     * @param  string  $tagsOperation  'OR', 'AND'
369
     * @return array
370
     */
371
    public function toTags($message, $tags, $tagsOperation = 'OR')
372
    {
373
        return $this->xinge->PushTags(0, (array) $tags, strtoupper($tagsOperation), $message, $this->environment);
374
    }
375
376
    /**
377
     * Create a batch push.
378
     *
379
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
380
     * @return string|null
381
     */
382
    public function createBatch($message)
383
    {
384
        return $this->result($this->xinge->CreateMultipush($message, $this->environment), 'push_id');
385
    }
386
387
    /**
388
     * Batch pushing to a list of users.
389
     *
390
     * @warning 用户数限制 1000 个。
391
     *
392
     * @param  int|string  $pushId
393
     * @param  string|string[] $users
394
     * @return array
395
     */
396
    public function batchToUsers($pushId, $users)
397
    {
398
        $accounts = array_map([$this, 'accountForUser'], (array) $users);
399
400
        return $this->xinge->PushAccountListMultiple($pushId, $accounts);
401
    }
402
403
    /**
404
     * Batch pushing to a list of devices.
405
     *
406
     * @param  int|string  $pushId
407
     * @param  string|string[]  $devices
408
     * @return array
409
     */
410
    public function batchToDevices($pushId, $devices)
411
    {
412
        return $this->xinge->PushDeviceListMultiple($pushId, (array) $devices);
413
    }
414
415
    /**
416
     * Query group pushing status.
417
     *
418
     * @param  mixed  $pushIds
419
     * @return array
420
     */
421
    public function queryPushStatus($pushIds)
422
    {
423
        $pushIds = $this->getParameterAsArray(func_get_args());
424
425
        $list = $this->result($this->xinge->QueryPushStatus($pushIds), 'list', []);
426
427
        return array_combine(array_pluck($list, 'push_id'), $list);
428
    }
429
430
    /**
431
     * Cancel a timed pushing task that has not been pushed.
432
     *
433
     * @param  string  $pushId
434
     * @return array
435
     */
436
    public function cancelTimedPush($pushId)
437
    {
438
        return $this->xinge->CancelTimingPush($pushId);
439
    }
440
441
    /**
442
     * Query all device tokens for the given user.
443
     *
444
     * @param  mixed  $user
445
     * @return string[]
446
     */
447
    public function queryDeviceTokensForUser($user)
448
    {
449
        return $this->result($this->xinge->QueryTokensOfAccount($this->accountForUser($user)), 'tokens', []);
450
    }
451
452
    /**
453
     * Delete device tokens for the given user.
454
     *
455
     * @param  mixed  $user
456
     * @param  string|string[]  $deviceToken
0 ignored issues
show
Documentation introduced by
There is no parameter named $deviceToken. Did you maybe mean $deviceTokens?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
457
     * @return bool
458
     */
459
    public function deleteDeviceTokensForUser($user, $deviceTokens = null)
460
    {
461
        $account = $this->accountForUser($user);
462
463
        if (is_null($deviceTokens)) {
464
            return $this->succeed($this->xinge->DeleteAllTokensOfAccount($account));
465
        }
466
467
        $deviceTokens = array_unique((array) $deviceTokens);
468
469
        $result = true;
470
471
        foreach ($deviceTokens as $token) {
472
            $result = $result && $this->succeed($this->xinge->DeleteTokenOfAccount($account, $token));
473
        }
474
475
        return $result;
476
    }
477
478
    /**
479
     * Query count of registered devices.
480
     *
481
     * @return int
482
     */
483
    public function queryCountOfDevices()
484
    {
485
        return $this->result($this->xinge->QueryDeviceCount(), 'device_num', 0);
486
    }
487
488
    /**
489
     * Query info for the given device token.
490
     *
491
     * @param  string  $deviceToken
492
     * @return array
493
     */
494
    public function queryDeviceTokenInfo($deviceToken)
495
    {
496
        return $this->xinge->QueryInfoOfToken($deviceToken);
497
    }
498
499
    /**
500
     * Query count of registered tokens for the given tag.
501
     *
502
     * @param  string  $tag
503
     * @return int
504
     */
505
    public function queryCountOfDeviceTokensForTag($tag)
506
    {
507
        return $this->result($this->xinge->QueryTagTokenNum($tag), 'device_num', 0);
508
    }
509
510
    /**
511
     * Query tags.
512
     *
513
     * @return array
514
     */
515
    public function queryTags($start = 0, $limit = 100)
516
    {
517
        return $this->xinge->QueryTags($start, $limit);
518
    }
519
520
    /**
521
     * Query all tags for the given device token.
522
     *
523
     * @param  string  $deviceToken
524
     * @return string[]
525
     */
526
    public function queryTagsForDeviceToken($deviceToken)
527
    {
528
        return $this->result($this->xinge->QueryTokenTags($deviceToken), 'tags', []);
529
    }
530
531
    /**
532
     * Query all tags for the given user.
533
     *
534
     * @param  mixed  $user
535
     * @param  array  &$deviceTokens
536
     * @return array
537
     */
538
    public function queryTagsForUser($user, &$deviceTokens = null)
539
    {
540
        $deviceTokens = $this->queryDeviceTokensForUser($user);
541
542
        $result = [];
543
        foreach ($deviceTokens as $token) {
544
            $result[$token] = $this->queryTagsForDeviceToken($token);
545
        }
546
547
        return $result;
548
    }
549
550
    /**
551
     * Set tags for device tokens.
552
     *
553
     * @warning 每次最多设置 20 对。
554
     *
555
     * @param  \ElfSundae\XgPush\TagTokenPair[]  $tagTokenPairs
556
     * @return bool
557
     */
558
    public function setTags($tagTokenPairs)
559
    {
560
        return $this->succeed($this->xinge->BatchSetTag($tagTokenPairs));
561
    }
562
563
    /**
564
     * Set tags for the given device token.
565
     *
566
     * @param  string  $deviceToken
567
     * @param  mixed  $tags
568
     * @return bool
569
     */
570
    public function setTagsForDeviceToken($deviceToken, $tags)
571
    {
572
        return $this->setTags($this->createTagTokenPairs(
573
            $this->getParameterAsArray(func_get_args(), 1),
574
            $deviceToken
575
        ));
576
    }
577
578
    /**
579
     * Set tags for the given user.
580
     *
581
     * @param  mixed  $user
582
     * @param  mixed  $tags
583
     * @return bool
584
     */
585
    public function setTagsForUser($user, $tags)
586
    {
587
        return $this->setTags($this->createTagTokenPairs(
588
            $this->getParameterAsArray(func_get_args(), 1),
589
            $this->queryDeviceTokensForUser($user)
590
        ));
591
    }
592
593
    /**
594
     * Delete tags for device tokens.
595
     *
596
     * @warning 每次最多删除 20 对。
597
     *
598
     * @param  \ElfSundae\XgPush\TagTokenPair[]  $tagTokenPairs
599
     * @return bool
600
     */
601
    public function deleteTags($tagTokenPairs)
602
    {
603
        return $this->succeed($this->xinge->BatchDelTag($tagTokenPairs));
604
    }
605
606
    /**
607
     * Delete tags for the given device token.
608
     *
609
     * @param  string  $deviceToken
610
     * @param  mixed  $tags
611
     * @return bool
612
     */
613
    public function deleteTagsForDeviceToken($deviceToken, $tags)
614
    {
615
        return $this->deleteTags($this->createTagTokenPairs(
616
            $this->getParameterAsArray(func_get_args(), 1),
617
            $deviceToken
618
        ));
619
    }
620
621
    /**
622
     * Delete tags for the given user.
623
     *
624
     * @param  mixed  $user
625
     * @param  mixed  $tags
626
     * @return bool
627
     */
628
    public function deleteTagsForUser($user, $tags)
629
    {
630
        return $this->deleteTags($this->createTagTokenPairs(
631
            $this->getParameterAsArray(func_get_args(), 1),
632
            $this->queryDeviceTokensForUser($user)
633
        ));
634
    }
635
636
    /**
637
     * Get parameter as array.
638
     *
639
     * @param  array  $args
640
     * @param  int $offset
641
     * @return array
642
     */
643
    protected function getParameterAsArray(array $args, $offset = 0)
644
    {
645
        return is_array($args[$offset]) ? $args[$offset] : array_slice($args, $offset);
646
    }
647
648
    /**
649
     * Create array of TagTokenPair.
650
     *
651
     * @warning $tags 和 $tokens 一个是数组,另一个是字符串
652
     *
653
     * @param  string|string[]  $tags
654
     * @param  string|string[]  $tokens
655
     * @return \ElfSundae\XgPush\TagTokenPair[]
656
     */
657
    protected function createTagTokenPairs($tags, $tokens)
658
    {
659
        $tagTokenPairs = [];
660
661
        $tokens = (array) $tokens;
662
        foreach ((array) $tags as $tag) {
663
            foreach ($tokens as $token) {
664
                $tagTokenPairs[] = new TagTokenPair($tag, $token);
665
            }
666
        }
667
668
        return array_unique($tagTokenPairs);
669
    }
670
671
    /**
672
     * Dynamically handle calls to the XingeApp instance.
673
     *
674
     * @param  string  $method
675
     * @param  array   $parameters
676
     * @return mixed
677
     */
678
    public function __call($method, $parameters)
679
    {
680
        return call_user_func_array([$this->xinge, $method], $parameters);
681
    }
682
}
683