Utility   F
last analyzed

Complexity

Total Complexity 65

Size/Duplication

Total Lines 355
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 1
Metric Value
eloc 158
c 5
b 0
f 1
dl 0
loc 355
rs 3.2
wmc 65

11 Methods

Rating   Name   Duplication   Size   Complexity  
B convertItem() 0 18 8
A convertEncoding() 0 11 3
A loadConfig() 0 7 1
B langDetect() 0 24 8
A createConfig() 0 6 1
B getPreferredLanguage() 0 33 7
B showSelectedLanguage() 0 52 11
B cleanMultiLang() 0 62 11
B detectLang() 0 41 11
A encodeCharSet() 0 14 2
A escapeBracketMultiLang() 0 10 2

How to fix   Complexity   

Complex Class

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

1
<?php
2
3
namespace XoopsModules\Xlanguage;
4
5
use XoopsModules\Xlanguage\{Common
6
};
7
use Xmf\Request;
8
9
/** @var Helper $helper */
10
/** @var LanguageHandler $languageHandler */
11
12
/**
13
 * Class Utility
14
 */
15
class Utility extends Common\SysUtility
16
{
17
    //--------------- Custom module methods -----------------------------
18
    /**
19
     * @param $value
20
     * @param $out_charset
21
     * @param $in_charset
22
     * @return array|string
23
     */
24
    public static function convertEncoding($value, $out_charset, $in_charset)
25
    {
26
        if (\is_array($value)) {
27
            foreach ($value as $key => $val) {
28
                $value[$key] = static::convertEncoding($val, $out_charset, $in_charset);
29
            }
30
        } else {
31
            $value = static::convertItem($value, $out_charset, $in_charset);
32
        }
33
34
        return $value;
35
    }
36
37
    /**
38
     * @param $value
39
     * @param $out_charset
40
     * @param $in_charset
41
     * @return string
42
     */
43
    public static function convertItem($value, $out_charset, $in_charset)
44
    {
45
        if (mb_strtolower($in_charset) == mb_strtolower($out_charset)) {
46
            return $value;
47
        }
48
49
        $xconvHandler = @\xoops_getModuleHandler('xconv', 'xconv', true);
50
        if (\is_object($xconvHandler) && $convertedValue = @$xconvHandler->convert_encoding($value, $out_charset, $in_charset)) {
0 ignored issues
show
Bug introduced by
The method convert_encoding() does not exist on XoopsObjectHandler. It seems like you code against a sub-type of XoopsObjectHandler such as XoopsPersistableObjectHandler. ( Ignorable by Annotation )

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

50
        if (\is_object($xconvHandler) && $convertedValue = @$xconvHandler->/** @scrutinizer ignore-call */ convert_encoding($value, $out_charset, $in_charset)) {
Loading history...
51
            return $convertedValue;
52
        }
53
        if (XOOPS_USE_MULTIBYTES && \function_exists('mb_convert_encoding')) {
54
            $convertedValue = @mb_convert_encoding($value, $out_charset, $in_charset);
55
        } elseif (\function_exists('iconv')) {
56
            $convertedValue = @\iconv($in_charset, $out_charset, $value);
57
        }
58
        $value = empty($convertedValue) ? $value : $convertedValue;
59
60
        return $value;
61
    }
62
63
    /**
64
     * @return mixed
65
     */
66
    public static function createConfig()
67
    {
68
        $helper          = Helper::getInstance();
69
        $languageHandler = $helper->getHandler('Language');
70
71
        return $languageHandler->createConfig();
72
    }
73
74
    /**
75
     * @return mixed
76
     */
77
    public static function loadConfig()
78
    {
79
        $helper          = Helper::getInstance();
80
        $languageHandler = $helper->getHandler('Language');
81
        $config          = $languageHandler->loadFileConfig();
82
83
        return $config;
84
    }
85
86
    /**
87
     * Analyzes some PHP environment variables to find the most probable language
88
     * that should be used
89
     *
90
     * @param string $str
91
     * @param string $envType
92
     * @return int|string
93
     * @internal param $string $ string to analyze
94
     * @internal param $integer $ type of the PHP environment variable which value is $str
95
     *
96
     * @global        array    the list of available translations
97
     * @global        string   the retained translation keyword
98
     * @access   private
99
     */
100
    public static function langDetect($str = '', $envType = '')
101
    {
102
        require dirname(__DIR__) . '/include/vars.php';
103
        $lang = '';
104
105
        if (!empty($available_languages)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $available_languages seems to never exist and therefore empty should always be true.
Loading history...
106
            foreach ($available_languages as $key => $value) {
107
                // $envType =  1 for the 'HTTP_ACCEPT_LANGUAGE' environment variable,
108
                //             2 for the 'HTTP_USER_AGENT' one
109
                $expr = $value[0];
110
                if (false === mb_strpos($expr, '[-_]')) {
111
                    $expr = \str_replace('|', '([-_][[:alpha:]]{2,3})?|', $expr);
112
                }
113
                //        if (($envType == 1 && eregi('^(' . $expr . ')(;q=[0-9]\\.[0-9])?$', $str))
114
                //            || ($envType == 2 && eregi('(\(|\[|;[[:space:]])(' . $expr . ')(;|\]|\))', $str))) {
115
                if ((1 == $envType && \preg_match('#^(' . $expr . ')(;q=[0-9]\\.[0-9])?$#i', $str)) || (2 == $envType && \preg_match('#(\(|\[|;[[:space:]])(' . $expr . ')(;|\]|\))#i', $str))) {
116
                    $lang = $key;
117
                    //if($lang != 'en')
118
                    break;
119
                }
120
            }
121
        }
122
123
        return $lang;
124
    }
125
126
    /**
127
     * @return string|bool
128
     */
129
    public static function detectLang()
130
    {
131
        global  $_SERVER;
132
        //      if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
133
        if (Request::hasVar('HTTP_ACCEPT_LANGUAGE', 'SERVER')) {
134
            $HTTP_ACCEPT_LANGUAGE = Request::getString('HTTP_ACCEPT_LANGUAGE', '', 'SERVER');
135
        }
136
137
        //if (!empty($_SERVER['HTTP_USER_AGENT'])) {
138
        if (Request::hasVar('HTTP_USER_AGENT', 'SERVER')) {
139
            $HTTP_USER_AGENT = Request::getString('HTTP_USER_AGENT', '', 'SERVER');
140
        }
141
142
        $lang       = '';
143
        $xoops_lang = '';
144
        // 1. try to findout user's language by checking its HTTP_ACCEPT_LANGUAGE variable
145
146
            if (empty($lang) && !empty($HTTP_ACCEPT_LANGUAGE)) {
147
                $accepted    = explode(',', $HTTP_ACCEPT_LANGUAGE);
148
                reset($accepted);
149
                foreach ($accepted as $iValue) {
150
                    $lang = static::langDetect($iValue, 1);
151
                    if (strncasecmp($lang, 'en', 2)) {
152
                        break;
153
                    }
154
                }
155
            }
156
157
        //This returns the most preferred language "q=1"
158
        $lang = static::getPreferredLanguage();
159
160
        // 2. if not found in HTTP_ACCEPT_LANGUAGE, try to find user's language by checking its HTTP_USER_AGENT variable
161
        if (empty($lang) && !empty($HTTP_USER_AGENT)) {
162
            $lang = static::langDetect($HTTP_USER_AGENT, 2);
163
        }
164
        // 3. If we catch a valid language, configure it
165
          if (!empty($lang)) {
166
            $xoops_lang = isset($available_languages[$lang][1])?:'';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $available_languages seems to never exist and therefore isset should always be false.
Loading history...
167
        }
168
169
        return $xoops_lang;
170
    }
171
172
    /**
173
     * @param $output
174
     * @return array|string|null
175
     */
176
    public static function encodeCharSet($output)
177
    {
178
        global $xlanguage;
179
        $output = static::cleanMultiLang($output);
180
        // escape XML doc
181
        if (\preg_match("/^\<\?[\s]?xml[\s]+version=([\"'])[^\>]+\\1[\s]+encoding=([\"'])[^\>]+\\2[\s]?\?\>/i", $output)) {
0 ignored issues
show
Bug introduced by
It seems like $output can also be of type array and null and string[]; however, parameter $subject of preg_match() 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

181
        if (\preg_match("/^\<\?[\s]?xml[\s]+version=([\"'])[^\>]+\\1[\s]+encoding=([\"'])[^\>]+\\2[\s]?\?\>/i", /** @scrutinizer ignore-type */ $output)) {
Loading history...
182
            return $output;
183
        }
184
        $in_charset  = $xlanguage['charset_base'];
185
        $out_charset = $xlanguage['charset'];
186
187
        $output = static::convertEncoding($output, $out_charset, $in_charset);
188
189
        return $output;
190
    }
191
192
    /**
193
     * @param string $text
194
     * @return array|string|string[]|null
195
     */
196
    public static function cleanMultiLang($text)
197
    {
198
        global $xoopsConfig;
199
        global $xlanguage_langs;
200
        $patterns = [];
201
        if (!isset($xlanguage_langs)) {
202
            $xlanguage_langs = [];
203
            $helper          = Helper::getInstance();
204
            $languageHandler = $helper->getHandler('Language');
205
            $langs           = $languageHandler->getAll(true);
206
            //        $langs = $GLOBALS['xlanguageHandler']->getAll(true); //mb
207
            if (false !== $langs) {
208
                foreach (\array_keys($langs) as $_lang) {
209
                    $xlanguage_langs[$_lang] = $langs[$_lang]->getVar('lang_code');
210
                }
211
            }
212
            unset($langs);
213
        }
214
        if (empty($xlanguage_langs) || 0 == \count($xlanguage_langs)) {
215
            return $text;
216
        }
217
218
        // escape brackets inside of <code>...</code>
219
        $patterns[] = '/(\<code>.*\<\/code>)/isU';
220
221
        // escape brackets inside of <input type="..." value="...">
222
        $patterns[] = '/(\<input\b(?![^\>]*\btype=([\'"]?)(submit|image|reset|button))[^\>]*\>)/isU';
223
224
        // escape brackets inside of <textarea></textarea>
225
        $patterns[] = '/(\<textarea\b[^>]*>[^\<]*\<\/textarea>)/isU';
226
227
        $text = \preg_replace_callback($patterns, 'static::escapeBracketMultiLang', $text);
228
229
        // create the pattern between language tags
230
        $pqhtmltags  = \explode(',', preg_quote(\XLANGUAGE_TAGS_RESERVED, '/'));
0 ignored issues
show
Unused Code introduced by
The assignment to $pqhtmltags is dead and can be removed.
Loading history...
231
        $mid_pattern = '(?:(?!(' . \str_replace(',', '|', preg_quote(\XLANGUAGE_TAGS_RESERVED, '/')) . ')).)*';
232
233
        $patterns = [];
234
        $replaces = [];
235
236
        if (isset($xlanguage_langs[$xoopsConfig['language']])) {
237
            $lang       = $xlanguage_langs[$xoopsConfig['language']];
238
            $patterns[] = '/(\[([^\]]*\|)?' . preg_quote($lang, '~') . '(\|[^\]]*)?\])(' . $mid_pattern . ')(\[\/([^\]]*\|)?' . preg_quote($lang, '~') . '(\|[^\]]*)?\])/isU';
239
            $replaces[] = '$4';
240
        }
241
242
        foreach (\array_keys($xlanguage_langs) as $_lang) {
243
            if ($_lang == @$xoopsConfig['language']) {
244
                continue;
245
            }
246
            $name       = $xlanguage_langs[$_lang];
247
            $patterns[] = '/(\[([^\]]*\|)?' . preg_quote($name, '~') . '(\|[^\]]*)?\])(' . $mid_pattern . ')(\[\/([^\]]*\|)?' . preg_quote($name, '~') . '(\|[^\]]*)?(\]\<br[\s]?[\/]?\>|\]))/isU';
248
            $replaces[] = '';
249
        }
250
        if (!empty($xoopsConfig['language'])) {
251
            $text = \preg_replace('/\[[\/]?[\|]?' . preg_quote($xoopsConfig['language'], '~') . '[\|]?\](\<br \/\>)?/i', '', $text);
252
        }
253
        if (\count($replaces) > 0) {
254
            $text = \preg_replace($patterns, $replaces, $text);
255
        }
256
257
        return $text;
258
    }
259
260
    /**
261
     * @param $matches
262
     * @return mixed
263
     */
264
    public static function escapeBracketMultiLang($matches)
265
    {
266
        global $xlanguage_langs;
267
        $ret = $matches[1];
268
        if (!empty($xlanguage_langs)) {
269
            $pattern = '/(\[([\/])?(' . \implode('|', \array_map('\preg_quote', \array_values($xlanguage_langs))) . ')([\|\]]))/isU';
270
            $ret     = \preg_replace($pattern, '&#91;\\2\\3\\4', $ret);
271
        }
272
273
        return $ret;
274
    }
275
276
    /**
277
     * @param null|array $options
278
     * @return bool
279
     */
280
    public static function showSelectedLanguage($options = null)
281
    {
282
        require_once XOOPS_ROOT_PATH . '/modules/xlanguage/blocks/xlanguage_blocks.php';
283
        if (empty($options)) {
284
            $options[0] = 'images'; // display style: image, text, select
285
            $options[1] = ' '; // delimitor
286
            $options[2] = 5; // items per line
287
        }
288
289
        $block        = \b_xlanguage_select_show($options);
290
        $block['tag'] = 'xlanguage';
291
292
        $content = '';
293
        $i       = 1;
294
        if (!empty($block['display'])) { //mb
295
            if (\in_array($block['display'], ['images', 'text'])) {
296
                foreach ($block['languages'] as $name => $lang) {
297
                    $content .= '<a href="' . $block['url'] . $lang['name'] . '" title="' . $lang['desc'] . '">';
298
                    if ('images' === $block['display']) {
299
                        $content .= '<img src="' . $lang['image'] . '" alt="' . $lang['desc'] . '"';
300
                        if ($block['selected'] != $lang['name']) {
301
                            $content .= ' style="MozOpacity: .8; opacity: .8; filter:Alpha(opacity=80);"';
302
                        }
303
                        $content .= '>';
304
                    } else {
305
                        $content .= $lang['desc'];
306
                    }
307
                    $content .= '</a>';
308
                    if (0 == (++$i % $block['number'])) {
309
                        $content .= '<br>';
310
                    }
311
                }
312
            } else {
313
                $content .= '<select name="' . $block['tag'] . '"
314
                onChange="if (this.options[this.selectedIndex].value.length >0) { window.document.location=this.options[this.selectedIndex].value;}"
315
                >';
316
                if (!empty($block['languages'])) { //mb
317
                    foreach ($block['languages'] as $name => $lang) {
318
                        $content .= '<option value="' . $block['url'] . $lang['name'] . '"';
319
                        if ($block['selected'] == $lang['name']) {
320
                            $content .= ' selected ';
321
                        }
322
                        $content .= '>' . $lang['desc'] . '</option>';
323
                    }
324
                }
325
                $content .= '</select>';
326
            }
327
        }
328
329
        \define('XLANGUAGE_SWITCH_CODE', $content);
330
331
        return true;
332
    }
333
334
    /**
335
     * @return int|string
336
     */
337
    public static function getPreferredLanguage()
338
    {
339
        $langs = [];
340
        $lang  = '';
341
        //        if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
342
        if (Request::hasVar('HTTP_ACCEPT_LANGUAGE', 'SERVER')) {
343
            // break up string into pieces (languages and q factors)
344
            $temp = Request::getString('HTTP_ACCEPT_LANGUAGE', '', 'SERVER');
345
            \preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.\d+))?/i', $temp, $lang_parse);
346
            if (\count($lang_parse[1])) {
347
                // create a list like "en" => 0.8
348
                $langs = \array_combine($lang_parse[1], $lang_parse[4]);
349
                // set default to 1 for any without q factor
350
                foreach ($langs as $lang => $val) {
351
                    if ('' === $val) {
352
                        $langs[$lang] = 1;
353
                    }
354
                }
355
                // sort list based on value
356
                \arsort($langs, \SORT_NUMERIC);
357
            }
358
        }
359
        //extract most important (first)
360
        foreach ($langs as $lang => $val) {
361
            break;
362
        }
363
        //if complex language simplify it
364
        if (false !== mb_strpos($lang, '-')) {
365
            $tmp  = \explode('-', $lang);
366
            $lang = $tmp[0];
367
        }
368
369
        return $lang;
370
    }
371
}
372