GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 8a4525...04b2e6 )
by t
05:00 queued 40s
created

I   F

Complexity

Total Complexity 75

Size/Duplication

Total Lines 390
Duplicated Lines 0 %

Test Coverage

Coverage 69.29%

Importance

Changes 23
Bugs 5 Features 0
Metric Value
eloc 144
c 23
b 5
f 0
dl 0
loc 390
ccs 97
cts 140
cp 0.6929
rs 2.4
wmc 75

14 Methods

Rating   Name   Duplication   Size   Complexity  
A isEmpty() 0 3 1
A def() 0 3 2
D get() 0 43 19
A displayErrors() 0 4 3
B set() 0 19 7
A phpini() 0 3 3
A call() 0 5 2
A isYii2() 0 3 1
A ini() 0 6 2
C setAlias() 0 39 13
A createObject() 0 17 5
C getAlias() 0 40 13
A isExt() 0 6 3
A hasFlag() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like I often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use I, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Class I
4
 *
5
 * @link https://www.icy2003.com/
6
 * @author icy2003 <[email protected]>
7
 * @copyright Copyright (c) 2017, icy2003
8
 */
9
namespace icy2003\php;
10
11
use Exception;
12
use icy2003\php\icomponents\file\LocalFile;
13
use icy2003\php\ihelpers\Strings;
14
use ReflectionClass;
15
16
/**
17
 * I 类
18
 */
19
class I
20
{
21
22
    /**
23
     * 获取值
24
     *
25
     * 支持类型:数组对象和 null、数字和字符串、布尔值、回调函数,依据数据类型有不同的含义(但是都很合理)
26
     *
27
     * @param mixed $mixed 混合类型
28
     *      - 当 $mixed 为**数组或对象**时,此方法用于按照层级获取值,用法如下:
29
     *          1. 对于一个多维数组 $array 来说,a.b.cd_ef 会拿 $array['a']['b']['cd_ef'] 的值
30
     *          2. 如果 $array['a'] 是对象,则先检查 getB 方法,然后检查 b 属性
31
     *          3. 如果 $array['a']['b'] 是对象,则检查 getCdEf 方法,然后检查 cd_ef 属性
32
     *      - 当 $mixed 为**布尔值**(即表达式)时,等价于三元操作符,例如 I::get(1 > 2, '真', '假')
33
     *      - 当 $mixed 为**字符串**时,等价于 Strings::sub,截取字符串
34
     *      - 当 $mixed 为 **null** 时,含义可被描述为:在使用 I::get($array, 'a.b', 1),$array 意外的是 null,返回 1 是理所当然的
35
     *      - 当 $mixed 为**回调函数**,$mixed 的执行结果将作为 I::get 的返回值
36
     * @param mixed $keyString 取决于 $mixed 的类型:
37
     *      - 当 $mixed 为**数组或对象**时,$keyString 表示:点(.)分割代表层级的字符串,下划线用于对象中转化成驼峰方法,支持数组和对象嵌套
38
     *      - 当 $mixed 为**布尔值**(即表达式)时,$keyString 表示:$mixed 为 true 时返回的值
39
     *      - 当 $mixed 为**字符串**时,$keyString 强制转为整型,表示:截取 $mixed 时,子串的起始位置
40
     *      - 当 $mixed 为 **null** 时,此参数无效
41
     *      - 当 $mixed 为**回调函数**,如果 $mixed 的返回值代表 true(如:1),则执行此回调
42
     * @param mixed $defaultValue 取决于 $mixed 的类型:
43
     *      - 当 $mixed 为**数组或对象**时,$defaultValue 表示:拿不到值时会直接返回该默认值
44
     *      - 当 $mixed 为**布尔值**(即表达式)时,$defaultValue 表示:$mixed 为 false 时返回的值
45
     *      - 当 $mixed 为**字符串**时,$defaultValue 表示:截取 $mixed 时,子串的长度,null 时表示长度为 1
46
     *      - 当 $mixed 为 **null** 时,返回 $defaultValue
47
     *      - 当 $mixed 为**回调函数**,如果 $mixed 的返回值代表 false(如:0),则执行此回调
48
     *
49
     * @return mixed
50
     */
51 65
    public static function get($mixed, $keyString, $defaultValue = null)
52
    {
53 65
        if (is_bool($mixed)) { // 布尔类型
54 1
            return true === $mixed ? $keyString : $defaultValue;
55 65
        } elseif (is_callable($mixed)) { // 回调
56 1
            $result = self::call($mixed);
57 1
            if ($result) {
58 1
                self::call($keyString);
59
            } else {
60 1
                self::call($defaultValue);
61
            }
62 1
            return $result;
63 65
        } elseif (is_array($mixed) || is_object($mixed)) { // 数组和对象
64 65
            $keyArray = explode('.', $keyString);
65 65
            foreach ($keyArray as $key) {
66 65
                if (is_array($mixed)) {
67 65
                    if (array_key_exists($key, $mixed) && null !== $mixed[$key]) {
68 64
                        $mixed = $mixed[$key];
69
                    } else {
70 65
                        return $defaultValue;
71
                    }
72 2
                } elseif (is_object($mixed)) {
73 2
                    $method = 'get' . ucfirst(Strings::toCamel($key));
74 2
                    if (method_exists($mixed, $method)) {
75 1
                        $mixed = $mixed->$method();
76 2
                    } elseif (property_exists($mixed, $key) && null !== $mixed->$key) {
77 2
                        $mixed = $mixed->$key;
78
                    } else {
79 2
                        return $defaultValue;
80
                    }
81
                } else {
82 1
                    return self::get($mixed, $key, $defaultValue);
83
                }
84
            }
85 64
            return $mixed;
86 1
        } elseif (is_string($mixed) || is_numeric($mixed)) { // 字符串或数字
87 1
            $pos = (int) $keyString;
88 1
            $length = null === $defaultValue ? 1 : (int) $defaultValue;
89 1
            return Strings::sub($mixed, $pos, $length);
90 1
        } elseif (null === $mixed) { // null
91 1
            return $defaultValue;
92
        } else { // 资源
93 1
            return $defaultValue;
94
        }
95
    }
96
97
    /**
98
     * 设置值
99
     *
100
     * @param array|object $mixed 对象或数组
101
     * @param string $key 键
102
     * @param mixed $value 值
103
     * @param boolean $overWrite 如果对应的值存在,是否用给定的值覆盖,默认 true,即:是
104
     *
105
     * @return mixed
106
     */
107 1
    public static function set(&$mixed, $key, $value, $overWrite = true)
108
    {
109 1
        $get = self::get($mixed, $key);
110 1
        if (null === $get || true === $overWrite) {
111 1
            if (is_array($mixed)) {
112 1
                $mixed[$key] = $value;
113 1
            } elseif (is_object($mixed)) {
114 1
                $method = 'set' . ucfirst(Strings::toCamel($key));
115 1
                if (method_exists($mixed, $method)) {
116 1
                    $mixed->$method($value);
117 1
                } elseif (property_exists($mixed, $key)) {
118 1
                    $mixed->$key = $value;
119
                } else {
120 1
                    throw new Exception('无法设置值');
121
                }
122
            }
123 1
            return $value;
124
        }
125 1
        return $get;
126
    }
127
128
    /**
129
     * 触发回调
130
     *
131
     * @param callback $callback 回调函数
132
     * @param array $params 回调参数
133
     * @return mixed
134
     */
135 11
    public static function call($callback, $params = [])
136
    {
137 11
        $result = false;
138 11
        is_callable($callback) && $result = call_user_func_array($callback, $params);
139 11
        return $result;
140
    }
141
142
    /**
143
     * 定义一个常量
144
     *
145
     * @param string $constant 常量名
146
     * @param mixed $value 值
147
     *
148
     * @return void
149
     */
150 1
    public static function def($constant, $value)
151
    {
152 1
        defined($constant) || define($constant, $value);
153 1
    }
154
155
    /**
156
     * 让 empty 支持函数调用
157
     *
158
     * 注意:此函数并不比 empty 好,只是为了让 empty 支持函数调用
159
     *
160
     * 例如:empty($array[0]) 就不能用此函数代替,另外,empty 是语法结构,性能明显比函数高
161
     *
162
     * @see http://php.net/manual/zh/function.empty.php
163
     *
164
     * @param mixed $data
165
     * @return boolean
166
     */
167 5
    public static function isEmpty($data)
168
    {
169 5
        return empty($data);
170
    }
171
172
    /**
173
     * 获取 php.ini 配置值
174
     *
175
     * @param string $key 配置名
176
     * @param mixed $default 默认值
177
     *
178
     * @return mixed
179
     */
180 2
    public static function phpini($key, $default = null)
181
    {
182 2
        return false !== ($ini = ini_get($key)) ? $ini : (false !== ($ini = get_cfg_var($key)) ? $ini : $default);
183
    }
184
185
    /**
186
     * 显示 PHP 错误
187
     *
188
     * @param boolean $show 是否显示,默认是
189
     *
190
     * @return void
191
     */
192 1
    public static function displayErrors($show = true)
193
    {
194 1
        ini_set("display_errors", true === $show ? 'On' : 'Off');
195 1
        true === $show && error_reporting(E_ALL | E_STRICT);
196 1
    }
197
198
    /**
199
     * 别名列表
200
     *
201
     * @var array
202
     */
203
    public static $aliases = [
204
        '@vendor' => __DIR__ . '/../../../../vendor',
205
        '@icy2003/php_tests' => __DIR__ . '/../tests',
206
        '@icy2003/php_runtime' => __DIR__ . '/../runtime',
207
        '@icy2003/php' => __DIR__,
208
    ];
209
210
    /**
211
     * 用别名获取真实路径
212
     *
213
     * @param string $alias 别名
214
     *
215
     * @return string|boolean
216
     */
217 50
    public static function getAlias($alias)
218
    {
219 50
        $alias = Strings::replace($alias, ["\\" => '/']);
220 50
        if (strncmp($alias, '@', 1)) {
221 50
            return $alias;
222
        }
223 50
        $localFile = new LocalFile();
224 50
        foreach (static::$aliases as $k => $v) {
225 50
            static::$aliases[$k] = $localFile->getRealpath($v);
226
        }
227
228 50
        $pos = 0;
229 50
        while (true) {
230 50
            $pos = strpos($alias, '/', $pos);
231 50
            $root = $pos === false ? $alias : substr($alias, 0, $pos);
232 50
            if (isset(static::$aliases[$root])) {
233 50
                if (is_string(static::$aliases[$root])) {
234 50
                    return $pos === false ? static::$aliases[$root] : static::$aliases[$root] . substr($alias, $pos);
235
                } elseif (is_array(static::$aliases[$root])) {
236
                    foreach (static::$aliases[$root] as $name => $path) {
237
                        if (strpos($alias . '/', $name . '/') === 0) {
238
                            return $path . substr($alias, strlen($name));
239
                        }
240
                    }
241
                } else {
242
                    return false;
243
                }
244
            }
245 50
            if ($root == $alias) {
246
                break;
247
            }
248 50
            $pos++;
249
        }
250
        // 对 Yii2 的支持
251
        if ($result = self::call(['\Yii', 'getAlias'], [$alias])) {
252
            self::setAlias($alias, $result);
253
            return $result;
254
        }
255
256
        return false;
257
    }
258
259
    /**
260
     * 是否是 Yii2 项目
261
     *
262
     * @return boolean
263
     */
264
    public static function isYii2()
265
    {
266
        return method_exists('\Yii', 'getVersion');
267
    }
268
269
    /**
270
     * 设置别名
271
     *
272
     * @param string $alias 别名
273
     * @param string|null $path 路径
274
     *
275
     * @return void
276
     */
277 1
    public static function setAlias($alias, $path)
278
    {
279
        // 对 Yii2 的支持
280
        try {
281 1
            self::call(['\Yii', 'getAlias'], [$alias]);
282
        } catch (Exception $e) {
283
            self::call(['\Yii', 'setAlias'], [$alias, $path]);
284
        }
285 1
        if (strncmp($alias, '@', 1)) {
286
            $alias = '@' . $alias;
287
        }
288 1
        $pos = strpos($alias, '/');
289 1
        $root = $pos === false ? $alias : substr($alias, 0, $pos);
290 1
        if ($path !== null) {
291 1
            $path = strncmp($path, '@', 1) ? rtrim($path, '\\/') : static::getAlias($path);
292 1
            if (!isset(static::$aliases[$root])) {
293 1
                if ($pos === false) {
294 1
                    static::$aliases[$root] = $path;
295
                } else {
296 1
                    static::$aliases[$root] = [$alias => $path];
297
                }
298
            } elseif (is_string(static::$aliases[$root])) {
299
                if ($pos === false) {
300
                    static::$aliases[$root] = $path;
301
                } else {
302
                    static::$aliases[$root] = [
303
                        $alias => $path,
304
                        $root => static::$aliases[$root],
305
                    ];
306
                }
307
            } else {
308
                static::$aliases[$root][$alias] = $path;
309 1
                krsort(static::$aliases[$root]);
310
            }
311
        } elseif (isset(static::$aliases[$root])) {
312
            if (is_array(static::$aliases[$root])) {
313
                unset(static::$aliases[$root][$alias]);
314
            } elseif ($pos === false) {
315
                unset(static::$aliases[$root]);
316
            }
317
        }
318 1
    }
319
320
    /**
321
     * 判断给定选项值里是否设置某选项
322
     *
323
     * @param integer $flags 选项值
324
     * @param integer $flag 待判断的选项值
325
     *
326
     * @return boolean
327
     */
328 8
    public static function hasFlag($flags, $flag)
329
    {
330 8
        return $flags === ($flag | $flags);
331
    }
332
333
    /**
334
     * 创建一个对象
335
     *
336
     * @param array $params
337
     * - class:表示类名,可使用别名
338
     * - 其他:该类的属性,初始化这些属性
339
     * @param array $config
340
     * - 构造函数传参
341
     *
342
     * @return object
343
     */
344
    public static function createObject($params, $config = [])
345
    {
346
        if (is_array($params) && isset($params['class'])) {
347
            try {
348
                $class = $params['class'];
349
                unset($params['class']);
350
                $reflection = new ReflectionClass(self::getAlias($class));
351
                $object = $reflection->newInstanceArgs($config);
352
                foreach ($params as $name => $value) {
353
                    self::set($object, $name, $value);
354
                }
355
                return $object;
356
            } catch (Exception $e) {
357
                throw new Exception('初始化 ' . $class . ' 失败', $e->getCode(), $e);
358
            }
359
        }
360
        throw new Exception('必须带 class 以指定一个类');
361
    }
362
363
    /**
364
     * 静态配置
365
     *
366
     * @var array
367
     */
368
    public static $ini = [
369
        'USE_CUSTOM' => false,
370
        'EXT_LOADED' => true,
371
    ];
372
373
    /**
374
     * 读取或设置一个全局配置
375
     *
376
     * - 该配置是利用静态类进行存储的
377
     * - 如果给定 $value,则为设置,不给则为获取
378
     * - 可选默认配置有:
379
     *      1. USE_CUSTOM:默认 false,即尝试使用 php 原生函数的实现,如果此参数为 true,则使用 icy2003/php 的实现
380
     *      2. EXT_LOADED:默认 true,即尝试检测是否有扩展,如果为 false,直接认为没有该扩展
381
     *
382
     * @param string $key
383
     * @param mixed $value
384
     *
385
     * @return void|mixed
386
     */
387 3
    public static function ini($key, $value = null)
388
    {
389 3
        if (null !== $value) {
390 3
            self::$ini[$key] = $value;
391
        } else {
392 3
            return self::get(self::$ini, $key);
393
        }
394 3
    }
395
396
    /**
397
     * 是否有加载 PHP 扩展
398
     *
399
     * @param string $extName
400
     *
401
     * @return boolean
402
     */
403
    public static function isExt($extName)
404
    {
405
        if (false === extension_loaded($extName) || false === self::ini('EXT_LOADED')) {
406
            return false;
407
        }
408
        return true;
409
    }
410
}
411