Completed
Push — master ( e66d9e...163e54 )
by Elf
04:22
created

XgPusher::__callStatic()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 6
ccs 0
cts 3
cp 0
crap 2
rs 9.4285
1
<?php
2
3
namespace App\Support\Tencent;
4
5
use ElfSundae\XgPush\XingeApp;
6
7
class XgPusher
8
{
9
    /**
10
     * The XingeApp instance.
11
     *
12
     * @var \ElfSundae\XgPush\XingeApp
13
     */
14
    protected $service;
15
16
    /**
17
     * Create a new instance.
18
     */
19
    public function __construct()
20
    {
21
        $this->service = static::createService();
22
    }
23
24
    /**
25
     * Get the XingeApp instance.
26
     *
27
     * @return \ElfSundae\XgPush\XingeApp
28
     */
29
    public function getService()
30
    {
31
        return $this->service;
32
    }
33
34
    /**
35
     * Create a XingeApp instance.
36
     *
37
     * @return \ElfSundae\XgPush\XingeApp
38
     */
39
    public static function createService()
40
    {
41
        return new XingeApp(static::appKey(), static::appSecret());
42
    }
43
44
    /**
45
     * Get the app key.
46
     *
47
     * @return string
48
     */
49
    public static function appKey()
50
    {
51
        return config('services.xgpush.key');
52
    }
53
54
    /**
55
     * Get the app secret.
56
     *
57
     * @return string
58
     */
59
    public static function appSecret()
60
    {
61
        return config('services.xgpush.secret');
62
    }
63
64
    /**
65
     * Get the custom key.
66
     *
67
     * @return string
68
     */
69
    public static function customKey()
70
    {
71
        return config('services.xgpush.custom_key', 'custom');
72
    }
73
74
    /**
75
     * Get the environment.
76
     *
77
     * environment: 向iOS设备推送时必填,1表示推送生产环境;2表示推送开发环境。推送Android平台不填或填0.
78
     *
79
     * @return int
80
     */
81
    public static function environment()
82
    {
83
        return config('services.xgpush.environment') == 'production' ?
84
            XingeApp::IOSENV_PROD :
85
            XingeApp::IOSENV_DEV;
86
    }
87
88
    /**
89
     * 解析信鸽返回的结果。
90
     *
91
     * @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
92
     *
93
     * @param  mixed    $xgResult   信鸽的请求结果
94
     * @param  int      &$code      返回码,0 为成功
95
     * @param  string   &$message   请求出错时的错误信息
96
     * @param  mixed    &$result    请求正确时的额外数据
97
     * @return bool
98
     */
99
    public static function parseResult($xgResult = null, &$code = null, &$message = null, &$result = null)
100
    {
101
        if (is_array($xgResult) && isset($xgResult['ret_code'])) {
102
            $code = (int) $xgResult['ret_code'];
103
            $message = isset($xgResult['err_msg']) ? (string) $xgResult['err_msg'] : '';
104
            if (isset($xgResult['result'])) {
105
                $result = $xgResult['result'];
106
            }
107
        } else {
108
            $code = -99999;
109
        }
110
111
        return $code === 0;
112
    }
113
114
    /**
115
     * Encode the custom data.
116
     *
117
     * @param  mixed  $data
118
     * @return array|null
119
     */
120
    public static function encodeCustomData($data)
121
    {
122
        return ! empty($data) ? [static::customKey() => $data] : null;
123
    }
124
125
    /**
126
     * Get Xinge account for the given user.
127
     *
128
     * @param  mixed  $user
129
     * @return string
130
     */
131
    public static function accountForUser($user)
132
    {
133 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...
134
            $user = $user->id;
135
        } elseif (is_array($user)) {
136
            $user = $user['id'];
137
        }
138
139
        // 信鸽不允许使用简单的账号,例如纯数字的id。
140
        // 所以在 userId 前面加个 'user' 字符。
141
        if (starts_with($user, 'user')) {
142
            return $user;
143
        }
144
145
        return 'user'.$user;
146
    }
147
148
    /**
149
     * Creates a MessageIOS instance.
150
     *
151
     * @param  string  $alert
152
     * @param  mixed  $custom
153
     * @param  int  $badge
154
     * @param  string  $sound
155
     * @return MessageIOS
156
     */
157
    public static function createIOSMessage($alert = '', $custom = null, $badge = 1, $sound = 'default')
158
    {
159
        $message = new MessageIOS();
160
        $message->setAlert($alert);
161
        if ($customData = static::encodeCustomData($custom)) {
162
            $message->setCustom($customData);
163
        }
164
        if (is_numeric($badge) && $badge >= 0) {
165
            $message->setBadge($badge);
166
        }
167
        if (! empty($sound)) {
168
            $message->setSound($sound);
169
        }
170
171
        return $message;
172
    }
173
174
    /**
175
     * Create a Message instance.
176
     *
177
     * @param  string $content
178
     * @param  mixed $custom
179
     * @param  string $title
180
     * @param  int $type
181
     * @return Message
182
     */
183
    public static function createAndroidMessage($content = '', $custom = null, $title = null, $type = Message::TYPE_NOTIFICATION)
184
    {
185
        $message = new Message();
186
        $message->setTitle($title ?: config('app.name'));
187
        $message->setContent($content);
188
        if ($customData = static::encodeCustomData($custom)) {
189
            $message->setCustom($customData);
190
        }
191
        $message->setType($type);
192
        //含义:样式编号0,响铃,震动,不可从通知栏清除,不影响先前通知
193
        $message->setStyle(new Style(0, 1, 1, 1, 0));
194
        $action = new ClickAction();
195
        $action->setActionType(ClickAction::TYPE_ACTIVITY);
196
        $message->setAction($action);
197
198
        return $message;
199
    }
200
201
    /**
202
     * Query all device tokens for the given user.
203
     *
204
     * @param  mixed  $user
205
     * @return string[]|null
206
     */
207 View Code Duplication
    public static function queryDeviceTokensForUser($user)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
208
    {
209
        $query = static::createService()->QueryTokensOfAccount(static::accountForUser($user));
210
211
        if (static::parseResult($query, null, null, $result)) {
0 ignored issues
show
Bug introduced by
null cannot be passed to parseresult() as the parameter $code expects a reference.
Loading history...
Bug introduced by
null cannot be passed to parseresult() as the parameter $message expects a reference.
Loading history...
212
            return is_array($result) ? array_get($result, 'tokens', []) : [];
213
        }
214
    }
215
216
    /**
217
     * Query all tags for the given device token.
218
     *
219
     * @param  string  $deviceToken
220
     * @return string[]|null
221
     */
222 View Code Duplication
    public static function queryTagsForDeviceToken($deviceToken)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
223
    {
224
        $query = static::createService()->QueryTokenTags($deviceToken);
225
226
        if (static::parseResult($query, null, null, $result)) {
0 ignored issues
show
Bug introduced by
null cannot be passed to parseresult() as the parameter $code expects a reference.
Loading history...
Bug introduced by
null cannot be passed to parseresult() as the parameter $message expects a reference.
Loading history...
227
            return is_array($result) ? array_get($result, 'tags', []) : [];
228
        }
229
    }
230
231
    /**
232
     * Query all tags for the given user.
233
     *
234
     * @param  mixed  $user
235
     * @param  array  &$deviceTokens
236
     * @return array|null
237
     */
238
    public static function queryTagsForUser($user, &$deviceTokens = null)
239
    {
240
        $deviceTokens = static::queryDeviceTokensForUser($user);
241
242
        $result = [];
243
        foreach ($deviceTokens as $token) {
0 ignored issues
show
Bug introduced by
The expression $deviceTokens of type array<integer,string>|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
244
            if ($tags = static::queryTagsForDeviceToken($token)) {
245
                $result[$token] = $tags;
246
            }
247
        }
248
249
        return $result;
250
    }
251
252
    /**
253
     * Dynamically handle calls to the XingeApp class.
254
     *
255
     * @param  string  $method
256
     * @param  array   $parameters
257
     * @return mixed
258
     */
259
    public static function __callStatic($method, $parameters)
260
    {
261
        array_unshift($parameters, static::appKey(), static::appSecret());
262
263
        return call_user_func_array([XingeApp::class, $method], $parameters);
264
    }
265
266
    /**
267
     * Dynamically handle calls to the XingeApp instance.
268
     *
269
     * @param  string  $method
270
     * @param  array   $parameters
271
     * @return mixed
272
     */
273
    public function __call($method, $parameters)
274
    {
275
        return call_user_func_array([$this->getService(), $method], $parameters);
276
    }
277
}
278