Completed
Push — master ( 88c00e...a7d489 )
by Elf
05:03
created

XgPusher::accountsForUsers()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 0
cts 2
cp 0
crap 2
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
12
class XgPusher
13
{
14
    /**
15
     * The XingeApp instance.
16
     *
17
     * @var \ElfSundae\XgPush\XingeApp
18
     */
19
    protected $xinge;
20
21
    /**
22
     * The pusher environment.
23
     *
24
     * 向iOS设备推送时必填,1表示推送生产环境;2表示推送开发环境。推送Android平台不填或填0.
25
     *
26
     * @var int
27
     */
28
    protected $environment = XingeApp::IOSENV_DEV;
29
30
    /**
31
     * The key of custom payload.
32
     *
33
     * @var string
34
     */
35
    protected $customKey;
36
37
    /**
38
     * Xinge account prefix.
39
     *
40
     * @warning 信鸽不允许使用简单的账号,例如纯数字的id。
41
     *
42
     * @var string
43
     */
44
    protected $accountPrefix;
45
46
    /**
47
     * Create a new instance.
48
     *
49
     * @param  string  $appKey
50
     * @param  string  $appSecret
51
     */
52
    public function __construct($appKey, $appSecret)
53
    {
54
        $this->xinge = new XingeApp($appKey, $appSecret);
55
    }
56
57
    /**
58
     * Get the XingeApp instance.
59
     *
60
     * @return \ElfSundae\XgPush\XingeApp
61
     */
62
    public function xinge()
63
    {
64
        return $this->xinge;
65
    }
66
67
    /**
68
     * Get the app key.
69
     *
70
     * @return string
71
     */
72
    public function getAppKey()
73
    {
74
        return $this->xinge->accessId;
75
    }
76
77
    /**
78
     * Get the app secret.
79
     *
80
     * @return string
81
     */
82
    public function getAppSecret()
83
    {
84
        return $this->xinge->secretKey;
85
    }
86
87
    /**
88
     * Get the pusher environment.
89
     *
90
     * @return int
91
     */
92
    public function getEnvironment()
93
    {
94
        return $this->environment;
95
    }
96
97
    /**
98
     * Set the pusher environment.
99
     *
100
     * @param  mixed  $env
101
     * @return $this
102
     */
103
    public function setEnvironment($env)
104
    {
105
        if (is_string($env)) {
106
            $env = $env == 'production' ? XingeApp::IOSENV_PROD : XingeApp::IOSENV_DEV;
107
        }
108
109
        if (is_int($env)) {
110
            $this->environment = $env;
111
        }
112
113
        return $this;
114
    }
115
116
    /**
117
     * Get the key of custom payload.
118
     *
119
     * @return string|null
120
     */
121
    public function getCustomKey()
122
    {
123
        return $this->customKey;
124
    }
125
126
    /**
127
     * Set the key of custom payload.
128
     *
129
     * @param  string|null  $key
130
     * @return $this
131
     */
132
    public function setCustomKey($key)
133
    {
134
        $this->customKey = $key;
135
136
        return $this;
137
    }
138
139
    /**
140
     * Get the account prefix.
141
     *
142
     * @return string
143
     */
144
    public function getAccountPrefix()
145
    {
146
        return $this->accountPrefix;
147
    }
148
149
    /**
150
     * Set the account prefix.
151
     *
152
     * @param  string  $prefix
153
     * @return $this
154
     */
155
    public function setAccountPrefix($prefix)
156
    {
157
        $this->accountPrefix = $prefix;
158
159
        return $this;
160
    }
161
162
    /**
163
     * Determine if the Xinge response is success.
164
     *
165
     * @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
166
     *
167
     * @param  mixed  $response
168
     * @return bool
169
     */
170
    public function succeed($response)
171
    {
172
        return $this->code($response) === 0;
173
    }
174
175
    /**
176
     * Get the code of Xinge response.
177
     *
178
     * @param  mixed  $response
179
     * @return int|null
180
     */
181
    public function code($response)
182
    {
183
        if (is_array($response)) {
184
            return array_get($response, 'ret_code');
185
        }
186
    }
187
188
    /**
189
     * Get the error message of Xinge response.
190
     *
191
     * @param  mixed  $response
192
     * @return string|null
193
     */
194
    public function message($response)
195
    {
196
        if (is_array($response)) {
197
            return array_get($response, 'err_msg');
198
        }
199
    }
200
201
    /**
202
     * Get the result data of Xinge response.
203
     *
204
     * @param  mixed  $response
205
     * @param  string  $key
206
     * @param  mixed  $default
207
     * @return mixed
208
     */
209
    public function result($response, $key = null, $default = null)
210
    {
211
        if (is_array($response)) {
212
            return array_get($response, $key ? "result.{$key}" : 'result', $default);
213
        }
214
    }
215
216
    /**
217
     * Encode the custom data.
218
     *
219
     * @param  mixed  $data
220
     * @return array
221
     */
222
    public function encodeCustomData($data)
223
    {
224
        if ($this->customKey && $data) {
225
            return [$this->customKey => $data];
226
        }
227
228
        return $data ?: [];
229
    }
230
231
    /**
232
     * Get Xinge account for the given user.
233
     *
234
     * @param  mixed  $user
235
     * @return string
236
     */
237
    public function accountForUser($user)
238
    {
239
        if ($this->accountPrefix && is_string($user) && starts_with($user, $this->accountPrefix)) {
240
            return $user;
241
        }
242
243 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...
244
            $user = $user->id;
245
        } elseif (is_array($user)) {
246
            $user = $user['id'];
247
        }
248
249
        return $this->accountPrefix.$user;
250
    }
251
252
    /**
253
     * Get Xinge accounts for users.
254
     *
255
     * @param  array $users
256
     * @return array
257
     */
258
    public function accountsForUsers(array $users)
259
    {
260
        return array_map([$this, 'accountForUser'], $users);
261
    }
262
263
    /**
264
     * Creates a new MessageIOS instance.
265
     *
266
     * @param  string  $alert
267
     * @param  mixed  $custom
268
     * @param  int  $badge
269
     * @param  string  $sound
270
     * @return \ElfSundae\XgPush\MessageIOS
271
     */
272
    public function createIOSMessage($alert = '', $custom = null, $badge = 1, $sound = 'default')
273
    {
274
        $message = new MessageIOS();
275
        $message->setAlert($alert);
276
        $message->setCustom($this->encodeCustomData($custom));
277
        if (is_int($badge) && $badge >= 0) {
278
            $message->setBadge($badge);
279
        }
280
        if ($sound) {
281
            $message->setSound($sound);
282
        }
283
284
        return $message;
285
    }
286
287
    /**
288
     * Create a new Message instance.
289
     *
290
     * @param  string  $title
291
     * @param  string  $content
292
     * @param  mixed  $custom
293
     * @param  int  $type
294
     * @return \ElfSundae\XgPush\Message
295
     */
296
    public function createAndroidMessage($title = '', $content = '', $custom = null, $type = Message::TYPE_MESSAGE)
297
    {
298
        $message = new Message();
299
        $message->setTitle($title);
300
        $message->setContent($content);
301
        $message->setCustom($this->encodeCustomData($custom));
302
        $message->setType($type);
303
304
        return $message;
305
    }
306
307
    /**
308
     * Create a new Message instance for notification.
309
     * The default action is opening app.
310
     *
311
     * @param  string  $title
312
     * @param  string  $content
313
     * @param  mixed  $custom
314
     * @return \ElfSundae\XgPush\Message
315
     */
316
    public function createAndroidNotification($title = '', $content = '', $custom = null)
317
    {
318
        $message = $this->createAndroidMessage($title, $content, $custom, Message::TYPE_NOTIFICATION);
319
320
        $message->setStyle(new Style(0, 1, 1, 1, 0));
321
        $action = new ClickAction();
322
        $action->setActionType(ClickAction::TYPE_ACTIVITY);
323
        $message->setAction($action);
324
325
        return $message;
326
    }
327
328
    /**
329
     * Push message to a device.
330
     *
331
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
332
     * @param  string  $deviceToken
333
     * @return array
334
     */
335
    public function toDevice($message, $deviceToken)
336
    {
337
        return $this->xinge->PushSingleDevice($deviceToken, $message, $this->environment);
338
    }
339
340
    /**
341
     * Push message to all devices.
342
     *
343
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
344
     * @return array
345
     */
346
    public function toAllDevices($message)
347
    {
348
        return $this->xinge->PushAllDevices(0, $message, $this->environment);
349
    }
350
351
    /**
352
     * Push message to users.
353
     *
354
     * @warning 用户数限制 100 个。
355
     *
356
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
357
     * @param  mixed  $users
358
     * @return array
359
     */
360
    public function toUser($message, $users)
361
    {
362
        $accounts = $this->accountsForUsers($this->getParameterAsArray(func_get_args(), 1));
363
364
        if (count($accounts) == 1) {
365
            return $this->xinge->PushSingleAccount(0, $accounts[0], $message, $this->environment);
366
        }
367
368
        return $this->xinge->PushAccountList(0, $accounts, $message, $this->environment);
369
    }
370
371
    /**
372
     * Push message to tagged devices.
373
     *
374
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
375
     * @param  string|string[]  $tags
376
     * @param  string  $tagsOperation  'OR', 'AND'
377
     * @return array
378
     */
379
    public function toTags($message, $tags, $tagsOperation = 'OR')
380
    {
381
        return $this->xinge->PushTags(0, (array) $tags, strtoupper($tagsOperation), $message, $this->environment);
382
    }
383
384
    /**
385
     * Create a batch push.
386
     *
387
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
388
     * @return string|null
389
     */
390
    public function createBatch($message)
391
    {
392
        return $this->result($this->xinge->CreateMultipush($message, $this->environment), 'push_id');
393
    }
394
395
    /**
396
     * Batch pushing to a list of users.
397
     *
398
     * @warning 用户数限制 1000 个。
399
     *
400
     * @param  int|string  $pushId
401
     * @param  mixed $users
402
     * @return array
403
     */
404
    public function batchToUsers($pushId, $users)
405
    {
406
        return $this->xinge->PushAccountListMultiple(
407
            $pushId,
408
            $this->accountsForUsers($this->getParameterAsArray(func_get_args(), 1))
409
        );
410
    }
411
412
    /**
413
     * Batch pushing to a list of devices.
414
     *
415
     * @warning 设备数限制 1000 个。
416
     *
417
     * @param  int|string  $pushId
418
     * @param  mixed  $deviceTokens
419
     * @return array
420
     */
421
    public function batchToDevices($pushId, $deviceTokens)
422
    {
423
        return $this->xinge->PushDeviceListMultiple(
424
            $pushId,
425
            $this->getParameterAsArray(func_get_args(), 1)
426
        );
427
    }
428
429
    /**
430
     * Query group pushing status.
431
     *
432
     * @param  mixed  $pushIds
433
     * @return array
434
     */
435
    public function queryPushStatus($pushIds)
436
    {
437
        $pushIds = $this->getParameterAsArray(func_get_args());
438
439
        $list = $this->result($this->xinge->QueryPushStatus($pushIds), 'list', []);
440
441
        return array_combine(array_pluck($list, 'push_id'), $list);
442
    }
443
444
    /**
445
     * Cancel a timed pushing task that has not been pushed.
446
     *
447
     * @param  string  $pushId
448
     * @return array
449
     */
450
    public function cancelTimedPush($pushId)
451
    {
452
        return $this->xinge->CancelTimingPush($pushId);
453
    }
454
455
    /**
456
     * Query all device tokens for the given user.
457
     *
458
     * @param  mixed  $user
459
     * @return string[]
460
     */
461
    public function queryDeviceTokensForUser($user)
462
    {
463
        return $this->result($this->xinge->QueryTokensOfAccount($this->accountForUser($user)), 'tokens', []);
464
    }
465
466
    /**
467
     * Delete device tokens for the given user.
468
     *
469
     * @param  mixed  $user
470
     * @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...
471
     * @return bool
472
     */
473
    public function deleteDeviceTokensForUser($user, $deviceTokens = null)
474
    {
475
        $account = $this->accountForUser($user);
476
477
        if (is_null($deviceTokens)) {
478
            return $this->succeed($this->xinge->DeleteAllTokensOfAccount($account));
479
        }
480
481
        $deviceTokens = array_unique((array) $deviceTokens);
482
483
        $result = true;
484
485
        foreach ($deviceTokens as $token) {
486
            $result = $result && $this->succeed($this->xinge->DeleteTokenOfAccount($account, $token));
487
        }
488
489
        return $result;
490
    }
491
492
    /**
493
     * Query count of registered devices.
494
     *
495
     * @return int
496
     */
497
    public function queryCountOfDevices()
498
    {
499
        return $this->result($this->xinge->QueryDeviceCount(), 'device_num', 0);
500
    }
501
502
    /**
503
     * Query info for the given device token.
504
     *
505
     * @param  string  $deviceToken
506
     * @return array
507
     */
508
    public function queryDeviceTokenInfo($deviceToken)
509
    {
510
        return $this->xinge->QueryInfoOfToken($deviceToken);
511
    }
512
513
    /**
514
     * Query count of registered tokens for the given tag.
515
     *
516
     * @param  string  $tag
517
     * @return int
518
     */
519
    public function queryCountOfDeviceTokensForTag($tag)
520
    {
521
        return $this->result($this->xinge->QueryTagTokenNum($tag), 'device_num', 0);
522
    }
523
524
    /**
525
     * Query tags.
526
     *
527
     * @return array
528
     */
529
    public function queryTags($start = 0, $limit = 100)
530
    {
531
        return $this->xinge->QueryTags($start, $limit);
532
    }
533
534
    /**
535
     * Query all tags for the given device token.
536
     *
537
     * @param  string  $deviceToken
538
     * @return string[]
539
     */
540
    public function queryTagsForDeviceToken($deviceToken)
541
    {
542
        return $this->result($this->xinge->QueryTokenTags($deviceToken), 'tags', []);
543
    }
544
545
    /**
546
     * Query all tags for the given user.
547
     *
548
     * @param  mixed  $user
549
     * @param  array  &$deviceTokens
550
     * @return array
551
     */
552
    public function queryTagsForUser($user, &$deviceTokens = null)
553
    {
554
        $deviceTokens = $this->queryDeviceTokensForUser($user);
555
556
        $result = [];
557
        foreach ($deviceTokens as $token) {
558
            $result[$token] = $this->queryTagsForDeviceToken($token);
559
        }
560
561
        return $result;
562
    }
563
564
    /**
565
     * Add tags for device tokens.
566
     *
567
     * @warning 每次最多设置 20 对。
568
     *
569
     * @param  \ElfSundae\XgPush\TagTokenPair[]  $tagTokenPairs
570
     * @return bool
571
     */
572
    public function addTags($tagTokenPairs)
573
    {
574
        return $this->succeed($this->xinge->BatchSetTag($tagTokenPairs));
575
    }
576
577
    /**
578
     * Add tags for the given device token.
579
     *
580
     * @param  string  $deviceToken
581
     * @param  mixed  $tags
582
     * @return bool
583
     */
584
    public function addTagsForDeviceToken($deviceToken, $tags)
585
    {
586
        return $this->addTags(
587
            $this->createTagTokenPairs($this->getParameterAsArray(func_get_args(), 1), $deviceToken)
588
        );
589
    }
590
591
    /**
592
     * Add tags for the given user.
593
     *
594
     * @param  mixed  $user
595
     * @param  mixed  $tags
596
     * @return bool
597
     */
598
    public function addTagsForUser($user, $tags)
599
    {
600
        return $this->addTags(
601
            $this->createTagTokenPairs(
602
                $this->getParameterAsArray(func_get_args(), 1),
603
                $this->queryDeviceTokensForUser($user)
604
            )
605
        );
606
    }
607
608
    /**
609
     * Remove tags for device tokens.
610
     *
611
     * @warning 每次最多删除 20 对。
612
     *
613
     * @param  \ElfSundae\XgPush\TagTokenPair[]  $tagTokenPairs
614
     * @return bool
615
     */
616
    public function removeTags($tagTokenPairs)
617
    {
618
        return $this->succeed($this->xinge->BatchDelTag($tagTokenPairs));
619
    }
620
621
    /**
622
     * Remove tags for the given device token.
623
     *
624
     * @param  string  $deviceToken
625
     * @param  mixed  $tags
626
     * @return bool
627
     */
628
    public function removeTagsForDeviceToken($deviceToken, $tags)
629
    {
630
        return $this->removeTags(
631
            $this->createTagTokenPairs($this->getParameterAsArray(func_get_args(), 1), $deviceToken)
632
        );
633
    }
634
635
    /**
636
     * Remove tags for the given user.
637
     *
638
     * @param  mixed  $user
639
     * @param  mixed  $tags
640
     * @return bool
641
     */
642
    public function removeTagsForUser($user, $tags)
643
    {
644
        return $this->removeTags(
645
            $this->createTagTokenPairs(
646
                $this->getParameterAsArray(func_get_args(), 1),
647
                $this->queryDeviceTokensForUser($user)
648
            )
649
        );
650
    }
651
652
    /**
653
     * Get parameter as array.
654
     *
655
     * @param  array  $args
656
     * @param  int $offset
657
     * @return array
658
     */
659
    protected function getParameterAsArray(array $args, $offset = 0)
660
    {
661
        return is_array($args[$offset]) ? $args[$offset] : array_slice($args, $offset);
662
    }
663
664
    /**
665
     * Create array of TagTokenPair.
666
     *
667
     * @warning $tags 和 $tokens 一个是数组,另一个是字符串
668
     *
669
     * @param  string|string[]  $tags
670
     * @param  string|string[]  $tokens
671
     * @return \ElfSundae\XgPush\TagTokenPair[]
672
     */
673
    protected function createTagTokenPairs($tags, $tokens)
674
    {
675
        $tagTokenPairs = [];
676
677
        $tokens = (array) $tokens;
678
        foreach ((array) $tags as $tag) {
679
            foreach ($tokens as $token) {
680
                $tagTokenPairs[] = new TagTokenPair($tag, $token);
681
            }
682
        }
683
684
        return $tagTokenPairs;
685
    }
686
687
    /**
688
     * Dynamically handle calls to the XingeApp instance.
689
     *
690
     * @param  string  $method
691
     * @param  array   $parameters
692
     * @return mixed
693
     */
694
    public function __call($method, $parameters)
695
    {
696
        return call_user_func_array([$this->xinge, $method], $parameters);
697
    }
698
}
699