Completed
Push — master ( 31b3b0...bda6dc )
by Elf
06:16
created

XgPusher::xinge()   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 0
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
     * @return mixed|null
206
     */
207
    public function result($response, $key = null)
208
    {
209
        if (is_array($response)) {
210
            return array_get($response, $key ? "result.{$key}" : 'result');
211
        }
212
    }
213
214
    /**
215
     * Encode the custom data.
216
     *
217
     * @param  mixed  $data
218
     * @return array
219
     */
220
    public function encodeCustomData($data)
221
    {
222
        if ($this->customKey && $data) {
223
            return [$this->customKey => $data];
224
        }
225
226
        return $data ?: [];
227
    }
228
229
    /**
230
     * Get Xinge account for the given user.
231
     *
232
     * @param  mixed  $user
233
     * @return string
234
     */
235
    public function accountForUser($user)
236
    {
237
        if ($this->accountPrefix && is_string($user) && starts_with($user, $this->accountPrefix)) {
238
            return $user;
239
        }
240
241 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...
242
            $user = $user->id;
243
        } elseif (is_array($user)) {
244
            $user = $user['id'];
245
        }
246
247
        return $this->accountPrefix.$user;
248
    }
249
250
    /**
251
     * Creates a new MessageIOS instance.
252
     *
253
     * @param  string  $alert
254
     * @param  mixed  $custom
255
     * @param  int  $badge
256
     * @param  string  $sound
257
     * @return \ElfSundae\XgPush\MessageIOS
258
     */
259
    public function createIOSMessage($alert = '', $custom = null, $badge = 1, $sound = 'default')
260
    {
261
        $message = new MessageIOS();
262
        $message->setAlert($alert);
263
        $message->setCustom($this->encodeCustomData($custom));
264
        if (is_int($badge) && $badge >= 0) {
265
            $message->setBadge($badge);
266
        }
267
        if ($sound) {
268
            $message->setSound($sound);
269
        }
270
271
        return $message;
272
    }
273
274
    /**
275
     * Create a new Message instance.
276
     *
277
     * @param  string  $title
278
     * @param  string  $content
279
     * @param  mixed  $custom
280
     * @param  int  $type
281
     * @return \ElfSundae\XgPush\Message
282
     */
283
    public function createAndroidMessage($title = '', $content = '', $custom = null, $type = Message::TYPE_MESSAGE)
284
    {
285
        $message = new Message();
286
        $message->setTitle($title);
287
        $message->setContent($content);
288
        $message->setCustom($this->encodeCustomData($custom));
289
        $message->setType($type);
290
291
        return $message;
292
    }
293
294
    /**
295
     * Create a new Message instance for notification.
296
     * The default action is opening app.
297
     *
298
     * @param  string  $title
299
     * @param  string  $content
300
     * @param  mixed  $custom
301
     * @return \ElfSundae\XgPush\Message
302
     */
303
    public function createAndroidNotification($title = '', $content = '', $custom = null)
304
    {
305
        $message = $this->createAndroidMessage($title, $content, $custom, Message::TYPE_NOTIFICATION);
306
307
        $message->setStyle(new Style(0, 1, 1, 1, 0));
308
        $action = new ClickAction();
309
        $action->setActionType(ClickAction::TYPE_ACTIVITY);
310
        $message->setAction($action);
311
312
        return $message;
313
    }
314
315
    /**
316
     * Push message to a device.
317
     *
318
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
319
     * @param  string  $deviceToken
320
     * @return array
321
     */
322
    public function toDevice($message, $deviceToken)
323
    {
324
        return $this->xinge->PushSingleDevice($deviceToken, $message, $this->environment);
325
    }
326
327
    /**
328
     * Push message to all devices.
329
     *
330
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
331
     * @return array
332
     */
333
    public function toAllDevices($message)
334
    {
335
        return $this->xinge->PushAllDevices(0, $message, $this->environment);
336
    }
337
338
    /**
339
     * Push message to users.
340
     *
341
     * @warning 用户数限制 100 个。
342
     *
343
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
344
     * @param  mixed  $users
345
     * @return array
346
     */
347
    public function toUser($message, $users)
348
    {
349
        if (! is_array($users)) {
350
            $users = array_slice(func_get_args(), 1);
351
        }
352
353
        $accounts = array_map([$this, 'accountForUser'], $users);
354
355
        if (count($accounts) == 1) {
356
            return $this->xinge->PushSingleAccount(0, $accounts[0], $message, $this->environment);
357
        }
358
359
        return $this->xinge->PushAccountList(0, $accounts, $message, $this->environment);
360
    }
361
362
    /**
363
     * Push message to tagged devices.
364
     *
365
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
366
     * @param  string|string[]  $tags
367
     * @param  string  $tagsOperation  'OR', 'AND'
368
     * @return array
369
     */
370
    public function toTags($message, $tags, $tagsOperation = 'OR')
371
    {
372
        return $this->xinge->PushTags(0, (array) $tags, strtoupper($tagsOperation), $message, $this->environment);
373
    }
374
375
    /**
376
     * Create a batch push.
377
     *
378
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
379
     * @return string|null
380
     */
381
    public function createBatch($message)
382
    {
383
        return $this->result($this->xinge->CreateMultipush($message, $this->environment), 'push_id');
384
    }
385
386
    /**
387
     * Batch pushing to a list of users.
388
     *
389
     * @warning 用户数限制 1000 个。
390
     *
391
     * @param  int|string  $pushId
392
     * @param  string|string[] $users
393
     * @return array
394
     */
395
    public function batchToUsers($pushId, $users)
396
    {
397
        $accounts = array_map([$this, 'accountForUser'], (array) $users);
398
399
        return $this->xinge->PushAccountListMultiple($pushId, $accounts);
400
    }
401
402
    /**
403
     * Batch pushing to a list of devices.
404
     *
405
     * @param  int|string  $pushId
406
     * @param  string|string[]  $devices
407
     * @return array
408
     */
409
    public function batchToDevices($pushId, $devices)
410
    {
411
        return $this->xinge->PushDeviceListMultiple($pushId, (array) $devices);
412
    }
413
414
    /**
415
     * Query group pushing status.
416
     *
417
     * @param  mixed  $pushIds
418
     * @return array
419
     */
420
    public function queryPushStatus($pushIds)
421
    {
422
        if (! is_array($pushIds)) {
423
            $pushIds = func_get_args();
424
        }
425
426
        $list = $this->result($this->xinge->QueryPushStatus($pushIds), 'list') ?: [];
427
428
        return array_combine(array_pluck($list, 'push_id'), $list);
429
    }
430
431
    /**
432
     * Cancel a timed pushing task that has not been pushed.
433
     *
434
     * @param  string  $pushId
435
     * @return array
436
     */
437
    public function cancelTimedPush($pushId)
438
    {
439
        return $this->xinge->CancelTimingPush($pushId);
440
    }
441
442
    /**
443
     * Query count of registered devices.
444
     *
445
     * @return int
446
     */
447
    public function queryCountOfDevices()
448
    {
449
        return $this->result($this->xinge->QueryDeviceCount(), 'device_num');
450
    }
451
452
    /**
453
     * Query info for the given device token.
454
     *
455
     * @param  string  $deviceToken
456
     * @return array
457
     */
458
    public function queryDeviceTokenInfo($deviceToken)
459
    {
460
        return $this->xinge->QueryInfoOfToken($deviceToken);
461
    }
462
463
    /**
464
     * Query count of registered tokens for the given tag.
465
     *
466
     * @param  string  $tag
467
     * @return int
468
     */
469
    public function queryCountOfDeviceTokensForTag($tag)
470
    {
471
        return $this->result($this->xinge->QueryTagTokenNum($tag), 'device_num');
472
    }
473
474
    /**
475
     * Query tags.
476
     *
477
     * @return array
478
     */
479
    public function queryTags($start = 0, $limit = 100)
480
    {
481
        return $this->result($this->xinge->QueryTags($start, $limit));
482
    }
483
484
    /**
485
     * Query all tags for the given device token.
486
     *
487
     * @param  string  $deviceToken
488
     * @return string[]|null
489
     */
490
    public function queryTagsForDeviceToken($deviceToken)
491
    {
492
        return $this->result($this->xinge->QueryTokenTags($deviceToken), 'tags');
493
    }
494
495
    /**
496
     * Query all tags for the given user.
497
     *
498
     * @param  mixed  $user
499
     * @param  array  &$deviceTokens
500
     * @return array|null
501
     */
502
    public function queryTagsForUser($user, &$deviceTokens = null)
503
    {
504
        $deviceTokens = $this->queryDeviceTokensForUser($user);
505
506
        if (is_array($deviceTokens)) {
507
            $result = [];
508
            foreach ($deviceTokens as $token) {
509
                $result[$token] = $this->queryTagsForDeviceToken($token) ?: [];
510
            }
511
512
            return $result;
513
        }
514
    }
515
516
    /**
517
     * Set tags for device tokens.
518
     *
519
     * @warning 每次最多设置 20 对。
520
     *
521
     * @param  \ElfSundae\XgPush\TagTokenPair[]  $tagTokenPairs
522
     * @return bool
523
     */
524
    public function setTags($tagTokenPairs)
525
    {
526
        return $this->succeed($this->xinge->BatchSetTag($tagTokenPairs));
527
    }
528
529
    /**
530
     * Delete tags for device tokens.
531
     *
532
     * @warning 每次最多删除 20 对。
533
     *
534
     * @param  \ElfSundae\XgPush\TagTokenPair[]  $tagTokenPairs
535
     * @return bool
536
     */
537
    public function deleteTags($tagTokenPairs)
538
    {
539
        return $this->succeed($this->xinge->BatchDelTag($tagTokenPairs));
540
    }
541
542
    /**
543
     * Query all device tokens for the given user.
544
     *
545
     * @param  mixed  $user
546
     * @return string[]|null
547
     */
548
    public function queryDeviceTokensForUser($user)
549
    {
550
        return $this->result($this->xinge->QueryTokensOfAccount($this->accountForUser($user)), 'tokens');
551
    }
552
553
    /**
554
     * Delete device tokens for the given user.
555
     *
556
     * @param  mixed  $user
557
     * @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...
558
     * @return bool
559
     */
560
    public function deleteDeviceTokensForUser($user, $deviceTokens = null)
561
    {
562
        $account = $this->accountForUser($user);
563
564
        if (is_null($deviceTokens)) {
565
            return $this->succeed($this->xinge->DeleteAllTokensOfAccount($account));
566
        }
567
568
        $deviceTokens = array_unique((array) $deviceTokens);
569
570
        $result = true;
571
572
        foreach ($deviceTokens as $token) {
573
            $result = $result && $this->succeed($this->xinge->DeleteTokenOfAccount($account, $token));
574
        }
575
576
        return $result;
577
    }
578
579
    /**
580
     * Dynamically handle calls to the XingeApp instance.
581
     *
582
     * @param  string  $method
583
     * @param  array   $parameters
584
     * @return mixed
585
     */
586
    public function __call($method, $parameters)
587
    {
588
        return call_user_func_array([$this->xinge, $method], $parameters);
589
    }
590
}
591