Passed
Pull Request — 8.0 (#2857)
by
unknown
02:13
created

Lang::get()   C

Complexity

Conditions 12
Paths 20

Size

Total Lines 45
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 156

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 23
c 1
b 0
f 0
nc 20
nop 3
dl 0
loc 45
ccs 0
cts 22
cp 0
crap 156
rs 6.9666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2023 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
    protected $app;
22
23
    /**
24
     * 配置参数
25
     * @var array
26
     */
27
    protected $config = [
28
        // 默认语言
29
        'default_lang'    => 'zh-cn',
30
        // 允许的语言列表
31
        'allow_lang_list' => [],
32
        // 是否使用Cookie记录
33
        'use_cookie'      => true,
34
        // 扩展语言包
35
        'extend_list'     => [],
36
        // 多语言cookie变量
37
        'cookie_var'      => 'think_lang',
38
        // 多语言header变量
39
        'header_var'      => 'think-lang',
40
        // 多语言自动侦测变量名
41
        'detect_var'      => 'lang',
42
        // Accept-Language转义为对应语言包名称
43
        'accept_language' => [
44
            'zh-hans-cn' => 'zh-cn',
45
        ],
46
        // 是否支持语言分组
47
        'allow_group'     => false,
48
    ];
49
50
    /**
51
     * 多语言信息
52
     * @var array
53
     */
54
    private $lang = [];
55
56
    /**
57
     * 当前语言
58
     * @var string
59
     */
60
    private $range = 'zh-cn';
61
62
    /**
63
     * 构造方法
64
     * @access public
65
     * @param array $config
66
     */
67 3
    public function __construct(App $app, array $config = [])
68
    {
69 3
        $this->config = array_merge($this->config, array_change_key_case($config));
70 3
        $this->range  = $this->config['default_lang'];
71 3
        $this->app    = $app;
72
    }
73
74 3
    public static function __make(App $app, Config $config)
75
    {
76 3
        return new static($app, $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

76
        return new static($app, /** @scrutinizer ignore-type */ $config->get('lang'));
Loading history...
77
    }
78
79
    /**
80
     * 获取当前语言配置
81
     * @access public
82
     * @return array
83
     */
84
    public function getConfig(): array
85
    {
86
        return $this->config;
87
    }
88
89
    /**
90
     * 设置当前语言
91
     * @access public
92
     * @param string $lang 语言
93
     * @return void
94
     */
95 3
    public function setLangSet(string $lang): void
96
    {
97 3
        $this->range = $lang;
98
    }
99
100
    /**
101
     * 获取当前语言
102
     * @access public
103
     * @return string
104
     */
105
    public function getLangSet(): string
106
    {
107
        return $this->range;
108
    }
109
110
    /**
111
     * 获取默认语言
112
     * @access public
113
     * @return string
114
     */
115 3
    public function defaultLangSet()
116
    {
117 3
        return $this->config['default_lang'];
118
    }
119
120
    /**
121
     * 切换语言
122
     * @access public
123
     * @param string $langset 语言
124
     * @return void
125
     */
126 3
    public function switchLangSet(string $langset)
127
    {
128 3
        if (empty($langset)) {
129
            return;
130
        }
131
132 3
        $this->setLangSet($langset);
133
134
        // 加载系统语言包
135 3
        $this->load([
136 3
            $this->app->getThinkPath() . 'lang' . DIRECTORY_SEPARATOR . $langset . '.php',
137 3
        ]);
138
139
        // 加载系统语言包
140 3
        $files = glob($this->app->getAppPath() . 'lang' . DIRECTORY_SEPARATOR . $langset . '.*');
141 3
        $this->load($files);
142
143
        // 加载扩展(自定义)语言包
144 3
        $list = $this->app->config->get('lang.extend_list', []);
145
146 3
        if (isset($list[$langset])) {
147
            $this->load($list[$langset]);
148
        }
149
    }
150
151
    /**
152
     * 加载语言定义(不区分大小写)
153
     * @access public
154
     * @param string|array $file  语言文件
155
     * @param string       $range 语言作用域
156
     * @return array
157
     */
158 3
    public function load($file, $range = ''): array
159
    {
160 3
        $range = $range ?: $this->range;
161 3
        if (!isset($this->lang[$range])) {
162 3
            $this->lang[$range] = [];
163
        }
164
165 3
        $lang = [];
166
167 3
        foreach ((array) $file as $name) {
168 3
            if (is_file($name)) {
169 3
                $result = $this->parse($name);
170 3
                $lang   = array_change_key_case($result) + $lang;
171
            }
172
        }
173
174 3
        if (!empty($lang)) {
175 3
            $this->lang[$range] = $lang + $this->lang[$range];
176
        }
177
178 3
        return $this->lang[$range];
179
    }
180
181
    /**
182
     * 解析语言文件
183
     * @access protected
184
     * @param string $file 语言文件名
185
     * @return array
186
     */
187 3
    protected function parse(string $file): array
188
    {
189 3
        $type   = pathinfo($file, PATHINFO_EXTENSION);
190 3
        $result = match ($type) {
191 3
            'php'       =>  include $file,
192 3
            'yml','yaml'=>  function_exists('yaml_parse_file') ? yaml_parse_file($file) : [],
193 3
            'json'      =>  json_decode(file_get_contents($file), true),
194 3
            default     =>  [],
195 3
        };
196
197 3
        return is_array($result) ? $result : [];
198
    }
199
200
    /**
201
     * 判断是否存在语言定义(不区分大小写)
202
     * @access public
203
     * @param string|null $name  语言变量
204
     * @param string      $range 语言作用域
205
     * @return bool
206
     */
207
    public function has(string $name, string $range = ''): bool
208
    {
209
        $range = $range ?: $this->range;
210
211
        if ($this->config['allow_group'] && substr_count($name, '.') === 2) {
212
            [$name1, $name2, $name3] = explode('.', $name, 3);
213
            return isset($this->lang[$range][strtolower($name1)][$name2][$name3]);
214
        } elseif ($this->config['allow_group'] && substr_count($name, '.') === 1) {
215
            [$name1, $name2] = explode('.', $name, 2);
216
            return isset($this->lang[$range][strtolower($name1)][$name2]);
217
        }
218
219
        return isset($this->lang[$range][strtolower($name)]);
220
    }
221
222
    /**
223
     * 获取语言定义(不区分大小写)
224
     * @access public
225
     * @param string|null $name  语言变量
226
     * @param array       $vars  变量替换
227
     * @param string      $range 语言作用域
228
     * @return mixed
229
     */
230
    public function get(string $name = null, array $vars = [], string $range = '')
231
    {
232
        $range = $range ?: $this->range;
233
234
        if (!isset($this->lang[$range])) {
235
            $this->switchLangSet($range);
236
        }
237
238
        // 空参数返回所有定义
239
        if (is_null($name)) {
240
            return $this->lang[$range] ?? [];
241
        }
242
243
        if ($this->config['allow_group'] && substr_count($name, '.') === 2) {
244
            [$name1, $name2, $name3] = explode('.', $name, 3);
245
            $value = $this->lang[$range][strtolower($name1)][$name2][$name3] ?? $this->lang[$range][strtolower($name1)][$name2] ?? $name;
246
        } elseif ($this->config['allow_group'] && substr_count($name, '.') === 1) {
247
            [$name1, $name2] = explode('.', $name, 2);
248
            $value = $this->lang[$range][strtolower($name1)][$name2] ?? $name;
249
        } else {
250
            $value = $this->lang[$range][strtolower($name)] ?? $name;
251
        }
252
253
        // 变量解析
254
        if (!empty($vars) && is_array($vars)) {
255
            /**
256
             * Notes:
257
             * 为了检测的方便,数字索引的判断仅仅是参数数组的第一个元素的key为数字0
258
             * 数字索引采用的是系统的 sprintf 函数替换,用法请参考 sprintf 函数
259
             */
260
            if (key($vars) === 0) {
261
                // 数字索引解析
262
                array_unshift($vars, $value);
263
                $value = call_user_func_array('sprintf', $vars);
264
            } else {
265
                // 关联索引解析
266
                $replace = array_keys($vars);
267
                foreach ($replace as &$v) {
268
                    $v = "{:{$v}}";
269
                }
270
                $value = str_replace($replace, $vars, $value);
271
            }
272
        }
273
274
        return $value;
275
    }
276
}
277