Mbstring::mb_convert_variables()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
c 0
b 0
f 0
nc 2
nop 8
dl 0
loc 12
rs 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Symfony\Polyfill\Mbstring;
13
14
/**
15
 * Partial mbstring implementation in PHP, iconv based, UTF-8 centric.
16
 *
17
 * Implemented:
18
 * - mb_chr                  - Returns a specific character from its Unicode code point
19
 * - mb_convert_encoding     - Convert character encoding
20
 * - mb_convert_variables    - Convert character code in variable(s)
21
 * - mb_decode_mimeheader    - Decode string in MIME header field
22
 * - mb_encode_mimeheader    - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED
23
 * - mb_convert_case         - Perform case folding on a string
24
 * - mb_get_info             - Get internal settings of mbstring
25
 * - mb_http_input           - Detect HTTP input character encoding
26
 * - mb_http_output          - Set/Get HTTP output character encoding
27
 * - mb_internal_encoding    - Set/Get internal character encoding
28
 * - mb_list_encodings       - Returns an array of all supported encodings
29
 * - mb_ord                  - Returns the Unicode code point of a character
30
 * - mb_output_handler       - Callback function converts character encoding in output buffer
31
 * - mb_scrub                - Replaces ill-formed byte sequences with substitute characters
32
 * - mb_strlen               - Get string length
33
 * - mb_strpos               - Find position of first occurrence of string in a string
34
 * - mb_strrpos              - Find position of last occurrence of a string in a string
35
 * - mb_strtolower           - Make a string lowercase
36
 * - mb_strtoupper           - Make a string uppercase
37
 * - mb_substitute_character - Set/Get substitution character
38
 * - mb_substr               - Get part of string
39
 * - mb_stripos              - Finds position of first occurrence of a string within another, case insensitive
40
 * - mb_stristr              - Finds first occurrence of a string within another, case insensitive
41
 * - mb_strrchr              - Finds the last occurrence of a character in a string within another
42
 * - mb_strrichr             - Finds the last occurrence of a character in a string within another, case insensitive
43
 * - mb_strripos             - Finds position of last occurrence of a string within another, case insensitive
44
 * - mb_strstr               - Finds first occurrence of a string within anothers
45
 * - mb_strwidth             - Return width of string
46
 * - mb_substr_count         - Count the number of substring occurrences
47
 *
48
 * Not implemented:
49
 * - mb_convert_kana         - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
50
 * - mb_decode_numericentity - Decode HTML numeric string reference to character
51
 * - mb_encode_numericentity - Encode character to HTML numeric string reference
52
 * - mb_ereg_*               - Regular expression with multibyte support
53
 * - mb_parse_str            - Parse GET/POST/COOKIE data and set global variable
54
 * - mb_preferred_mime_name  - Get MIME charset string
55
 * - mb_regex_encoding       - Returns current encoding for multibyte regex as string
56
 * - mb_regex_set_options    - Set/Get the default options for mbregex functions
57
 * - mb_send_mail            - Send encoded mail
58
 * - mb_split                - Split multibyte string using regular expression
59
 * - mb_strcut               - Get part of string
60
 * - mb_strimwidth           - Get truncated string with specified width
61
 *
62
 * @author Nicolas Grekas <[email protected]>
63
 *
64
 * @internal
65
 */
66
final class Mbstring
67
{
68
    const MB_CASE_FOLD = PHP_INT_MAX;
69
70
    private static $encodingList = array('ASCII', 'UTF-8');
71
    private static $language = 'neutral';
72
    private static $internalEncoding = 'UTF-8';
73
    private static $caseFold = array(
74
        array('µ','ſ',"\xCD\x85",'ς',"\xCF\x90","\xCF\x91","\xCF\x95","\xCF\x96","\xCF\xB0","\xCF\xB1","\xCF\xB5","\xE1\xBA\x9B","\xE1\xBE\xBE"),
75
        array('μ','s','ι',       'σ','β',       'θ',       'φ',       'π',       'κ',       'ρ',       'ε',       "\xE1\xB9\xA1",'ι'),
76
    );
77
78
    public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
79
    {
80
        if (is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
81
            $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
82
        } else {
83
            $fromEncoding = self::getEncoding($fromEncoding);
84
        }
85
86
        $toEncoding = self::getEncoding($toEncoding);
87
88
        if ('BASE64' === $fromEncoding) {
89
            $s = base64_decode($s);
90
            $fromEncoding = $toEncoding;
91
        }
92
93
        if ('BASE64' === $toEncoding) {
94
            return base64_encode($s);
95
        }
96
97
        if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
98
            if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
99
                $fromEncoding = 'Windows-1252';
100
            }
101
            if ('UTF-8' !== $fromEncoding) {
102
                $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
103
            }
104
105
            return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s);
106
        }
107
108
        if ('HTML-ENTITIES' === $fromEncoding) {
109
            $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
110
            $fromEncoding = 'UTF-8';
111
        }
112
113
        return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
114
    }
115
116
    public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null)
117
    {
118
        $vars = array(&$a, &$b, &$c, &$d, &$e, &$f);
119
120
        $ok = true;
121
        array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
122
            if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
123
                $ok = false;
124
            }
125
        });
126
127
        return $ok ? $fromEncoding : false;
128
    }
129
130
    public static function mb_decode_mimeheader($s)
131
    {
132
        return iconv_mime_decode($s, 2, self::$internalEncoding);
133
    }
134
135
    public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
0 ignored issues
show
Unused Code introduced by
The parameter $indent is not used and could be removed. ( Ignorable by Annotation )

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

135
    public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, /** @scrutinizer ignore-unused */ $indent = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $linefeed is not used and could be removed. ( Ignorable by Annotation )

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

135
    public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, /** @scrutinizer ignore-unused */ $linefeed = null, $indent = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $s is not used and could be removed. ( Ignorable by Annotation )

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

135
    public static function mb_encode_mimeheader(/** @scrutinizer ignore-unused */ $s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $charset is not used and could be removed. ( Ignorable by Annotation )

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

135
    public static function mb_encode_mimeheader($s, /** @scrutinizer ignore-unused */ $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $transferEncoding is not used and could be removed. ( Ignorable by Annotation )

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

135
    public static function mb_encode_mimeheader($s, $charset = null, /** @scrutinizer ignore-unused */ $transferEncoding = null, $linefeed = null, $indent = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
136
    {
137
        trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING);
138
    }
139
140
    public static function mb_convert_case($s, $mode, $encoding = null)
141
    {
142
        if ('' === $s .= '') {
143
            return '';
144
        }
145
146
        $encoding = self::getEncoding($encoding);
147
148
        if ('UTF-8' === $encoding) {
149
            $encoding = null;
150
            if (!preg_match('//u', $s)) {
151
                $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
152
            }
153
        } else {
154
            $s = iconv($encoding, 'UTF-8//IGNORE', $s);
155
        }
156
157
        if (MB_CASE_TITLE == $mode) {
158
            $s = preg_replace_callback('/\b\p{Ll}/u', array(__CLASS__, 'title_case_upper'), $s);
159
            $s = preg_replace_callback('/\B[\p{Lu}\p{Lt}]+/u', array(__CLASS__, 'title_case_lower'), $s);
160
        } else {
161
            if (MB_CASE_UPPER == $mode) {
162
                static $upper = null;
163
                if (null === $upper) {
164
                    $upper = self::getData('upperCase');
165
                }
166
                $map = $upper;
167
            } else {
168
                if (self::MB_CASE_FOLD === $mode) {
169
                    $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
170
                }
171
172
                static $lower = null;
173
                if (null === $lower) {
174
                    $lower = self::getData('lowerCase');
175
                }
176
                $map = $lower;
177
            }
178
179
            static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
180
181
            $i = 0;
182
            $len = strlen($s);
0 ignored issues
show
Bug introduced by
It seems like $s can also be of type false; however, parameter $string of strlen() 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

182
            $len = strlen(/** @scrutinizer ignore-type */ $s);
Loading history...
183
184
            while ($i < $len) {
185
                $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
186
                $uchr = substr($s, $i, $ulen);
0 ignored issues
show
Bug introduced by
It seems like $s can also be of type false; however, parameter $string of substr() 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

186
                $uchr = substr(/** @scrutinizer ignore-type */ $s, $i, $ulen);
Loading history...
187
                $i += $ulen;
188
189
                if (isset($map[$uchr])) {
190
                    $uchr = $map[$uchr];
191
                    $nlen = strlen($uchr);
192
193
                    if ($nlen == $ulen) {
194
                        $nlen = $i;
195
                        do {
196
                            $s[--$nlen] = $uchr[--$ulen];
197
                        } while ($ulen);
198
                    } else {
199
                        $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
0 ignored issues
show
Bug introduced by
It seems like $s can also be of type false; however, parameter $string of substr_replace() does only seem to accept array|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

199
                        $s = substr_replace(/** @scrutinizer ignore-type */ $s, $uchr, $i - $ulen, $ulen);
Loading history...
200
                        $len += $nlen - $ulen;
201
                        $i   += $nlen - $ulen;
202
                    }
203
                }
204
            }
205
        }
206
207
        if (null === $encoding) {
208
            return $s;
209
        }
210
211
        return iconv('UTF-8', $encoding.'//IGNORE', $s);
212
    }
213
214
    public static function mb_internal_encoding($encoding = null)
215
    {
216
        if (null === $encoding) {
217
            return self::$internalEncoding;
218
        }
219
220
        $encoding = self::getEncoding($encoding);
221
222
        if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) {
223
            self::$internalEncoding = $encoding;
224
225
            return true;
226
        }
227
228
        return false;
229
    }
230
231
    public static function mb_language($lang = null)
232
    {
233
        if (null === $lang) {
234
            return self::$language;
235
        }
236
237
        switch ($lang = strtolower($lang)) {
238
            case 'uni':
239
            case 'neutral':
240
                self::$language = $lang;
241
242
                return true;
243
        }
244
245
        return false;
246
    }
247
248
    public static function mb_list_encodings()
249
    {
250
        return array('UTF-8');
251
    }
252
253
    public static function mb_encoding_aliases($encoding)
254
    {
255
        switch (strtoupper($encoding)) {
256
            case 'UTF8':
257
            case 'UTF-8':
258
                return array('utf8');
259
        }
260
261
        return false;
262
    }
263
264
    public static function mb_check_encoding($var = null, $encoding = null)
265
    {
266
        if (null === $encoding) {
267
            if (null === $var) {
268
                return false;
269
            }
270
            $encoding = self::$internalEncoding;
271
        }
272
273
        return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var);
274
    }
275
276
    public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
0 ignored issues
show
Unused Code introduced by
The parameter $strict is not used and could be removed. ( Ignorable by Annotation )

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

276
    public static function mb_detect_encoding($str, $encodingList = null, /** @scrutinizer ignore-unused */ $strict = false)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
277
    {
278
        if (null === $encodingList) {
279
            $encodingList = self::$encodingList;
280
        } else {
281
            if (!is_array($encodingList)) {
282
                $encodingList = array_map('trim', explode(',', $encodingList));
283
            }
284
            $encodingList = array_map('strtoupper', $encodingList);
285
        }
286
287
        foreach ($encodingList as $enc) {
288
            switch ($enc) {
289
                case 'ASCII':
290
                    if (!preg_match('/[\x80-\xFF]/', $str)) {
291
                        return $enc;
292
                    }
293
                    break;
294
295
                case 'UTF8':
296
                case 'UTF-8':
297
                    if (preg_match('//u', $str)) {
298
                        return 'UTF-8';
299
                    }
300
                    break;
301
302
                default:
303
                    if (0 === strncmp($enc, 'ISO-8859-', 9)) {
304
                        return $enc;
305
                    }
306
            }
307
        }
308
309
        return false;
310
    }
311
312
    public static function mb_detect_order($encodingList = null)
313
    {
314
        if (null === $encodingList) {
315
            return self::$encodingList;
316
        }
317
318
        if (!is_array($encodingList)) {
319
            $encodingList = array_map('trim', explode(',', $encodingList));
320
        }
321
        $encodingList = array_map('strtoupper', $encodingList);
322
323
        foreach ($encodingList as $enc) {
324
            switch ($enc) {
325
                default:
326
                    if (strncmp($enc, 'ISO-8859-', 9)) {
327
                        return false;
328
                    }
329
                case 'ASCII':
330
                case 'UTF8':
331
                case 'UTF-8':
332
            }
333
        }
334
335
        self::$encodingList = $encodingList;
336
337
        return true;
338
    }
339
340
    public static function mb_strlen($s, $encoding = null)
341
    {
342
        $encoding = self::getEncoding($encoding);
343
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
344
            return strlen($s);
345
        }
346
347
        return @iconv_strlen($s, $encoding);
348
    }
349
350
    public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
351
    {
352
        $encoding = self::getEncoding($encoding);
353
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
354
            return strpos($haystack, $needle, $offset);
355
        }
356
357
        if ('' === $needle .= '') {
358
            trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING);
359
360
            return false;
361
        }
362
363
        return iconv_strpos($haystack, $needle, $offset, $encoding);
364
    }
365
366
    public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
367
    {
368
        $encoding = self::getEncoding($encoding);
369
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
370
            return strrpos($haystack, $needle, $offset);
371
        }
372
373
        if ($offset != (int) $offset) {
374
            $offset = 0;
375
        } elseif ($offset = (int) $offset) {
376
            if ($offset < 0) {
377
                $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
378
                $offset = 0;
379
            } else {
380
                $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
381
            }
382
        }
383
384
        $pos = iconv_strrpos($haystack, $needle, $encoding);
385
386
        return false !== $pos ? $offset + $pos : false;
387
    }
388
389
    public static function mb_strtolower($s, $encoding = null)
390
    {
391
        return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
392
    }
393
394
    public static function mb_strtoupper($s, $encoding = null)
395
    {
396
        return self::mb_convert_case($s, MB_CASE_UPPER, $encoding);
397
    }
398
399
    public static function mb_substitute_character($c = null)
400
    {
401
        if (0 === strcasecmp($c, 'none')) {
402
            return true;
403
        }
404
405
        return null !== $c ? false : 'none';
406
    }
407
408
    public static function mb_substr($s, $start, $length = null, $encoding = null)
409
    {
410
        $encoding = self::getEncoding($encoding);
411
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
412
            return substr($s, $start, null === $length ? 2147483647 : $length);
413
        }
414
415
        if ($start < 0) {
416
            $start = iconv_strlen($s, $encoding) + $start;
417
            if ($start < 0) {
418
                $start = 0;
419
            }
420
        }
421
422
        if (null === $length) {
423
            $length = 2147483647;
424
        } elseif ($length < 0) {
425
            $length = iconv_strlen($s, $encoding) + $length - $start;
426
            if ($length < 0) {
427
                return '';
428
            }
429
        }
430
431
        return iconv_substr($s, $start, $length, $encoding).'';
432
    }
433
434
    public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
435
    {
436
        $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
437
        $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
438
439
        return self::mb_strpos($haystack, $needle, $offset, $encoding);
440
    }
441
442
    public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
443
    {
444
        $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
445
446
        return self::getSubpart($pos, $part, $haystack, $encoding);
447
    }
448
449
    public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
450
    {
451
        $encoding = self::getEncoding($encoding);
452
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
453
            return strrchr($haystack, $needle, $part);
0 ignored issues
show
Unused Code introduced by
The call to strrchr() has too many arguments starting with $part. ( Ignorable by Annotation )

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

453
            return /** @scrutinizer ignore-call */ strrchr($haystack, $needle, $part);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
454
        }
455
        $needle = self::mb_substr($needle, 0, 1, $encoding);
456
        $pos = iconv_strrpos($haystack, $needle, $encoding);
457
458
        return self::getSubpart($pos, $part, $haystack, $encoding);
459
    }
460
461
    public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
462
    {
463
        $needle = self::mb_substr($needle, 0, 1, $encoding);
464
        $pos = self::mb_strripos($haystack, $needle, $encoding);
465
466
        return self::getSubpart($pos, $part, $haystack, $encoding);
467
    }
468
469
    public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
470
    {
471
        $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
472
        $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
473
474
        return self::mb_strrpos($haystack, $needle, $offset, $encoding);
475
    }
476
477
    public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

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

477
    public static function mb_strstr($haystack, $needle, $part = false, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
478
    {
479
        $pos = strpos($haystack, $needle);
480
        if (false === $pos) {
481
            return false;
482
        }
483
        if ($part) {
484
            return substr($haystack, 0, $pos);
485
        }
486
487
        return substr($haystack, $pos);
488
    }
489
490
    public static function mb_get_info($type = 'all')
491
    {
492
        $info = array(
493
            'internal_encoding' => self::$internalEncoding,
494
            'http_output' => 'pass',
495
            'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
496
            'func_overload' => 0,
497
            'func_overload_list' => 'no overload',
498
            'mail_charset' => 'UTF-8',
499
            'mail_header_encoding' => 'BASE64',
500
            'mail_body_encoding' => 'BASE64',
501
            'illegal_chars' => 0,
502
            'encoding_translation' => 'Off',
503
            'language' => self::$language,
504
            'detect_order' => self::$encodingList,
505
            'substitute_character' => 'none',
506
            'strict_detection' => 'Off',
507
        );
508
509
        if ('all' === $type) {
510
            return $info;
511
        }
512
        if (isset($info[$type])) {
513
            return $info[$type];
514
        }
515
516
        return false;
517
    }
518
519
    public static function mb_http_input($type = '')
0 ignored issues
show
Unused Code introduced by
The parameter $type is not used and could be removed. ( Ignorable by Annotation )

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

519
    public static function mb_http_input(/** @scrutinizer ignore-unused */ $type = '')

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
520
    {
521
        return false;
522
    }
523
524
    public static function mb_http_output($encoding = null)
525
    {
526
        return null !== $encoding ? 'pass' === $encoding : 'pass';
527
    }
528
529
    public static function mb_strwidth($s, $encoding = null)
530
    {
531
        $encoding = self::getEncoding($encoding);
532
533
        if ('UTF-8' !== $encoding) {
534
            $s = iconv($encoding, 'UTF-8//IGNORE', $s);
535
        }
536
537
        $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide);
538
539
        return ($wide << 1) + iconv_strlen($s, 'UTF-8');
540
    }
541
542
    public static function mb_substr_count($haystack, $needle, $encoding = null)
0 ignored issues
show
Unused Code introduced by
The parameter $encoding is not used and could be removed. ( Ignorable by Annotation )

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

542
    public static function mb_substr_count($haystack, $needle, /** @scrutinizer ignore-unused */ $encoding = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
543
    {
544
        return substr_count($haystack, $needle);
545
    }
546
547
    public static function mb_output_handler($contents, $status)
0 ignored issues
show
Unused Code introduced by
The parameter $status is not used and could be removed. ( Ignorable by Annotation )

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

547
    public static function mb_output_handler($contents, /** @scrutinizer ignore-unused */ $status)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
548
    {
549
        return $contents;
550
    }
551
552
    public static function mb_chr($code, $encoding = null)
553
    {
554
        if (0x80 > $code %= 0x200000) {
555
            $s = chr($code);
556
        } elseif (0x800 > $code) {
557
            $s = chr(0xC0 | $code >> 6).chr(0x80 | $code & 0x3F);
558
        } elseif (0x10000 > $code) {
559
            $s = chr(0xE0 | $code >> 12).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
560
        } else {
561
            $s = chr(0xF0 | $code >> 18).chr(0x80 | $code >> 12 & 0x3F).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
562
        }
563
564
        if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
565
            $s = mb_convert_encoding($s, $encoding, 'UTF-8');
566
        }
567
568
        return $s;
569
    }
570
571
    public static function mb_ord($s, $encoding = null)
572
    {
573
        if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
574
            $s = mb_convert_encoding($s, 'UTF-8', $encoding);
575
        }
576
577
        $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
578
        if (0xF0 <= $code) {
579
            return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
580
        }
581
        if (0xE0 <= $code) {
582
            return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
583
        }
584
        if (0xC0 <= $code) {
585
            return (($code - 0xC0) << 6) + $s[2] - 0x80;
586
        }
587
588
        return $code;
589
    }
590
591
    private static function getSubpart($pos, $part, $haystack, $encoding)
592
    {
593
        if (false === $pos) {
594
            return false;
595
        }
596
        if ($part) {
597
            return self::mb_substr($haystack, 0, $pos, $encoding);
598
        }
599
600
        return self::mb_substr($haystack, $pos, null, $encoding);
601
    }
602
603
    private static function html_encoding_callback($m)
604
    {
605
        $i = 1;
606
        $entities = '';
607
        $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8'));
608
609
        while (isset($m[$i])) {
610
            if (0x80 > $m[$i]) {
611
                $entities .= chr($m[$i++]);
612
                continue;
613
            }
614
            if (0xF0 <= $m[$i]) {
615
                $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
616
            } elseif (0xE0 <= $m[$i]) {
617
                $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
618
            } else {
619
                $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
620
            }
621
622
            $entities .= '&#'.$c.';';
623
        }
624
625
        return $entities;
626
    }
627
628
    private static function title_case_lower($s)
629
    {
630
        return self::mb_convert_case($s[0], MB_CASE_LOWER, 'UTF-8');
631
    }
632
633
    private static function title_case_upper($s)
634
    {
635
        return self::mb_convert_case($s[0], MB_CASE_UPPER, 'UTF-8');
636
    }
637
638
    private static function getData($file)
639
    {
640
        if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
641
            return require $file;
642
        }
643
644
        return false;
645
    }
646
647
    private static function getEncoding($encoding)
648
    {
649
        if (null === $encoding) {
650
            return self::$internalEncoding;
651
        }
652
653
        $encoding = strtoupper($encoding);
654
655
        if ('8BIT' === $encoding || 'BINARY' === $encoding) {
656
            return 'CP850';
657
        }
658
        if ('UTF8' === $encoding) {
659
            return 'UTF-8';
660
        }
661
662
        return $encoding;
663
    }
664
}
665