Completed
Push — develop ( ec7312...1cf119 )
by Adrien
27:33
created

StringHelper::getIsIconvEnabled()   C

Complexity

Conditions 11
Paths 6

Size

Total Lines 40
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 23.6107

Importance

Changes 0
Metric Value
cc 11
eloc 17
nc 6
nop 0
dl 0
loc 40
rs 5.2653
c 0
b 0
f 0
ccs 9
cts 17
cp 0.5294
crap 23.6107

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
namespace PhpOffice\PhpSpreadsheet\Shared;
4
5
use PhpOffice\PhpSpreadsheet\Calculation;
6
7
/**
8
 * Copyright (c) 2006 - 2016 PhpSpreadsheet.
9
 *
10
 * This library is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU Lesser General Public
12
 * License as published by the Free Software Foundation; either
13
 * version 2.1 of the License, or (at your option) any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
 * Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public
21
 * License along with this library; if not, write to the Free Software
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
 *
24
 * @category   PhpSpreadsheet
25
 *
26
 * @copyright  Copyright (c) 2006 - 2016 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
27
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
28
 */
29
class StringHelper
30
{
31
    /**    Constants                */
32
    /**    Regular Expressions        */
33
    //    Fraction
34
    const STRING_REGEXP_FRACTION = '(-?)(\d+)\s+(\d+\/\d+)';
35
36
    /**
37
     * Control characters array.
38
     *
39
     * @var string[]
40
     */
41
    private static $controlCharacters = [];
42
43
    /**
44
     * SYLK Characters array.
45
     *
46
     * @var array
47
     */
48
    private static $SYLKCharacters = [];
49
50
    /**
51
     * Decimal separator.
52
     *
53
     * @var string
54
     */
55
    private static $decimalSeparator;
56
57
    /**
58
     * Thousands separator.
59
     *
60
     * @var string
61
     */
62
    private static $thousandsSeparator;
63
64
    /**
65
     * Currency code.
66
     *
67
     * @var string
68
     */
69
    private static $currencyCode;
70
71
    /**
72
     * Is iconv extension avalable?
73
     *
74
     * @var bool
75
     */
76
    private static $isIconvEnabled;
77
78
    /**
79
     * Build control characters array.
80
     */
81 52
    private static function buildControlCharacters()
82
    {
83 52
        for ($i = 0; $i <= 31; ++$i) {
84 52
            if ($i != 9 && $i != 10 && $i != 13) {
85 52
                $find = '_x' . sprintf('%04s', strtoupper(dechex($i))) . '_';
86 52
                $replace = chr($i);
87 52
                self::$controlCharacters[$find] = $replace;
88
            }
89
        }
90 52
    }
91
92
    /**
93
     * Build SYLK characters array.
94
     */
95 52
    private static function buildSYLKCharacters()
96
    {
97 52
        self::$SYLKCharacters = [
98 52
            "\x1B 0" => chr(0),
99 52
            "\x1B 1" => chr(1),
100 52
            "\x1B 2" => chr(2),
101 52
            "\x1B 3" => chr(3),
102 52
            "\x1B 4" => chr(4),
103 52
            "\x1B 5" => chr(5),
104 52
            "\x1B 6" => chr(6),
105 52
            "\x1B 7" => chr(7),
106 52
            "\x1B 8" => chr(8),
107 52
            "\x1B 9" => chr(9),
108 52
            "\x1B :" => chr(10),
109 52
            "\x1B ;" => chr(11),
110 52
            "\x1B <" => chr(12),
111 52
            "\x1B =" => chr(13),
112 52
            "\x1B >" => chr(14),
113 52
            "\x1B ?" => chr(15),
114 52
            "\x1B!0" => chr(16),
115 52
            "\x1B!1" => chr(17),
116 52
            "\x1B!2" => chr(18),
117 52
            "\x1B!3" => chr(19),
118 52
            "\x1B!4" => chr(20),
119 52
            "\x1B!5" => chr(21),
120 52
            "\x1B!6" => chr(22),
121 52
            "\x1B!7" => chr(23),
122 52
            "\x1B!8" => chr(24),
123 52
            "\x1B!9" => chr(25),
124 52
            "\x1B!:" => chr(26),
125 52
            "\x1B!;" => chr(27),
126 52
            "\x1B!<" => chr(28),
127 52
            "\x1B!=" => chr(29),
128 52
            "\x1B!>" => chr(30),
129 52
            "\x1B!?" => chr(31),
130 52
            "\x1B'?" => chr(127),
131 52
            "\x1B(0" => '€', // 128 in CP1252
132 52
            "\x1B(2" => '‚', // 130 in CP1252
133 52
            "\x1B(3" => 'ƒ', // 131 in CP1252
134 52
            "\x1B(4" => '„', // 132 in CP1252
135 52
            "\x1B(5" => '…', // 133 in CP1252
136 52
            "\x1B(6" => '†', // 134 in CP1252
137 52
            "\x1B(7" => '‡', // 135 in CP1252
138 52
            "\x1B(8" => 'ˆ', // 136 in CP1252
139 52
            "\x1B(9" => '‰', // 137 in CP1252
140 52
            "\x1B(:" => 'Š', // 138 in CP1252
141 52
            "\x1B(;" => '‹', // 139 in CP1252
142 52
            "\x1BNj" => 'Œ', // 140 in CP1252
143 52
            "\x1B(>" => 'Ž', // 142 in CP1252
144 52
            "\x1B)1" => '‘', // 145 in CP1252
145 52
            "\x1B)2" => '’', // 146 in CP1252
146 52
            "\x1B)3" => '“', // 147 in CP1252
147 52
            "\x1B)4" => '”', // 148 in CP1252
148 52
            "\x1B)5" => '•', // 149 in CP1252
149 52
            "\x1B)6" => '–', // 150 in CP1252
150 52
            "\x1B)7" => '—', // 151 in CP1252
151 52
            "\x1B)8" => '˜', // 152 in CP1252
152 52
            "\x1B)9" => '™', // 153 in CP1252
153 52
            "\x1B):" => 'š', // 154 in CP1252
154 52
            "\x1B);" => '›', // 155 in CP1252
155 52
            "\x1BNz" => 'œ', // 156 in CP1252
156 52
            "\x1B)>" => 'ž', // 158 in CP1252
157 52
            "\x1B)?" => 'Ÿ', // 159 in CP1252
158 52
            "\x1B*0" => ' ', // 160 in CP1252
159 52
            "\x1BN!" => '¡', // 161 in CP1252
160 52
            "\x1BN\"" => '¢', // 162 in CP1252
161 52
            "\x1BN#" => '£', // 163 in CP1252
162 52
            "\x1BN(" => '¤', // 164 in CP1252
163 52
            "\x1BN%" => '¥', // 165 in CP1252
164 52
            "\x1B*6" => '¦', // 166 in CP1252
165 52
            "\x1BN'" => '§', // 167 in CP1252
166 52
            "\x1BNH " => '¨', // 168 in CP1252
167 52
            "\x1BNS" => '©', // 169 in CP1252
168 52
            "\x1BNc" => 'ª', // 170 in CP1252
169 52
            "\x1BN+" => '«', // 171 in CP1252
170 52
            "\x1B*<" => '¬', // 172 in CP1252
171 52
            "\x1B*=" => '­', // 173 in CP1252
172 52
            "\x1BNR" => '®', // 174 in CP1252
173 52
            "\x1B*?" => '¯', // 175 in CP1252
174 52
            "\x1BN0" => '°', // 176 in CP1252
175 52
            "\x1BN1" => '±', // 177 in CP1252
176 52
            "\x1BN2" => '²', // 178 in CP1252
177 52
            "\x1BN3" => '³', // 179 in CP1252
178 52
            "\x1BNB " => '´', // 180 in CP1252
179 52
            "\x1BN5" => 'µ', // 181 in CP1252
180 52
            "\x1BN6" => '¶', // 182 in CP1252
181 52
            "\x1BN7" => '·', // 183 in CP1252
182 52
            "\x1B+8" => '¸', // 184 in CP1252
183 52
            "\x1BNQ" => '¹', // 185 in CP1252
184 52
            "\x1BNk" => 'º', // 186 in CP1252
185 52
            "\x1BN;" => '»', // 187 in CP1252
186 52
            "\x1BN<" => '¼', // 188 in CP1252
187 52
            "\x1BN=" => '½', // 189 in CP1252
188 52
            "\x1BN>" => '¾', // 190 in CP1252
189 52
            "\x1BN?" => '¿', // 191 in CP1252
190 52
            "\x1BNAA" => 'À', // 192 in CP1252
191 52
            "\x1BNBA" => 'Á', // 193 in CP1252
192 52
            "\x1BNCA" => 'Â', // 194 in CP1252
193 52
            "\x1BNDA" => 'Ã', // 195 in CP1252
194 52
            "\x1BNHA" => 'Ä', // 196 in CP1252
195 52
            "\x1BNJA" => 'Å', // 197 in CP1252
196 52
            "\x1BNa" => 'Æ', // 198 in CP1252
197 52
            "\x1BNKC" => 'Ç', // 199 in CP1252
198 52
            "\x1BNAE" => 'È', // 200 in CP1252
199 52
            "\x1BNBE" => 'É', // 201 in CP1252
200 52
            "\x1BNCE" => 'Ê', // 202 in CP1252
201 52
            "\x1BNHE" => 'Ë', // 203 in CP1252
202 52
            "\x1BNAI" => 'Ì', // 204 in CP1252
203 52
            "\x1BNBI" => 'Í', // 205 in CP1252
204 52
            "\x1BNCI" => 'Î', // 206 in CP1252
205 52
            "\x1BNHI" => 'Ï', // 207 in CP1252
206 52
            "\x1BNb" => 'Ð', // 208 in CP1252
207 52
            "\x1BNDN" => 'Ñ', // 209 in CP1252
208 52
            "\x1BNAO" => 'Ò', // 210 in CP1252
209 52
            "\x1BNBO" => 'Ó', // 211 in CP1252
210 52
            "\x1BNCO" => 'Ô', // 212 in CP1252
211 52
            "\x1BNDO" => 'Õ', // 213 in CP1252
212 52
            "\x1BNHO" => 'Ö', // 214 in CP1252
213 52
            "\x1B-7" => '×', // 215 in CP1252
214 52
            "\x1BNi" => 'Ø', // 216 in CP1252
215 52
            "\x1BNAU" => 'Ù', // 217 in CP1252
216 52
            "\x1BNBU" => 'Ú', // 218 in CP1252
217 52
            "\x1BNCU" => 'Û', // 219 in CP1252
218 52
            "\x1BNHU" => 'Ü', // 220 in CP1252
219 52
            "\x1B-=" => 'Ý', // 221 in CP1252
220 52
            "\x1BNl" => 'Þ', // 222 in CP1252
221 52
            "\x1BN{" => 'ß', // 223 in CP1252
222 52
            "\x1BNAa" => 'à', // 224 in CP1252
223 52
            "\x1BNBa" => 'á', // 225 in CP1252
224 52
            "\x1BNCa" => 'â', // 226 in CP1252
225 52
            "\x1BNDa" => 'ã', // 227 in CP1252
226 52
            "\x1BNHa" => 'ä', // 228 in CP1252
227 52
            "\x1BNJa" => 'å', // 229 in CP1252
228 52
            "\x1BNq" => 'æ', // 230 in CP1252
229 52
            "\x1BNKc" => 'ç', // 231 in CP1252
230 52
            "\x1BNAe" => 'è', // 232 in CP1252
231 52
            "\x1BNBe" => 'é', // 233 in CP1252
232 52
            "\x1BNCe" => 'ê', // 234 in CP1252
233 52
            "\x1BNHe" => 'ë', // 235 in CP1252
234 52
            "\x1BNAi" => 'ì', // 236 in CP1252
235 52
            "\x1BNBi" => 'í', // 237 in CP1252
236 52
            "\x1BNCi" => 'î', // 238 in CP1252
237 52
            "\x1BNHi" => 'ï', // 239 in CP1252
238 52
            "\x1BNs" => 'ð', // 240 in CP1252
239 52
            "\x1BNDn" => 'ñ', // 241 in CP1252
240 52
            "\x1BNAo" => 'ò', // 242 in CP1252
241 52
            "\x1BNBo" => 'ó', // 243 in CP1252
242 52
            "\x1BNCo" => 'ô', // 244 in CP1252
243 52
            "\x1BNDo" => 'õ', // 245 in CP1252
244 52
            "\x1BNHo" => 'ö', // 246 in CP1252
245 52
            "\x1B/7" => '÷', // 247 in CP1252
246 52
            "\x1BNy" => 'ø', // 248 in CP1252
247 52
            "\x1BNAu" => 'ù', // 249 in CP1252
248 52
            "\x1BNBu" => 'ú', // 250 in CP1252
249 52
            "\x1BNCu" => 'û', // 251 in CP1252
250 52
            "\x1BNHu" => 'ü', // 252 in CP1252
251 52
            "\x1B/=" => 'ý', // 253 in CP1252
252 52
            "\x1BN|" => 'þ', // 254 in CP1252
253 52
            "\x1BNHy" => 'ÿ', // 255 in CP1252
254
        ];
255 52
    }
256
257
    /**
258
     * Get whether iconv extension is available.
259
     *
260
     * @return bool
261
     */
262 79
    public static function getIsIconvEnabled()
263
    {
264 79
        if (isset(self::$isIconvEnabled)) {
265 78
            return self::$isIconvEnabled;
266
        }
267
268
        // Fail if iconv doesn't exist
269 62
        if (!function_exists('iconv')) {
270
            self::$isIconvEnabled = false;
271
272
            return false;
273
        }
274
275
        // Sometimes iconv is not working, and e.g. iconv('UTF-8', 'UTF-16LE', 'x') just returns false,
276 62
        if (!@iconv('UTF-8', 'UTF-16LE', 'x')) {
277
            self::$isIconvEnabled = false;
278
279
            return false;
280
        }
281
282
        // Sometimes iconv_substr('A', 0, 1, 'UTF-8') just returns false in PHP 5.2.0
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
283
        // we cannot use iconv in that case either (http://bugs.php.net/bug.php?id=37773)
284 62
        if (!@iconv_substr('A', 0, 1, 'UTF-8')) {
285
            self::$isIconvEnabled = false;
286
287
            return false;
288
        }
289
290
        // CUSTOM: IBM AIX iconv() does not work
291 62
        if (defined('PHP_OS') && @stristr(PHP_OS, 'AIX') && defined('ICONV_IMPL') && (@strcasecmp(ICONV_IMPL, 'unknown') == 0) && defined('ICONV_VERSION') && (@strcasecmp(ICONV_VERSION, 'unknown') == 0)) {
292
            self::$isIconvEnabled = false;
293
294
            return false;
295
        }
296
297
        // If we reach here no problems were detected with iconv
298 62
        self::$isIconvEnabled = true;
299
300 62
        return true;
301
    }
302
303 54
    private static function buildCharacterSets()
304
    {
305 54
        if (empty(self::$controlCharacters)) {
306 52
            self::buildControlCharacters();
307
        }
308
309 54
        if (empty(self::$SYLKCharacters)) {
310 52
            self::buildSYLKCharacters();
311
        }
312 54
    }
313
314
    /**
315
     * Convert from OpenXML escaped control character to PHP control character.
316
     *
317
     * Excel 2007 team:
318
     * ----------------
319
     * That's correct, control characters are stored directly in the shared-strings table.
320
     * We do encode characters that cannot be represented in XML using the following escape sequence:
321
     * _xHHHH_ where H represents a hexadecimal character in the character's value...
322
     * So you could end up with something like _x0008_ in a string (either in a cell value (<v>)
323
     * element or in the shared string <t> element.
324
     *
325
     * @param string $value Value to unescape
326
     *
327
     * @return string
328
     */
329 9
    public static function controlCharacterOOXML2PHP($value)
330
    {
331 9
        self::buildCharacterSets();
332
333 9
        return str_replace(array_keys(self::$controlCharacters), array_values(self::$controlCharacters), $value);
334
    }
335
336
    /**
337
     * Convert from PHP control character to OpenXML escaped control character.
338
     *
339
     * Excel 2007 team:
340
     * ----------------
341
     * That's correct, control characters are stored directly in the shared-strings table.
342
     * We do encode characters that cannot be represented in XML using the following escape sequence:
343
     * _xHHHH_ where H represents a hexadecimal character in the character's value...
344
     * So you could end up with something like _x0008_ in a string (either in a cell value (<v>)
345
     * element or in the shared string <t> element.
346
     *
347
     * @param string $value Value to escape
348
     *
349
     * @return string
350
     */
351 52
    public static function controlCharacterPHP2OOXML($value)
352
    {
353 52
        self::buildCharacterSets();
354
355 52
        return str_replace(array_values(self::$controlCharacters), array_keys(self::$controlCharacters), $value);
356
    }
357
358
    /**
359
     * Try to sanitize UTF8, stripping invalid byte sequences. Not perfect. Does not surrogate characters.
360
     *
361
     * @param string $value
362
     *
363
     * @return string
364
     */
365 68
    public static function sanitizeUTF8($value)
366
    {
367 68
        if (self::getIsIconvEnabled()) {
368 68
            $value = @iconv('UTF-8', 'UTF-8', $value);
369
370 68
            return $value;
371
        }
372
373
        $value = mb_convert_encoding($value, 'UTF-8', 'UTF-8');
374
375
        return $value;
376
    }
377
378
    /**
379
     * Check if a string contains UTF8 data.
380
     *
381
     * @param string $value
382
     *
383
     * @return bool
384
     */
385
    public static function isUTF8($value)
386
    {
387
        return $value === '' || preg_match('/^./su', $value) === 1;
388
    }
389
390
    /**
391
     * Formats a numeric value as a string for output in various output writers forcing
392
     * point as decimal separator in case locale is other than English.
393
     *
394
     * @param mixed $value
395
     *
396
     * @return string
397
     */
398 60
    public static function formatNumber($value)
399
    {
400 60
        if (is_float($value)) {
401 60
            return str_replace(',', '.', $value);
402
        }
403
404 56
        return (string) $value;
405
    }
406
407
    /**
408
     * Converts a UTF-8 string into BIFF8 Unicode string data (8-bit string length)
409
     * Writes the string using uncompressed notation, no rich text, no Asian phonetics
410
     * If mbstring extension is not available, ASCII is assumed, and compressed notation is used
411
     * although this will give wrong results for non-ASCII strings
412
     * see OpenOffice.org's Documentation of the Microsoft Excel File Format, sect. 2.5.3.
413
     *
414
     * @param string $value UTF-8 encoded string
415
     * @param mixed[] $arrcRuns Details of rich text runs in $value
416
     *
417
     * @return string
418
     */
419 39
    public static function UTF8toBIFF8UnicodeShort($value, $arrcRuns = [])
420
    {
421
        // character count
422 39
        $ln = self::countCharacters($value, 'UTF-8');
423
        // option flags
424 39
        if (empty($arrcRuns)) {
425 39
            $data = pack('CC', $ln, 0x0001);
426
            // characters
427 39
            $data .= self::convertEncoding($value, 'UTF-16LE', 'UTF-8');
428
        } else {
429 9
            $data = pack('vC', $ln, 0x09);
430 9
            $data .= pack('v', count($arrcRuns));
431
            // characters
432 9
            $data .= self::convertEncoding($value, 'UTF-16LE', 'UTF-8');
433 9
            foreach ($arrcRuns as $cRun) {
434 9
                $data .= pack('v', $cRun['strlen']);
435 9
                $data .= pack('v', $cRun['fontidx']);
436
            }
437
        }
438
439 39
        return $data;
440
    }
441
442
    /**
443
     * Converts a UTF-8 string into BIFF8 Unicode string data (16-bit string length)
444
     * Writes the string using uncompressed notation, no rich text, no Asian phonetics
445
     * If mbstring extension is not available, ASCII is assumed, and compressed notation is used
446
     * although this will give wrong results for non-ASCII strings
447
     * see OpenOffice.org's Documentation of the Microsoft Excel File Format, sect. 2.5.3.
448
     *
449
     * @param string $value UTF-8 encoded string
450
     *
451
     * @return string
452
     */
453 39
    public static function UTF8toBIFF8UnicodeLong($value)
454
    {
455
        // character count
456 39
        $ln = self::countCharacters($value, 'UTF-8');
457
458
        // characters
459 39
        $chars = self::convertEncoding($value, 'UTF-16LE', 'UTF-8');
460
461 39
        $data = pack('vC', $ln, 0x0001) . $chars;
462
463 39
        return $data;
464
    }
465
466
    /**
467
     * Convert string from one encoding to another.
468
     *
469
     * @param string $value
470
     * @param string $to Encoding to convert to, e.g. 'UTF-8'
471
     * @param string $from Encoding to convert from, e.g. 'UTF-16LE'
472
     *
473
     * @return string
474
     */
475 39
    public static function convertEncoding($value, $to, $from)
476
    {
477 39
        if (self::getIsIconvEnabled()) {
478 39
            $result = iconv($from, $to . '//IGNORE//TRANSLIT', $value);
479 39
            if (false !== $result) {
480 39
                return $result;
481
            }
482
        }
483
484
        return mb_convert_encoding($value, $to, $from);
485
    }
486
487
    /**
488
     * Get character count.
489
     *
490
     * @param string $value
491
     * @param string $enc Encoding
492
     *
493
     * @return int Character count
494
     */
495 120
    public static function countCharacters($value, $enc = 'UTF-8')
496
    {
497 120
        return mb_strlen($value, $enc);
498
    }
499
500
    /**
501
     * Get a substring of a UTF-8 encoded string.
502
     *
503
     * @param string $pValue UTF-8 encoded string
504
     * @param int $pStart Start offset
505
     * @param int $pLength Maximum number of characters in substring
506
     *
507
     * @return string
508
     */
509 96
    public static function substring($pValue, $pStart, $pLength = 0)
510
    {
511 96
        return mb_substr($pValue, $pStart, $pLength, 'UTF-8');
512
    }
513
514
    /**
515
     * Convert a UTF-8 encoded string to upper case.
516
     *
517
     * @param string $pValue UTF-8 encoded string
518
     *
519
     * @return string
520
     */
521 4
    public static function strToUpper($pValue)
522
    {
523 4
        return mb_convert_case($pValue, MB_CASE_UPPER, 'UTF-8');
524
    }
525
526
    /**
527
     * Convert a UTF-8 encoded string to lower case.
528
     *
529
     * @param string $pValue UTF-8 encoded string
530
     *
531
     * @return string
532
     */
533 4
    public static function strToLower($pValue)
534
    {
535 4
        return mb_convert_case($pValue, MB_CASE_LOWER, 'UTF-8');
536
    }
537
538
    /**
539
     * Convert a UTF-8 encoded string to title/proper case
540
     * (uppercase every first character in each word, lower case all other characters).
541
     *
542
     * @param string $pValue UTF-8 encoded string
543
     *
544
     * @return string
545
     */
546 3
    public static function strToTitle($pValue)
547
    {
548 3
        return mb_convert_case($pValue, MB_CASE_TITLE, 'UTF-8');
549
    }
550
551 21
    public static function mbIsUpper($char)
552
    {
553 21
        return mb_strtolower($char, 'UTF-8') != $char;
554
    }
555
556 21
    public static function mbStrSplit($string)
557
    {
558
        // Split at all position not after the start: ^
559
        // and not before the end: $
560 21
        return preg_split('/(?<!^)(?!$)/u', $string);
561
    }
562
563
    /**
564
     * Reverse the case of a string, so that all uppercase characters become lowercase
565
     * and all lowercase characters become uppercase.
566
     *
567
     * @param string $pValue UTF-8 encoded string
568
     *
569
     * @return string
570
     */
571 21
    public static function strCaseReverse($pValue)
572
    {
573 21
        $characters = self::mbStrSplit($pValue);
574 21
        foreach ($characters as &$character) {
575 21
            if (self::mbIsUpper($character)) {
576 14
                $character = mb_strtolower($character, 'UTF-8');
577
            } else {
578 21
                $character = mb_strtoupper($character, 'UTF-8');
579
            }
580
        }
581
582 21
        return implode('', $characters);
583
    }
584
585
    /**
586
     * Identify whether a string contains a fractional numeric value,
587
     * and convert it to a numeric if it is.
588
     *
589
     * @param string &$operand string value to test
590
     *
591
     * @return bool
592
     */
593 1
    public static function convertToNumberIfFraction(&$operand)
594
    {
595 1
        if (preg_match('/^' . self::STRING_REGEXP_FRACTION . '$/i', $operand, $match)) {
596
            $sign = ($match[1] == '-') ? '-' : '+';
597
            $fractionFormula = '=' . $sign . $match[2] . $sign . $match[3];
598
            $operand = Calculation::getInstance()->_calculateFormulaValue($fractionFormula);
599
600
            return true;
601
        }
602
603 1
        return false;
604
    }
605
606
    //    function convertToNumberIfFraction()
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
607
608
    /**
609
     * Get the decimal separator. If it has not yet been set explicitly, try to obtain number
610
     * formatting information from locale.
611
     *
612
     * @return string
613
     */
614 31
    public static function getDecimalSeparator()
615
    {
616 31
        if (!isset(self::$decimalSeparator)) {
617 7
            $localeconv = localeconv();
618 7
            self::$decimalSeparator = ($localeconv['decimal_point'] != '')
619 7
                ? $localeconv['decimal_point'] : $localeconv['mon_decimal_point'];
620
621 7
            if (self::$decimalSeparator == '') {
622
                // Default to .
623
                self::$decimalSeparator = '.';
624
            }
625
        }
626
627 31
        return self::$decimalSeparator;
628
    }
629
630
    /**
631
     * Set the decimal separator. Only used by NumberFormat::toFormattedString()
632
     * to format output by \PhpOffice\PhpSpreadsheet\Writer\Html and \PhpOffice\PhpSpreadsheet\Writer\Pdf.
633
     *
634
     * @param string $pValue Character for decimal separator
635
     */
636 77
    public static function setDecimalSeparator($pValue)
637
    {
638 77
        self::$decimalSeparator = $pValue;
639 77
    }
640
641
    /**
642
     * Get the thousands separator. If it has not yet been set explicitly, try to obtain number
643
     * formatting information from locale.
644
     *
645
     * @return string
646
     */
647 39
    public static function getThousandsSeparator()
648
    {
649 39
        if (!isset(self::$thousandsSeparator)) {
650 7
            $localeconv = localeconv();
651 7
            self::$thousandsSeparator = ($localeconv['thousands_sep'] != '')
652 7
                ? $localeconv['thousands_sep'] : $localeconv['mon_thousands_sep'];
653
654 7
            if (self::$thousandsSeparator == '') {
655
                // Default to .
656
                self::$thousandsSeparator = ',';
657
            }
658
        }
659
660 39
        return self::$thousandsSeparator;
661
    }
662
663
    /**
664
     * Set the thousands separator. Only used by NumberFormat::toFormattedString()
665
     * to format output by \PhpOffice\PhpSpreadsheet\Writer\Html and \PhpOffice\PhpSpreadsheet\Writer\Pdf.
666
     *
667
     * @param string $pValue Character for thousands separator
668
     */
669 77
    public static function setThousandsSeparator($pValue)
670
    {
671 77
        self::$thousandsSeparator = $pValue;
672 77
    }
673
674
    /**
675
     *    Get the currency code. If it has not yet been set explicitly, try to obtain the
676
     *        symbol information from locale.
677
     *
678
     * @return string
679
     */
680 18
    public static function getCurrencyCode()
681
    {
682 18
        if (!empty(self::$currencyCode)) {
683 17
            return self::$currencyCode;
684
        }
685 2
        self::$currencyCode = '$';
686 2
        $localeconv = localeconv();
687 2
        if (!empty($localeconv['currency_symbol'])) {
688 2
            self::$currencyCode = $localeconv['currency_symbol'];
689
690 2
            return self::$currencyCode;
691
        }
692
        if (!empty($localeconv['int_curr_symbol'])) {
693
            self::$currencyCode = $localeconv['int_curr_symbol'];
694
695
            return self::$currencyCode;
696
        }
697
698
        return self::$currencyCode;
699
    }
700
701
    /**
702
     * Set the currency code. Only used by NumberFormat::toFormattedString()
703
     *        to format output by \PhpOffice\PhpSpreadsheet\Writer\Html and \PhpOffice\PhpSpreadsheet\Writer\Pdf.
704
     *
705
     * @param string $pValue Character for currency code
706
     */
707 41
    public static function setCurrencyCode($pValue)
708
    {
709 41
        self::$currencyCode = $pValue;
710 41
    }
711
712
    /**
713
     * Convert SYLK encoded string to UTF-8.
714
     *
715
     * @param string $pValue
716
     *
717
     * @return string UTF-8 encoded string
718
     */
719 2
    public static function SYLKtoUTF8($pValue)
720
    {
721 2
        self::buildCharacterSets();
722
723
        // If there is no escape character in the string there is nothing to do
724 2
        if (strpos($pValue, '') === false) {
725 1
            return $pValue;
726
        }
727
728 1
        foreach (self::$SYLKCharacters as $k => $v) {
729 1
            $pValue = str_replace($k, $v, $pValue);
730
        }
731
732 1
        return $pValue;
733
    }
734
735
    /**
736
     * Retrieve any leading numeric part of a string, or return the full string if no leading numeric
737
     * (handles basic integer or float, but not exponent or non decimal).
738
     *
739
     * @param string $value
740
     *
741
     * @return mixed string or only the leading numeric part of the string
742
     */
743 83
    public static function testStringAsNumeric($value)
744
    {
745 83
        if (is_numeric($value)) {
746 83
            return $value;
747
        }
748 3
        $v = (float) $value;
749
750 3
        return (is_numeric(substr($value, 0, strlen($v)))) ? $v : $value;
751
    }
752
}
753