Completed
Push — 6.0 ( 4e9123...ab2135 )
by liu
02:14
created

Lang   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 272
Duplicated Lines 0 %

Test Coverage

Coverage 31.03%

Importance

Changes 6
Bugs 0 Features 0
Metric Value
eloc 90
c 6
b 0
f 0
dl 0
loc 272
ccs 27
cts 87
cp 0.3103
rs 8.8
wmc 45

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __make() 0 3 1
A setLangSet() 0 3 1
A defaultLangSet() 0 3 1
A load() 0 21 6
A getLangSet() 0 3 1
A __construct() 0 4 1
B detect() 0 31 9
A saveToCookie() 0 4 2
B parse() 0 29 10
A has() 0 10 4
B get() 0 39 9

How to fix   Complexity   

Complex Class

Complex classes like Lang 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 Lang, and based on these observations, apply Extract Interface, too.

1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: liu21st <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think;
14
15
/**
16
 * 多语言管理类
17
 * @package think
18
 */
19
class Lang
20
{
21
    /**
22
     * 配置参数
23
     * @var array
24
     */
25
    protected $config = [
26
        // 默认语言
27
        'default_lang'    => 'zh-cn',
28
        // 允许的语言列表
29
        'allow_lang_list' => [],
30
        // 是否使用Cookie记录
31
        'use_cookie'      => true,
32
        // 扩展语言包
33
        'extend_list'     => [],
34
        // 多语言cookie变量
35
        'cookie_var'      => 'think_lang',
36
        // 多语言header变量
37
        'header_var'      => 'think-lang',
38
        // 多语言自动侦测变量名
39
        'detect_var'      => 'lang',
40
        // Accept-Language转义为对应语言包名称
41
        'accept_language' => [
42
            'zh-hans-cn' => 'zh-cn',
43
        ],
44
        // 是否支持语言分组
45
        'allow_group'     => false,
46
    ];
47
48
    /**
49
     * 多语言信息
50
     * @var array
51
     */
52
    private $lang = [];
53
54
    /**
55
     * 当前语言
56
     * @var string
57
     */
58
    private $range = 'zh-cn';
59
60
    /**
61
     * 构造方法
62
     * @access public
63
     * @param array $config
64
     */
65 3
    public function __construct(array $config = [])
66
    {
67 3
        $this->config = array_merge($this->config, array_change_key_case($config));
68 3
        $this->range  = $this->config['default_lang'];
69 3
    }
70
71 3
    public static function __make(Config $config)
72
    {
73 3
        return new static($config->get('lang'));
0 ignored issues
show
Bug introduced by
It seems like $config->get('lang') can also be of type null; however, parameter $config of think\Lang::__construct() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

73
        return new static(/** @scrutinizer ignore-type */ $config->get('lang'));
Loading history...
74
    }
75
76
    /**
77
     * 设置当前语言
78
     * @access public
79
     * @param string $lang 语言
80
     * @return void
81
     */
82
    public function setLangSet(string $lang): void
83
    {
84
        $this->range = $lang;
85
    }
86
87
    /**
88
     * 获取当前语言
89
     * @access public
90
     * @return string
91
     */
92
    public function getLangSet(): string
93
    {
94
        return $this->range;
95
    }
96
97
    /**
98
     * 获取默认语言
99
     * @access public
100
     * @return string
101
     */
102 3
    public function defaultLangSet()
103
    {
104 3
        return $this->config['default_lang'];
105
    }
106
107
    /**
108
     * 加载语言定义(不区分大小写)
109
     * @access public
110
     * @param string|array $file  语言文件
111
     * @param string       $range 语言作用域
112
     * @return array
113
     */
114 3
    public function load($file, $range = ''): array
115
    {
116 3
        $range = $range ?: $this->range;
117 3
        if (!isset($this->lang[$range])) {
118 3
            $this->lang[$range] = [];
119
        }
120
121 3
        $lang = [];
122
123 3
        foreach ((array) $file as $name) {
124 3
            if (is_file($name)) {
125 3
                $result = $this->parse($name);
126 3
                $lang   = array_change_key_case($result) + $lang;
127
            }
128
        }
129
130 3
        if (!empty($lang)) {
131 3
            $this->lang[$range] = $lang + $this->lang[$range];
132
        }
133
134 3
        return $this->lang[$range];
135
    }
136
137
    /**
138
     * 解析语言文件
139
     * @access protected
140
     * @param string $file 语言文件名
141
     * @return array
142
     */
143 3
    protected function parse(string $file): array
144
    {
145 3
        $type = pathinfo($file, PATHINFO_EXTENSION);
146
147 2
        switch ($type) {
148 3
            case 'php':
149 3
                $result = include $file;
150 3
                break;
151
            case 'yml':
152
            case 'yaml':
153
                if (function_exists('yaml_parse_file')) {
154
                    $result = yaml_parse_file($file);
155
                }
156
                break;
157
            case 'json':
158
                $data = file_get_contents($file);
159
160
                if($data !== false) {
161
                    $data = json_decode($data, true);
162
163
                    if(json_last_error() === JSON_ERROR_NONE) {
164
                        $result = $data;
165
                    }
166
                }
167
168
                break;
169
        }
170
171 3
        return isset($result) && is_array($result) ? $result : [];
172
    }
173
174
    /**
175
     * 判断是否存在语言定义(不区分大小写)
176
     * @access public
177
     * @param string|null $name  语言变量
178
     * @param string      $range 语言作用域
179
     * @return bool
180
     */
181
    public function has(string $name, string $range = ''): bool
182
    {
183
        $range = $range ?: $this->range;
184
185
        if ($this->config['allow_group'] && strpos($name, '.')) {
186
            [$name1, $name2] = explode('.', $name, 2);
187
            return isset($this->lang[$range][strtolower($name1)][$name2]);
188
        }
189
190
        return isset($this->lang[$range][strtolower($name)]);
191
    }
192
193
    /**
194
     * 获取语言定义(不区分大小写)
195
     * @access public
196
     * @param string|null $name  语言变量
197
     * @param array       $vars  变量替换
198
     * @param string      $range 语言作用域
199
     * @return mixed
200
     */
201
    public function get(string $name = null, array $vars = [], string $range = '')
202
    {
203
        $range = $range ?: $this->range;
204
205
        // 空参数返回所有定义
206
        if (is_null($name)) {
207
            return $this->lang[$range] ?? [];
208
        }
209
210
        if ($this->config['allow_group'] && strpos($name, '.')) {
211
            [$name1, $name2] = explode('.', $name, 2);
212
213
            $value = $this->lang[$range][strtolower($name1)][$name2] ?? $name;
214
        } else {
215
            $value = $this->lang[$range][strtolower($name)] ?? $name;
216
        }
217
218
        // 变量解析
219
        if (!empty($vars) && is_array($vars)) {
220
            /**
221
             * Notes:
222
             * 为了检测的方便,数字索引的判断仅仅是参数数组的第一个元素的key为数字0
223
             * 数字索引采用的是系统的 sprintf 函数替换,用法请参考 sprintf 函数
224
             */
225
            if (key($vars) === 0) {
226
                // 数字索引解析
227
                array_unshift($vars, $value);
228
                $value = call_user_func_array('sprintf', $vars);
229
            } else {
230
                // 关联索引解析
231
                $replace = array_keys($vars);
232
                foreach ($replace as &$v) {
233
                    $v = "{:{$v}}";
234
                }
235
                $value = str_replace($replace, $vars, $value);
236
            }
237
        }
238
239
        return $value;
240
    }
241
242
    /**
243
     * 自动侦测设置获取语言选择
244
     * @access public
245
     * @param Request $request
246
     * @return string
247
     */
248
    public function detect(Request $request): string
249
    {
250
        // 自动侦测设置获取语言选择
251
        $langSet = '';
252
253
        if ($request->get($this->config['detect_var'])) {
254
            // url中设置了语言变量
255
            $langSet = strtolower($request->get($this->config['detect_var']));
256
        } elseif ($request->header($this->config['header_var'])) {
257
            // Header中设置了语言变量
258
            $langSet = strtolower($request->header($this->config['header_var']));
0 ignored issues
show
Bug introduced by
It seems like $request->header($this->config['header_var']) can also be of type array; however, parameter $str of strtolower() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

258
            $langSet = strtolower(/** @scrutinizer ignore-type */ $request->header($this->config['header_var']));
Loading history...
259
        } elseif ($request->cookie($this->config['cookie_var'])) {
260
            // Cookie中设置了语言变量
261
            $langSet = strtolower($request->cookie($this->config['cookie_var']));
262
        } elseif ($request->server('HTTP_ACCEPT_LANGUAGE')) {
263
            // 自动侦测浏览器语言
264
            $match = preg_match('/^([a-z\d\-]+)/i', $request->server('HTTP_ACCEPT_LANGUAGE'), $matches);
265
            if ($match) {
266
                $langSet = strtolower($matches[1]);
267
                if (isset($this->config['accept_language'][$langSet])) {
268
                    $langSet = $this->config['accept_language'][$langSet];
269
                }
270
            }
271
        }
272
273
        if (empty($this->config['allow_lang_list']) || in_array($langSet, $this->config['allow_lang_list'])) {
274
            // 合法的语言
275
            $this->range = $langSet;
276
        }
277
278
        return $this->range;
279
    }
280
281
    /**
282
     * 保存当前语言到Cookie
283
     * @access public
284
     * @param Cookie $cookie Cookie对象
285
     * @return void
286
     */
287
    public function saveToCookie(Cookie $cookie)
288
    {
289
        if ($this->config['use_cookie']) {
290
            $cookie->set($this->config['cookie_var'], $this->range);
291
        }
292
    }
293
294
}
295