Completed
Push — master ( 4b257d...a8afb6 )
by Elf
04:10
created

Helper::int2string()   B

Complexity

Conditions 4
Paths 5

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

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