Passed
Push — master ( 22887c...b0a7cb )
by Michael
04:05 queued 02:12
created

Utility::encodeCharSet()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 1
dl 0
loc 14
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace XoopsModules\Xlanguage;
4
5
/**
6
 * Class Utility
7
 */
8
class Utility
9
{
10
    use Common\VersionChecks; //checkVerXoops, checkVerPhp Traits
0 ignored issues
show
introduced by
The trait XoopsModules\Xlanguage\Common\VersionChecks requires some properties which are not provided by XoopsModules\Xlanguage\Utility: $tag_name, $prerelease
Loading history...
11
12
    use Common\ServerStats; // getServerStats Trait
13
14
    use Common\FilesManagement; // Files Management Trait
15
16
    //--------------- Custom module methods -----------------------------
17
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
        /** @var \XoopsModules\Xlanguage\Helper $helper */
69
        $helper = Helper::getInstance();
70
        /** @var \XoopsModules\Xlanguage\LanguageHandler $xlanguageHandler */
71
        $xlanguageHandler = $helper->getHandler('Language');
72
73
        return $xlanguageHandler->createConfig();
74
    }
75
76
    /**
77
     * @return mixed
78
     */
79
    public static function loadConfig()
80
    {
81
        /** @var \XoopsModules\Xlanguage\Helper $helper */
82
        $helper = Helper::getInstance();
83
        /** @var \XoopsModules\Xlanguage\LanguageHandler $xlanguageHandler */
84
        $xlanguageHandler = $helper->getHandler('Language');
85
        $config           = $xlanguageHandler->loadFileConfig();
86
87
        return $config;
88
    }
89
90
    /**
91
     * Analyzes some PHP environment variables to find the most probable language
92
     * that should be used
93
     *
94
     * @param string $str
95
     * @param string $envType
96
     * @return int|string
97
     * @internal param $string $ string to analyze
98
     * @internal param $integer $ type of the PHP environment variable which value is $str
99
     *
100
     * @global        array    the list of available translations
101
     * @global        string   the retained translation keyword
102
     * @access   private
103
     */
104
    public static function langDetect($str = '', $envType = '')
105
    {
106
        global $available_languages;
107
        $lang = '';
108
109
        if (!empty($available_languages)) {
110
            foreach ($available_languages as $key => $value) {
111
                // $envType =  1 for the 'HTTP_ACCEPT_LANGUAGE' environment variable,
112
                //             2 for the 'HTTP_USER_AGENT' one
113
                $expr = $value[0];
114
                if (false === mb_strpos($expr, '[-_]')) {
115
                    $expr = str_replace('|', '([-_][[:alpha:]]{2,3})?|', $expr);
116
                }
117
                //        if (($envType == 1 && eregi('^(' . $expr . ')(;q=[0-9]\\.[0-9])?$', $str))
118
                //            || ($envType == 2 && eregi('(\(|\[|;[[:space:]])(' . $expr . ')(;|\]|\))', $str))) {
119
                if ((1 == $envType && preg_match('#^(' . $expr . ')(;q=[0-9]\\.[0-9])?$#i', $str)) || (2 == $envType && preg_match('#(\(|\[|;[[:space:]])(' . $expr . ')(;|\]|\))#i', $str))) {
120
                    $lang = $key;
121
                    //if($lang != 'en')
122
                    break;
123
                }
124
            }
125
        }
126
127
        return $lang;
128
    }
129
130
    /**
131
     * @return string
132
     */
133
    public static function detectLang()
134
    {
135
        global $available_languages, $_SERVER;
136
137
        //      if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
138
        if (\Xmf\Request::hasVar('HTTP_ACCEPT_LANGUAGE', 'SERVER')) {
139
            $HTTP_ACCEPT_LANGUAGE = \Xmf\Request::getString('HTTP_ACCEPT_LANGUAGE', '', 'SERVER');
0 ignored issues
show
Unused Code introduced by
The assignment to $HTTP_ACCEPT_LANGUAGE is dead and can be removed.
Loading history...
140
        }
141
142
        //if (!empty($_SERVER['HTTP_USER_AGENT'])) {
143
        if (\Xmf\Request::hasVar('HTTP_USER_AGENT', 'SERVER')) {
144
            $HTTP_USER_AGENT = \Xmf\Request::getString('HTTP_USER_AGENT', '', 'SERVER');
145
        }
146
147
        $lang       = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $lang is dead and can be removed.
Loading history...
148
        $xoops_lang = '';
149
        // 1. try to findout user's language by checking its HTTP_ACCEPT_LANGUAGE variable
150
151
        //    if (empty($lang) && !empty($HTTP_ACCEPT_LANGUAGE)) {
152
        //        $accepted    = explode(',', $HTTP_ACCEPT_LANGUAGE);
153
        //        $acceptedCnt = count($accepted);
154
        //        reset($accepted);
155
        //        for ($i = 0; $i < $acceptedCnt; ++$i) {
156
        //            $lang = static::langDetect($accepted[$i], 1);
157
        //            if (strncasecmp($lang, 'en', 2)) {
158
        //                break;
159
        //            }
160
        //        }
161
        //    }
162
163
        //This returns the most preferred language "q=1"
164
        $lang = static::getPreferredLanguage();
165
166
        // 2. if not found in HTTP_ACCEPT_LANGUAGE, try to find user's language by checking its HTTP_USER_AGENT variable
167
        if (empty($lang) && !empty($HTTP_USER_AGENT)) {
168
            $lang = static::langDetect($HTTP_USER_AGENT, 2);
169
        }
170
        // 3. If we catch a valid language, configure it
171
        if (!empty($lang)) {
172
            $xoops_lang = $available_languages[$lang][1];
173
        }
174
175
        return $xoops_lang;
176
    }
177
178
    /**
179
     * @param $output
180
     * @return array|mixed|string
181
     */
182
    public static function encodeCharSet($output)
183
    {
184
        global $xlanguage;
185
        $output = static::cleanMultiLang($output);
186
        // escape XML doc
187
        if (preg_match("/^\<\?[\s]?xml[\s]+version=([\"'])[^\>]+\\1[\s]+encoding=([\"'])[^\>]+\\2[\s]?\?\>/i", $output)) {
188
            return $output;
189
        }
190
        $in_charset  = $xlanguage['charset_base'];
191
        $out_charset = $xlanguage['charset'];
192
193
        $output = static::convertEncoding($output, $out_charset, $in_charset);
194
195
        return $output;
196
    }
197
198
    /**
199
     * @param string $text
200
     * @return mixed
201
     */
202
    public static function cleanMultiLang($text)
203
    {
204
        global $xoopsConfig;
205
        global $xlanguage_langs;
206
        $patterns = [];
207
        if (!isset($xlanguage_langs)) {
208
            $xlanguage_langs = [];
209
            /** @var \XoopsModules\Xlanguage\Helper $helper */
210
            $helper = Helper::getInstance();
211
            /** @var \XoopsModules\Xlanguage\LanguageHandler $xlanguageHandler */
212
            $xlanguageHandler = $helper->getHandler('Language');
213
            $langs            = $xlanguageHandler->getAll(true);
214
            //        $langs = $GLOBALS['xlanguageHandler']->getAll(true); //mb
215
            if (false !== $langs) {
216
                foreach (array_keys($langs) as $_lang) {
217
                    $xlanguage_langs[$_lang] = $langs[$_lang]->getVar('lang_code');
218
                }
219
            }
220
            unset($langs);
221
        }
222
        if (empty($xlanguage_langs) || 0 == count($xlanguage_langs)) {
223
            return $text;
224
        }
225
226
        // escape brackets inside of <code>...</code>
227
        $patterns[] = '/(\<code>.*\<\/code>)/isU';
228
229
        // escape brackets inside of <input type="..." value="...">
230
        $patterns[] = '/(\<input\b(?![^\>]*\btype=([\'"]?)(submit|image|reset|button))[^\>]*\>)/isU';
231
232
        // escape brackets inside of <textarea></textarea>
233
        $patterns[] = '/(\<textarea\b[^>]*>[^\<]*\<\/textarea>)/isU';
234
235
        $text = preg_replace_callback($patterns, 'static::escapeBracketMultiLang', $text);
236
237
        // create the pattern between language tags
238
        $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...
239
        $mid_pattern = '(?:(?!(' . str_replace(',', '|', preg_quote(XLANGUAGE_TAGS_RESERVED, '/')) . ')).)*';
240
241
        $patterns = [];
242
        $replaces = [];
243
244
        if (isset($xlanguage_langs[$xoopsConfig['language']])) {
245
            $lang       = $xlanguage_langs[$xoopsConfig['language']];
246
            $patterns[] = '/(\[([^\]]*\|)?' . preg_quote($lang, '~') . '(\|[^\]]*)?\])(' . $mid_pattern . ')(\[\/([^\]]*\|)?' . preg_quote($lang, '~') . '(\|[^\]]*)?\])/isU';
247
            $replaces[] = '$4';
248
        }
249
250
        foreach (array_keys($xlanguage_langs) as $_lang) {
251
            if ($_lang == @$xoopsConfig['language']) {
252
                continue;
253
            }
254
            $name       = $xlanguage_langs[$_lang];
255
            $patterns[] = '/(\[([^\]]*\|)?' . preg_quote($name, '~') . '(\|[^\]]*)?\])(' . $mid_pattern . ')(\[\/([^\]]*\|)?' . preg_quote($name, '~') . '(\|[^\]]*)?(\]\<br[\s]?[\/]?\>|\]))/isU';
256
            $replaces[] = '';
257
        }
258
        if (!empty($xoopsConfig['language'])) {
259
            $text = preg_replace('/\[[\/]?[\|]?' . preg_quote($xoopsConfig['language'], '~') . '[\|]?\](\<br \/\>)?/i', '', $text);
260
        }
261
        if (count($replaces) > 0) {
262
            $text = preg_replace($patterns, $replaces, $text);
263
        }
264
265
        return $text;
266
    }
267
268
    /**
269
     * @param $matches
270
     * @return mixed
271
     */
272
    public static function escapeBracketMultiLang($matches)
273
    {
274
        global $xlanguage_langs;
275
        $ret = $matches[1];
276
        if (!empty($xlanguage_langs)) {
277
            $pattern = '/(\[([\/])?(' . implode('|', array_map('preg_quote', array_values($xlanguage_langs))) . ')([\|\]]))/isU';
278
            $ret     = preg_replace($pattern, '&#91;\\2\\3\\4', $ret);
279
        }
280
281
        return $ret;
282
    }
283
284
    /**
285
     * @param null|array $options
286
     * @return bool
287
     */
288
    public static function showSelectedLanguage($options = null)
289
    {
290
        require_once XOOPS_ROOT_PATH . '/modules/xlanguage/blocks/xlanguage_blocks.php';
291
        if (empty($options)) {
292
            $options[0] = 'images'; // display style: image, text, select
293
            $options[1] = ' '; // delimitor
294
            $options[2] = 5; // items per line
295
        }
296
297
        $block        = b_xlanguage_select_show($options);
298
        $block['tag'] = 'xlanguage';
299
300
        $content = '';
301
        $i       = 1;
302
        if (!empty($block['display'])) { //mb
303
            if (in_array($block['display'], ['images', 'text'])) {
304
                foreach ($block['languages'] as $name => $lang) {
305
                    $content .= '<a href="' . $block['url'] . $lang['name'] . '" title="' . $lang['desc'] . '">';
306
                    if ('images' === $block['display']) {
307
                        $content .= '<img src="' . $lang['image'] . '" alt="' . $lang['desc'] . '"';
308
                        if ($block['selected'] != $lang['name']) {
309
                            $content .= ' style="MozOpacity: .8; opacity: .8; filter:Alpha(opacity=80);"';
310
                        }
311
                        $content .= '>';
312
                    } else {
313
                        $content .= $lang['desc'];
314
                    }
315
                    $content .= '</a>';
316
                    if (0 == (++$i % $block['number'])) {
317
                        $content .= '<br>';
318
                    }
319
                }
320
            } else {
321
                $content .= '<select name="' . $block['tag'] . '"
322
                onChange="if (this.options[this.selectedIndex].value.length >0) { window.document.location=this.options[this.selectedIndex].value;}"
323
                >';
324
                if (!empty($block['languages'])) { //mb
325
                    foreach ($block['languages'] as $name => $lang) {
326
                        $content .= '<option value="' . $block['url'] . $lang['name'] . '"';
327
                        if ($block['selected'] == $lang['name']) {
328
                            $content .= ' selected ';
329
                        }
330
                        $content .= '>' . $lang['desc'] . '</option>';
331
                    }
332
                }
333
                $content .= '</select>';
334
            }
335
        }
336
337
        define('XLANGUAGE_SWITCH_CODE', $content);
338
339
        return true;
340
    }
341
342
    /**
343
     * @return int|string
344
     */
345
    public static function getPreferredLanguage()
346
    {
347
        $langs = [];
348
        $lang = '';
349
        //        if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
350
        if (\Xmf\Request::hasVar('HTTP_ACCEPT_LANGUAGE', 'SERVER')) {
351
            // break up string into pieces (languages and q factors)
352
            $temp = \Xmf\Request::getString('HTTP_ACCEPT_LANGUAGE', '', 'SERVER');
353
            preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.\d+))?/i', $temp, $lang_parse);
354
            if (count($lang_parse[1])) {
355
                // create a list like "en" => 0.8
356
                $langs = array_combine($lang_parse[1], $lang_parse[4]);
357
                // set default to 1 for any without q factor
358
                foreach ($langs as $lang => $val) {
359
                    if ('' === $val) {
360
                        $langs[$lang] = 1;
361
                    }
362
                }
363
                // sort list based on value
364
                arsort($langs, SORT_NUMERIC);
0 ignored issues
show
Bug introduced by
It seems like $langs can also be of type false; however, parameter $array of arsort() 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

364
                arsort(/** @scrutinizer ignore-type */ $langs, SORT_NUMERIC);
Loading history...
365
            }
366
        }
367
        //extract most important (first)
368
        foreach ($langs as $lang => $val) {
369
            break;
370
        }
371
        //if complex language simplify it
372
        if (false !== mb_strpos($lang, '-')) {
373
            $tmp  = explode('-', $lang);
374
            $lang = $tmp[0];
375
        }
376
377
        return $lang;
378
    }
379
}
380