Completed
Push — master ( 6e3512...b3aa38 )
by Elf
05:23
created

Helper   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 353
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 1

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 34
c 0
b 0
f 0
lcom 0
cbo 1
dl 0
loc 353
ccs 0
cts 222
cp 0
rs 9.2

10 Methods

Rating   Name   Duplication   Size   Complexity  
A gravatar() 0 20 4
A fileExtensionForMimeType() 0 12 3
B iDeviceModel() 0 87 3
A mailHomepage() 0 20 3
A sampleDecrypt() 0 15 3
B sampleEncryption() 0 28 4
B int2string() 0 22 4
A string2int() 0 18 3
B addAcceptableJsonType() 0 20 5
A sampleEncrypt() 0 20 2
1
<?php
2
3
namespace ElfSundae\Laravel\Support;
4
5
use Illuminate\Http\Request;
6
use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;
7
8
class Helper
9
{
10
    /**
11
     * Generate a Gravatar URL.
12
     *
13
     * @see https://gravatar.com/site/implement/images/
14
     *
15
     * @param  string  $email
16
     * @param  int  $size
17
     * @param  string  $default
18
     * @param  string  $rating
19
     * @return string
20
     */
21
    public static function gravatar($email, $size = 120, $default = null, $rating = null)
22
    {
23
        if (is_null($default)) {
24
            $default = config('support.gravatar.default');
25
        }
26
27
        if (is_null($rating)) {
28
            $rating = config('support.gravatar.rating');
29
        }
30
31
        $query = http_build_query(array_filter(compact('size', 'default', 'rating')));
32
        if ($query) {
33
            $query = '?'.$query;
34
        }
35
36
        return app('url')->assetFrom(
37
            config('support.gravatar.host', 'https://www.gravatar.com/avatar'),
38
            md5(strtolower(trim($email))).$query
39
        );
40
    }
41
42
    /**
43
     * Add JSON type to the "Accept" header for the current request.
44
     *
45
     * @see https://laravel-china.org/topics/3430/modify-request-headers-incomplete-raiders
46
     *
47
     * @param  callable  $determination
48
     * @param  callable  $callback
49
     * @return mixed
50
     */
51
    public static function addAcceptableJsonType($determination = null, $callback = null)
52
    {
53
        return app()->rebinding('request', function ($app, $request) use ($determination, $callback) {
54
            if (is_null($determination) || call_user_func($determination, $request)) {
55
                $accept = $request->headers->get('Accept');
56
57
                if (! str_contains($accept, ['/json', '+json'])) {
58
                    $accept = rtrim('application/json,'.$accept, ',');
59
60
                    $request->headers->set('Accept', $accept);
61
                    $request->server->set('HTTP_ACCEPT', $accept);
62
                    $_SERVER['HTTP_ACCEPT'] = $accept;
63
64
                    if ($callback) {
65
                        call_user_func($callback, $request);
66
                    }
67
                }
68
            }
69
        });
70
    }
71
72
    /**
73
     * Get file extension for MIME type.
74
     *
75
     * @param  string  $mimeType
76
     * @param  string  $prefix
77
     * @return string|null
78
     */
79
    public static function fileExtensionForMimeType($mimeType, $prefix = '')
80
    {
81
        $extension = ExtensionGuesser::getInstance()->guess($mimeType);
82
83
        if (! is_null($extension)) {
84
            if ('jpeg' == $extension) {
85
                $extension = 'jpg';
86
            }
87
88
            return $prefix.$extension;
89
        }
90
    }
91
92
    /**
93
     * Convert an iOS platform to the device model name.
94
     *
95
     * @see https://www.theiphonewiki.com/wiki/Models
96
     * @see https://support.hockeyapp.net/kb/client-integration-ios-mac-os-x-tvos/ios-device-types
97
     *
98
     * @param  string  $platform
99
     * @return string
100
     */
101
    public static function iDeviceModel($platform)
102
    {
103
        static $iDeviceModels = null;
104
105
        if (is_null($iDeviceModels)) {
106
            $iDeviceModels = [
107
                'i386' => 'Simulator',
108
                'x86_64' => 'Simulator',
109
110
                'iPhone1,1' => 'iPhone',
111
                'iPhone1,2' => 'iPhone 3G',
112
                'iPhone2,1' => 'iPhone 3GS',
113
                'iPhone3,1' => 'iPhone 4',
114
                'iPhone3,2' => 'iPhone 4',
115
                'iPhone3,3' => 'iPhone 4',
116
                'iPhone4,1' => 'iPhone 4S',
117
                'iPhone5,1' => 'iPhone 5',
118
                'iPhone5,2' => 'iPhone 5',
119
                'iPhone5,3' => 'iPhone 5c',
120
                'iPhone5,4' => 'iPhone 5c',
121
                'iPhone6,1' => 'iPhone 5s',
122
                'iPhone6,2' => 'iPhone 5s',
123
                'iPhone7,1' => 'iPhone 6 Plus',
124
                'iPhone7,2' => 'iPhone 6',
125
                'iPhone8,1' => 'iPhone 6s',
126
                'iPhone8,2' => 'iPhone 6s Plus',
127
                'iPhone8,4' => 'iPhone SE',
128
                'iPhone9,1' => 'iPhone 7',
129
                'iPhone9,2' => 'iPhone 7 Plus',
130
                'iPhone9,3' => 'iPhone 7',
131
                'iPhone9,4' => 'iPhone 7 Plus',
132
133
                'iPod1,1' => 'iPod touch',
134
                'iPod2,1' => 'iPod touch 2G',
135
                'iPod3,1' => 'iPod touch 3G',
136
                'iPod4,1' => 'iPod touch 4G',
137
                'iPod5,1' => 'iPod touch 5G',
138
                'iPod7,1' => 'iPod touch 6G',
139
140
                'iPad1,1' => 'iPad',
141
                'iPad2,1' => 'iPad 2',
142
                'iPad2,2' => 'iPad 2',
143
                'iPad2,3' => 'iPad 2',
144
                'iPad2,4' => 'iPad 2',
145
                'iPad2,5' => 'iPad mini',
146
                'iPad2,6' => 'iPad mini',
147
                'iPad2,7' => 'iPad mini',
148
                'iPad3,1' => 'iPad 3',
149
                'iPad3,2' => 'iPad 3',
150
                'iPad3,3' => 'iPad 3',
151
                'iPad3,4' => 'iPad 4',
152
                'iPad3,5' => 'iPad 4',
153
                'iPad3,6' => 'iPad 4',
154
                'iPad4,1' => 'iPad Air',
155
                'iPad4,2' => 'iPad Air',
156
                'iPad4,3' => 'iPad Air',
157
                'iPad4,4' => 'iPad mini 2',
158
                'iPad4,5' => 'iPad mini 2',
159
                'iPad4,6' => 'iPad mini 2',
160
                'iPad4,7' => 'iPad mini 3',
161
                'iPad4,8' => 'iPad mini 3',
162
                'iPad4,9' => 'iPad mini 3',
163
                'iPad5,1' => 'iPad mini 4',
164
                'iPad5,2' => 'iPad mini 4',
165
                'iPad5,3' => 'iPad Air 2',
166
                'iPad5,4' => 'iPad Air 2',
167
                'iPad6,3' => 'iPad Pro',
168
                'iPad6,4' => 'iPad Pro',
169
                'iPad6,7' => 'iPad Pro',
170
                'iPad6,8' => 'iPad Pro',
171
172
                'AppleTV2,1' => 'Apple TV 2G',
173
                'AppleTV3,1' => 'Apple TV 3G',
174
                'AppleTV3,2' => 'Apple TV 3G',
175
                'AppleTV5,3' => 'Apple TV 4G',
176
177
                'Watch1,1' => 'Apple Watch',
178
                'Watch1,2' => 'Apple Watch',
179
                'Watch2,6' => 'Apple Watch Series 1',
180
                'Watch2,7' => 'Apple Watch Series 1',
181
                'Watch2,3' => 'Apple Watch Series 2',
182
                'Watch2,4' => 'Apple Watch Series 2',
183
            ];
184
        }
185
186
        return isset($iDeviceModels[$platform]) ? $iDeviceModels[$platform] : $platform;
187
    }
188
189
    /**
190
     * Get the mail homepage.
191
     *
192
     * @param  string  $address
193
     * @return string|null
194
     */
195
    public static function mailHomepage($address)
196
    {
197
        if (preg_match('#@([a-z0-9.-]+)#i', $address, $match)) {
198
            $list = [
199
                'qq.com' => 'https://mail.qq.com',
200
                'vip.qq.com' => 'https://mail.qq.com',
201
                '126.com' => 'http://www.126.com',
202
                'gmail.com' => 'https://mail.google.com',
203
                '139.com' => 'http://mail.10086.cn',
204
                'wo.cn' => 'http://mail.wo.com.cn',
205
                'sina.com' => 'http://mail.sina.com.cn',
206
                'sina.cn' => 'http://mail.sina.com.cn',
207
                'vip.sina.com' => 'http://mail.sina.com.cn',
208
            ];
209
210
            $domain = strtolower($match[1]);
211
212
            return isset($list[$domain]) ? $list[$domain] : 'http://mail.'.$domain;
213
        }
214
    }
215
216
    /**
217
     * Encrypt ASCII string via XOR.
218
     *
219
     * @param  string  $text
220
     * @param  string|null  $key
221
     * @return string
222
     */
223
    public static function sampleEncrypt($text, $key = null)
224
    {
225
        $text = (string) $text;
226
        if (is_null($key)) {
227
            $key = app('encrypter')->getKey();
228
        }
229
230
        // 生成随机字符串
231
        $random = str_random(strlen($text));
232
233
        // 按字符拼接:随机字符串 + 随机字符串异或原文
234
        $tmp = static::sampleEncryption($text, $random, function ($a, $b) {
235
            return $b.($a ^ $b);
236
        });
237
238
        // 异或 $tmp 和 $key
239
        $result = static::sampleEncryption($tmp, $key);
240
241
        return urlsafe_base64_encode($result);
242
    }
243
244
    /**
245
     * Decrypt string via XOR.
246
     *
247
     * @param  string  $text
248
     * @param  string|null  $key
249
     * @return string
250
     */
251
    public static function sampleDecrypt($text, $key = null)
252
    {
253
        if (is_null($key)) {
254
            $key = app('encrypter')->getKey();
255
        }
256
257
        $tmp = static::sampleEncryption(urlsafe_base64_decode($text), $key);
258
        $tmpLength = strlen($tmp);
259
        $result = '';
260
        for ($i = 0; $i < $tmpLength, ($i + 1) < $tmpLength; $i += 2) {
261
            $result .= $tmp[$i] ^ $tmp[$i + 1];
262
        }
263
264
        return $result;
265
    }
266
267
    /**
268
     * Do a sample XOR encryption.
269
     *
270
     * @param  string  $text
271
     * @param  string  $key
272
     * @param  \Closure|null  $callback `($a, $b, $index)`
273
     * @return string
274
     */
275
    protected static function sampleEncryption($text, $key, $callback = null)
276
    {
277
        // 对 $text 和 $key 的每个字符进行运算。
278
        // $callback 为 null 时默认进行异或运算。
279
        // $callback 参数: 第 i 位 $text, 第 i 位 $key, 下标 i
280
        // $callback 返回 false 时,结束字符循环.
281
282
        $text = (string) $text;
283
        $key = (string) $key;
284
        $keyLength = strlen($key);
285
        if (is_null($callback)) {
286
            $callback = function ($a, $b) {
287
                return $a ^ $b;
288
            };
289
        }
290
291
        $result = '';
292
        $textLength = strlen($text);
293
        for ($i = 0; $i < $textLength; $i++) {
294
            $tmp = $callback($text[$i], $key[$i % $keyLength], $i);
295
            if (false === $tmp) {
296
                break;
297
            }
298
            $result .= $tmp;
299
        }
300
301
        return $result;
302
    }
303
304
    /**
305
     * Convert an integer to a string.
306
     * It is useful to shorten a database ID to URL keyword, e.g. 54329 to 'xkE'.
307
     *
308
     * @param  int $number
309
     * @param  string|null  $characters
310
     * @return string
311
     */
312
    public static function int2string($number, string $characters = null)
313
    {
314
        $number = (int) $number;
315
        if ($number < 0) {
316
            return '';
317
        }
318
319
        if (is_null($characters)) {
320
            $characters = config('support.int2string');
321
        }
322
323
        $charactersLength = strlen($characters);
324
        $string = '';
325
326
        while ($number >= $charactersLength) {
327
            $mod = (int) bcmod($number, $charactersLength);
328
            $number = (int) bcdiv($number, $charactersLength);
329
            $string = $characters[$mod].$string;
330
        }
331
332
        return $characters[$number].$string;
333
    }
334
335
    /**
336
     * Convert an `int2string` generated string back to an integer.
337
     *
338
     * @param  string  $string
339
     * @param  string|null  $characters
340
     * @return int
341
     */
342
    public static function string2int($string, string $characters = null)
343
    {
344
        $string = strrev($string);
345
        $stringLength = strlen($string);
346
347
        if (is_null($characters)) {
348
            $characters = config('support.int2string');
349
        }
350
        $charactersLength = strlen($characters);
351
352
        $number = 0;
353
        for ($i = 0; $i < $stringLength; $i++) {
354
            $index = strpos($characters, $string[$i]);
355
            $number = (int) bcadd($number, bcmul($index, bcpow($charactersLength, $i)));
356
        }
357
358
        return $number;
359
    }
360
}
361