Completed
Push — master ( ed6d73...5b44ef )
by Elf
04:52
created

XgPusher::toDevice()   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 2
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\XingeApp;
10
11
class XgPusher
12
{
13
    /**
14
     * The XingeApp instance.
15
     *
16
     * @var \ElfSundae\XgPush\XingeApp
17
     */
18
    protected $xinge;
19
20
    /**
21
     * The pusher environment.
22
     *
23
     * 向iOS设备推送时必填,1表示推送生产环境;2表示推送开发环境。推送Android平台不填或填0.
24
     *
25
     * @var int
26
     */
27
    protected $environment = XingeApp::IOSENV_DEV;
28
29
    /**
30
     * The key of custom payload.
31
     *
32
     * @var string
33
     */
34
    protected $customKey;
35
36
    /**
37
     * Xinge account prefix.
38
     *
39
     * @warning 信鸽不允许使用简单的账号,例如纯数字的id。
40
     *
41
     * @var string
42
     */
43
    protected $accountPrefix;
44
45
    /**
46
     * Create a new instance.
47
     *
48
     * @param  string  $appKey
49
     * @param  string  $appSecret
50
     */
51
    public function __construct($appKey, $appSecret)
52
    {
53
        $this->xinge = new XingeApp($appKey, $appSecret);
54
    }
55
56
    /**
57
     * Get the XingeApp instance.
58
     *
59
     * @return \ElfSundae\XgPush\XingeApp
60
     */
61
    public function getXinge()
62
    {
63
        return $this->xinge;
64
    }
65
66
    /**
67
     * Get the app key.
68
     *
69
     * @return string
70
     */
71
    public function getAppKey()
72
    {
73
        return $this->xinge->accessId;
74
    }
75
76
    /**
77
     * Get the app secret.
78
     *
79
     * @return string
80
     */
81
    public function getAppSecret()
82
    {
83
        return $this->xinge->secretKey;
84
    }
85
86
    /**
87
     * Get the pusher environment.
88
     *
89
     * @return int
90
     */
91
    public function getEnvironment()
92
    {
93
        return $this->environment;
94
    }
95
96
    /**
97
     * Set the pusher environment.
98
     *
99
     * @param  mixed  $env
100
     * @return $this
101
     */
102
    public function setEnvironment($env)
103
    {
104
        if (is_string($env)) {
105
            $env = $env == 'production' ? XingeApp::IOSENV_PROD : XingeApp::IOSENV_DEV;
106
        }
107
108
        if (is_int($env)) {
109
            $this->environment = $env;
110
        }
111
112
        return $this;
113
    }
114
115
    /**
116
     * Get the key of custom payload.
117
     *
118
     * @return string|null
119
     */
120
    public function getCustomKey()
121
    {
122
        return $this->customKey;
123
    }
124
125
    /**
126
     * Set the key of custom payload.
127
     *
128
     * @param  string|null  $key
129
     * @return $this
130
     */
131
    public function setCustomKey($key)
132
    {
133
        $this->customKey = $key;
134
135
        return $this;
136
    }
137
138
    /**
139
     * Get the account prefix.
140
     *
141
     * @return string
142
     */
143
    public function getAccountPrefix()
144
    {
145
        return $this->accountPrefix;
146
    }
147
148
    /**
149
     * Set the account prefix.
150
     *
151
     * @param  string  $prefix
152
     * @return $this
153
     */
154
    public function setAccountPrefix($prefix)
155
    {
156
        $this->accountPrefix = $prefix;
157
158
        return $this;
159
    }
160
161
    /**
162
     * Determine if the Xinge response is success.
163
     *
164
     * @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
165
     *
166
     * @param  mixed  $response
167
     * @return bool
168
     */
169
    public function succeed($response)
170
    {
171
        return $this->code($response) === 0;
172
    }
173
174
    /**
175
     * Get the code of Xinge response.
176
     *
177
     * @param  mixed  $response
178
     * @return int|null
179
     */
180
    public function code($response)
181
    {
182
        if (is_array($response)) {
183
            return array_get($response, 'ret_code');
184
        }
185
    }
186
187
    /**
188
     * Get the error message of Xinge response.
189
     *
190
     * @param  mixed  $response
191
     * @return string|null
192
     */
193
    public function message($response)
194
    {
195
        if (is_array($response)) {
196
            return array_get($response, 'err_msg');
197
        }
198
    }
199
200
    /**
201
     * Get the result data of Xinge response.
202
     *
203
     * @param  mixed  $response
204
     * @return mixed|null
205
     */
206
    public function result($response, $key = null)
207
    {
208
        if (is_array($response)) {
209
            return array_get($response, $key ? "result.{$key}" : 'result');
210
        }
211
    }
212
213
    /**
214
     * Encode the custom data.
215
     *
216
     * @param  mixed  $data
217
     * @return array
218
     */
219
    public function encodeCustomData($data)
220
    {
221
        if ($this->customKey && $data) {
222
            return [$this->customKey => $data];
223
        }
224
225
        return $data ?: [];
226
    }
227
228
    /**
229
     * Get Xinge account for the given user.
230
     *
231
     * @param  mixed  $user
232
     * @return string
233
     */
234
    public function accountForUser($user)
235
    {
236
        if ($this->accountPrefix && is_string($user) && starts_with($user, $this->accountPrefix)) {
237
            return $user;
238
        }
239
240 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...
241
            $user = $user->id;
242
        } elseif (is_array($user)) {
243
            $user = $user['id'];
244
        }
245
246
        return $this->accountPrefix.$user;
247
    }
248
249
    /**
250
     * Creates a new MessageIOS instance.
251
     *
252
     * @param  string  $alert
253
     * @param  mixed  $custom
254
     * @param  int  $badge
255
     * @param  string  $sound
256
     * @return \ElfSundae\XgPush\MessageIOS
257
     */
258
    public function createIOSMessage($alert = '', $custom = null, $badge = 1, $sound = 'default')
259
    {
260
        $message = new MessageIOS();
261
        $message->setAlert($alert);
262
        $message->setCustom($this->encodeCustomData($custom));
263
        if (is_int($badge) && $badge >= 0) {
264
            $message->setBadge($badge);
265
        }
266
        if ($sound) {
267
            $message->setSound($sound);
268
        }
269
270
        return $message;
271
    }
272
273
    /**
274
     * Create a new Message instance.
275
     *
276
     * @param  string  $title
277
     * @param  string  $content
278
     * @param  mixed  $custom
279
     * @param  int  $type
280
     * @return \ElfSundae\XgPush\Message
281
     */
282
    public function createAndroidMessage($title = '', $content = '', $custom = null, $type = Message::TYPE_MESSAGE)
283
    {
284
        $message = new Message();
285
        $message->setTitle($title);
286
        $message->setContent($content);
287
        $message->setCustom($this->encodeCustomData($custom));
288
        $message->setType($type);
289
290
        return $message;
291
    }
292
293
    /**
294
     * Create a new Message instance for notification.
295
     * The default action is opening app.
296
     *
297
     * @param  string  $title
298
     * @param  string  $content
299
     * @param  mixed  $custom
300
     * @return \ElfSundae\XgPush\Message
301
     */
302
    public function createAndroidNotification($title = '', $content = '', $custom = null)
303
    {
304
        $message = $this->createAndroidMessage($title, $content, $custom, Message::TYPE_NOTIFICATION);
305
306
        $message->setStyle(new Style(0, 1, 1, 1, 0));
307
        $action = new ClickAction();
308
        $action->setActionType(ClickAction::TYPE_ACTIVITY);
309
        $message->setAction($action);
310
311
        return $message;
312
    }
313
314
    /**
315
     * Push message to a device.
316
     *
317
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
318
     * @param  string  $deviceToken
319
     * @return array
320
     */
321
    public function toDevice($message, $deviceToken)
322
    {
323
        return $this->xinge->PushSingleDevice($deviceToken, $message, $this->environment);
324
    }
325
326
    /**
327
     * Push message to all devices.
328
     *
329
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
330
     * @return array
331
     */
332
    public function toAllDevices($message)
333
    {
334
        return $this->xinge->PushAllDevices(0, $message, $this->environment);
335
    }
336
337
    /**
338
     * Push message to users.
339
     *
340
     * @warning 用户数限制 100 个。
341
     *
342
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
343
     * @param  mixed  $users
344
     * @return array
345
     */
346
    public function toUser($message, $users)
347
    {
348
        if (! is_array($users)) {
349
            $users = array_slice(func_get_args(), 1);
350
        }
351
352
        $accounts = array_map([$this, 'accountForUser'], $users);
353
354
        if (count($accounts) == 1) {
355
            return $this->xinge->PushSingleAccount(0, $accounts[0], $message, $this->environment);
356
        }
357
358
        return $this->xinge->PushAccountList(0, $accounts, $message, $this->environment);
359
    }
360
361
    /**
362
     * Push message to tagged devices.
363
     *
364
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
365
     * @param  string|string[]  $tags
366
     * @param  string  $tagsOperation  'OR', 'AND'
367
     * @return array
368
     */
369
    public function toTags($message, $tags, $tagsOperation = 'OR')
370
    {
371
        return $this->xinge->PushTags(0, (array) $tags, strtoupper($tagsOperation), $message, $this->environment);
372
    }
373
374
    /**
375
     * Create a batch push.
376
     *
377
     * @param  \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS  $message
378
     * @return string|null
379
     */
380
    public function createBatch($message)
381
    {
382
        return $this->result($this->xinge->CreateMultipush($message, $this->environment), 'push_id');
383
    }
384
385
    /**
386
     * Batch pushing to a list of users.
387
     *
388
     * @warning 用户数限制 1000 个。
389
     *
390
     * @param  int|string  $pushId
391
     * @param  string|string[] $users
392
     * @return array
393
     */
394
    public function batchToUsers($pushId, $users)
395
    {
396
        $accounts = array_map([$this, 'accountForUser'], (array) $users);
397
398
        return $this->xinge->PushAccountListMultiple($pushId, $accounts);
399
    }
400
401
    /**
402
     * Batch pushing to a list of devices.
403
     *
404
     * @param  int|string  $pushId
405
     * @param  string|string[]  $devices
406
     * @return array
407
     */
408
    public function batchToDevices($pushId, $devices)
409
    {
410
        return $this->xinge->PushDeviceListMultiple($pushId, (array) $devices);
411
    }
412
413
    /**
414
     * Query group pushing status.
415
     *
416
     * @param  mixed  $pushIds
417
     * @return array
418
     */
419
    public function queryPushStatus($pushIds)
420
    {
421
        if (! is_array($pushIds)) {
422
            $pushIds = func_get_args();
423
        }
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 count of registered devices.
443
     *
444
     * @return int
445
     */
446
    public function queryDevicesCount()
447
    {
448
        return $this->result($this->xinge->QueryDeviceCount(), 'device_num');
449
    }
450
451
    /**
452
     * Query tags.
453
     *
454
     * @return array
455
     */
456
    public function queryTags($start = 0, $limit = 100)
457
    {
458
        return $this->result($this->xinge->QueryTags($start, $limit));
459
    }
460
461
    /**
462
     * Query all tags for the given device token.
463
     *
464
     * @param  string  $deviceToken
465
     * @return string[]|null
466
     */
467
    public function queryTagsForDeviceToken($deviceToken)
468
    {
469
        return $this->result($this->xinge->QueryTokenTags($deviceToken), 'tags');
470
    }
471
472
    /**
473
     * Query all device tokens for the given user.
474
     *
475
     * @param  mixed  $user
476
     * @return string[]|null
477
     */
478
    public function queryDeviceTokensForUser($user)
479
    {
480
        return $this->result($this->xinge->QueryTokensOfAccount($this->accountForUser($user)), 'tokens');
481
    }
482
483
    /**
484
     * Query all tags for the given user.
485
     *
486
     * @param  mixed  $user
487
     * @param  array  &$deviceTokens
488
     * @return array|null
489
     */
490
    public function queryTagsForUser($user, &$deviceTokens = null)
491
    {
492
        $deviceTokens = $this->queryDeviceTokensForUser($user);
493
494
        if (is_array($deviceTokens)) {
495
            $result = [];
496
            foreach ($deviceTokens as $token) {
497
                $result[$token] = $this->queryTagsForDeviceToken($token) ?: [];
498
            }
499
500
            return $result;
501
        }
502
    }
503
504
    /**
505
     * Dynamically handle calls to the XingeApp instance.
506
     *
507
     * @param  string  $method
508
     * @param  array   $parameters
509
     * @return mixed
510
     */
511
    public function __call($method, $parameters)
512
    {
513
        return call_user_func_array([$this->xinge, $method], $parameters);
514
    }
515
}
516