Completed
Push — develop ( c96e2d...d2f55f )
by Adrien
48:43 queued 44:11
created

StringHelper::buildSYLKCharacters()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 159
Code Lines 157

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 157
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 157
nc 1
nop 0
dl 0
loc 159
ccs 157
cts 158
cp 0.9937
crap 1
rs 8.2857
c 0
b 0
f 0

How to fix   Long Method   

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\Calculation;
6
7
class StringHelper
8
{
9
    /**    Constants                */
10
    /**    Regular Expressions        */
11
    //    Fraction
12
    const STRING_REGEXP_FRACTION = '(-?)(\d+)\s+(\d+\/\d+)';
13
14
    /**
15
     * Control characters array.
16
     *
17
     * @var string[]
18
     */
19
    private static $controlCharacters = [];
20
21
    /**
22
     * SYLK Characters array.
23
     *
24
     * @var array
25
     */
26
    private static $SYLKCharacters = [];
27
28
    /**
29
     * Decimal separator.
30
     *
31
     * @var string
32
     */
33
    private static $decimalSeparator;
34
35
    /**
36
     * Thousands separator.
37
     *
38
     * @var string
39
     */
40
    private static $thousandsSeparator;
41
42
    /**
43
     * Currency code.
44
     *
45
     * @var string
46
     */
47
    private static $currencyCode;
48
49
    /**
50
     * Is iconv extension avalable?
51
     *
52
     * @var bool
53
     */
54
    private static $isIconvEnabled;
55
56
    /**
57
     * Build control characters array.
58
     */
59 55
    private static function buildControlCharacters()
60
    {
61 55
        for ($i = 0; $i <= 31; ++$i) {
62 55
            if ($i != 9 && $i != 10 && $i != 13) {
63 55
                $find = '_x' . sprintf('%04s', strtoupper(dechex($i))) . '_';
64 55
                $replace = chr($i);
65 55
                self::$controlCharacters[$find] = $replace;
66
            }
67
        }
68 55
    }
69
70
    /**
71
     * Build SYLK characters array.
72
     */
73 55
    private static function buildSYLKCharacters()
74
    {
75
        self::$SYLKCharacters = [
76 55
            "\x1B 0" => chr(0),
77 55
            "\x1B 1" => chr(1),
78 55
            "\x1B 2" => chr(2),
79 55
            "\x1B 3" => chr(3),
80 55
            "\x1B 4" => chr(4),
81 55
            "\x1B 5" => chr(5),
82 55
            "\x1B 6" => chr(6),
83 55
            "\x1B 7" => chr(7),
84 55
            "\x1B 8" => chr(8),
85 55
            "\x1B 9" => chr(9),
86 55
            "\x1B :" => chr(10),
87 55
            "\x1B ;" => chr(11),
88 55
            "\x1B <" => chr(12),
89 55
            "\x1B =" => chr(13),
90 55
            "\x1B >" => chr(14),
91 55
            "\x1B ?" => chr(15),
92 55
            "\x1B!0" => chr(16),
93 55
            "\x1B!1" => chr(17),
94 55
            "\x1B!2" => chr(18),
95 55
            "\x1B!3" => chr(19),
96 55
            "\x1B!4" => chr(20),
97 55
            "\x1B!5" => chr(21),
98 55
            "\x1B!6" => chr(22),
99 55
            "\x1B!7" => chr(23),
100 55
            "\x1B!8" => chr(24),
101 55
            "\x1B!9" => chr(25),
102 55
            "\x1B!:" => chr(26),
103 55
            "\x1B!;" => chr(27),
104 55
            "\x1B!<" => chr(28),
105 55
            "\x1B!=" => chr(29),
106 55
            "\x1B!>" => chr(30),
107 55
            "\x1B!?" => chr(31),
108 55
            "\x1B'?" => chr(127),
109 55
            "\x1B(0" => '€', // 128 in CP1252
110 55
            "\x1B(2" => '‚', // 130 in CP1252
111 55
            "\x1B(3" => 'ƒ', // 131 in CP1252
112 55
            "\x1B(4" => '„', // 132 in CP1252
113 55
            "\x1B(5" => '…', // 133 in CP1252
114 55
            "\x1B(6" => '†', // 134 in CP1252
115 55
            "\x1B(7" => '‡', // 135 in CP1252
116 55
            "\x1B(8" => 'ˆ', // 136 in CP1252
117 55
            "\x1B(9" => '‰', // 137 in CP1252
118 55
            "\x1B(:" => 'Š', // 138 in CP1252
119 55
            "\x1B(;" => '‹', // 139 in CP1252
120 55
            "\x1BNj" => 'Œ', // 140 in CP1252
121 55
            "\x1B(>" => 'Ž', // 142 in CP1252
122 55
            "\x1B)1" => '‘', // 145 in CP1252
123 55
            "\x1B)2" => '’', // 146 in CP1252
124 55
            "\x1B)3" => '“', // 147 in CP1252
125 55
            "\x1B)4" => '”', // 148 in CP1252
126 55
            "\x1B)5" => '•', // 149 in CP1252
127 55
            "\x1B)6" => '–', // 150 in CP1252
128 55
            "\x1B)7" => '—', // 151 in CP1252
129 55
            "\x1B)8" => '˜', // 152 in CP1252
130 55
            "\x1B)9" => '™', // 153 in CP1252
131 55
            "\x1B):" => 'š', // 154 in CP1252
132 55
            "\x1B);" => '›', // 155 in CP1252
133 55
            "\x1BNz" => 'œ', // 156 in CP1252
134 55
            "\x1B)>" => 'ž', // 158 in CP1252
135 55
            "\x1B)?" => 'Ÿ', // 159 in CP1252
136 55
            "\x1B*0" => ' ', // 160 in CP1252
137 55
            "\x1BN!" => '¡', // 161 in CP1252
138 55
            "\x1BN\"" => '¢', // 162 in CP1252
139 55
            "\x1BN#" => '£', // 163 in CP1252
140 55
            "\x1BN(" => '¤', // 164 in CP1252
141 55
            "\x1BN%" => '¥', // 165 in CP1252
142 55
            "\x1B*6" => '¦', // 166 in CP1252
143 55
            "\x1BN'" => '§', // 167 in CP1252
144 55
            "\x1BNH " => '¨', // 168 in CP1252
145 55
            "\x1BNS" => '©', // 169 in CP1252
146 55
            "\x1BNc" => 'ª', // 170 in CP1252
147 55
            "\x1BN+" => '«', // 171 in CP1252
148 55
            "\x1B*<" => '¬', // 172 in CP1252
149 55
            "\x1B*=" => '­', // 173 in CP1252
150 55
            "\x1BNR" => '®', // 174 in CP1252
151 55
            "\x1B*?" => '¯', // 175 in CP1252
152 55
            "\x1BN0" => '°', // 176 in CP1252
153 55
            "\x1BN1" => '±', // 177 in CP1252
154 55
            "\x1BN2" => '²', // 178 in CP1252
155 55
            "\x1BN3" => '³', // 179 in CP1252
156 55
            "\x1BNB " => '´', // 180 in CP1252
157 55
            "\x1BN5" => 'µ', // 181 in CP1252
158 55
            "\x1BN6" => '¶', // 182 in CP1252
159 55
            "\x1BN7" => '·', // 183 in CP1252
160 55
            "\x1B+8" => '¸', // 184 in CP1252
161 55
            "\x1BNQ" => '¹', // 185 in CP1252
162 55
            "\x1BNk" => 'º', // 186 in CP1252
163 55
            "\x1BN;" => '»', // 187 in CP1252
164 55
            "\x1BN<" => '¼', // 188 in CP1252
165 55
            "\x1BN=" => '½', // 189 in CP1252
166 55
            "\x1BN>" => '¾', // 190 in CP1252
167 55
            "\x1BN?" => '¿', // 191 in CP1252
168 55
            "\x1BNAA" => 'À', // 192 in CP1252
169 55
            "\x1BNBA" => 'Á', // 193 in CP1252
170 55
            "\x1BNCA" => 'Â', // 194 in CP1252
171 55
            "\x1BNDA" => 'Ã', // 195 in CP1252
172 55
            "\x1BNHA" => 'Ä', // 196 in CP1252
173 55
            "\x1BNJA" => 'Å', // 197 in CP1252
174 55
            "\x1BNa" => 'Æ', // 198 in CP1252
175 55
            "\x1BNKC" => 'Ç', // 199 in CP1252
176 55
            "\x1BNAE" => 'È', // 200 in CP1252
177 55
            "\x1BNBE" => 'É', // 201 in CP1252
178 55
            "\x1BNCE" => 'Ê', // 202 in CP1252
179 55
            "\x1BNHE" => 'Ë', // 203 in CP1252
180 55
            "\x1BNAI" => 'Ì', // 204 in CP1252
181 55
            "\x1BNBI" => 'Í', // 205 in CP1252
182 55
            "\x1BNCI" => 'Î', // 206 in CP1252
183 55
            "\x1BNHI" => 'Ï', // 207 in CP1252
184 55
            "\x1BNb" => 'Ð', // 208 in CP1252
185 55
            "\x1BNDN" => 'Ñ', // 209 in CP1252
186 55
            "\x1BNAO" => 'Ò', // 210 in CP1252
187 55
            "\x1BNBO" => 'Ó', // 211 in CP1252
188 55
            "\x1BNCO" => 'Ô', // 212 in CP1252
189 55
            "\x1BNDO" => 'Õ', // 213 in CP1252
190 55
            "\x1BNHO" => 'Ö', // 214 in CP1252
191 55
            "\x1B-7" => '×', // 215 in CP1252
192 55
            "\x1BNi" => 'Ø', // 216 in CP1252
193 55
            "\x1BNAU" => 'Ù', // 217 in CP1252
194 55
            "\x1BNBU" => 'Ú', // 218 in CP1252
195 55
            "\x1BNCU" => 'Û', // 219 in CP1252
196 55
            "\x1BNHU" => 'Ü', // 220 in CP1252
197 55
            "\x1B-=" => 'Ý', // 221 in CP1252
198 55
            "\x1BNl" => 'Þ', // 222 in CP1252
199 55
            "\x1BN{" => 'ß', // 223 in CP1252
200 55
            "\x1BNAa" => 'à', // 224 in CP1252
201 55
            "\x1BNBa" => 'á', // 225 in CP1252
202 55
            "\x1BNCa" => 'â', // 226 in CP1252
203 55
            "\x1BNDa" => 'ã', // 227 in CP1252
204 55
            "\x1BNHa" => 'ä', // 228 in CP1252
205 55
            "\x1BNJa" => 'å', // 229 in CP1252
206 55
            "\x1BNq" => 'æ', // 230 in CP1252
207 55
            "\x1BNKc" => 'ç', // 231 in CP1252
208 55
            "\x1BNAe" => 'è', // 232 in CP1252
209 55
            "\x1BNBe" => 'é', // 233 in CP1252
210 55
            "\x1BNCe" => 'ê', // 234 in CP1252
211 55
            "\x1BNHe" => 'ë', // 235 in CP1252
212 55
            "\x1BNAi" => 'ì', // 236 in CP1252
213 55
            "\x1BNBi" => 'í', // 237 in CP1252
214 55
            "\x1BNCi" => 'î', // 238 in CP1252
215 55
            "\x1BNHi" => 'ï', // 239 in CP1252
216 55
            "\x1BNs" => 'ð', // 240 in CP1252
217 55
            "\x1BNDn" => 'ñ', // 241 in CP1252
218 55
            "\x1BNAo" => 'ò', // 242 in CP1252
219 55
            "\x1BNBo" => 'ó', // 243 in CP1252
220 55
            "\x1BNCo" => 'ô', // 244 in CP1252
221 55
            "\x1BNDo" => 'õ', // 245 in CP1252
222 55
            "\x1BNHo" => 'ö', // 246 in CP1252
223 55
            "\x1B/7" => '÷', // 247 in CP1252
224 55
            "\x1BNy" => 'ø', // 248 in CP1252
225 55
            "\x1BNAu" => 'ù', // 249 in CP1252
226 55
            "\x1BNBu" => 'ú', // 250 in CP1252
227 55
            "\x1BNCu" => 'û', // 251 in CP1252
228 55
            "\x1BNHu" => 'ü', // 252 in CP1252
229 55
            "\x1B/=" => 'ý', // 253 in CP1252
230 55
            "\x1BN|" => 'þ', // 254 in CP1252
231 55
            "\x1BNHy" => 'ÿ', // 255 in CP1252
232
        ];
233 55
    }
234
235
    /**
236
     * Get whether iconv extension is available.
237
     *
238
     * @return bool
239
     */
240 133
    public static function getIsIconvEnabled()
241
    {
242 133
        if (isset(self::$isIconvEnabled)) {
243 132
            return self::$isIconvEnabled;
244
        }
245
246
        // Fail if iconv doesn't exist
247 96
        if (!function_exists('iconv')) {
248
            self::$isIconvEnabled = false;
249
250
            return false;
251
        }
252
253
        // Sometimes iconv is not working, and e.g. iconv('UTF-8', 'UTF-16LE', 'x') just returns false,
254 96
        if (!@iconv('UTF-8', 'UTF-16LE', 'x')) {
255
            self::$isIconvEnabled = false;
256
257
            return false;
258
        }
259
260
        // 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...
261
        // we cannot use iconv in that case either (http://bugs.php.net/bug.php?id=37773)
262 96
        if (!@iconv_substr('A', 0, 1, 'UTF-8')) {
263
            self::$isIconvEnabled = false;
264
265
            return false;
266
        }
267
268
        // CUSTOM: IBM AIX iconv() does not work
269 96
        if (defined('PHP_OS') && @stristr(PHP_OS, 'AIX') && defined('ICONV_IMPL') && (@strcasecmp(ICONV_IMPL, 'unknown') == 0) && defined('ICONV_VERSION') && (@strcasecmp(ICONV_VERSION, 'unknown') == 0)) {
270
            self::$isIconvEnabled = false;
271
272
            return false;
273
        }
274
275
        // If we reach here no problems were detected with iconv
276 96
        self::$isIconvEnabled = true;
277
278 96
        return true;
279
    }
280
281 58
    private static function buildCharacterSets()
282
    {
283 58
        if (empty(self::$controlCharacters)) {
284 55
            self::buildControlCharacters();
285
        }
286
287 58
        if (empty(self::$SYLKCharacters)) {
288 55
            self::buildSYLKCharacters();
289
        }
290 58
    }
291
292
    /**
293
     * Convert from OpenXML escaped control character to PHP control character.
294
     *
295
     * Excel 2007 team:
296
     * ----------------
297
     * That's correct, control characters are stored directly in the shared-strings table.
298
     * We do encode characters that cannot be represented in XML using the following escape sequence:
299
     * _xHHHH_ where H represents a hexadecimal character in the character's value...
300
     * So you could end up with something like _x0008_ in a string (either in a cell value (<v>)
301
     * element or in the shared string <t> element.
302
     *
303
     * @param string $value Value to unescape
304
     *
305
     * @return string
306
     */
307 13
    public static function controlCharacterOOXML2PHP($value)
308
    {
309 13
        self::buildCharacterSets();
310
311 13
        return str_replace(array_keys(self::$controlCharacters), array_values(self::$controlCharacters), $value);
312
    }
313
314
    /**
315
     * Convert from PHP control character to OpenXML escaped 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 escape
326
     *
327
     * @return string
328
     */
329 53
    public static function controlCharacterPHP2OOXML($value)
330
    {
331 53
        self::buildCharacterSets();
332
333 53
        return str_replace(array_values(self::$controlCharacters), array_keys(self::$controlCharacters), $value);
334
    }
335
336
    /**
337
     * Try to sanitize UTF8, stripping invalid byte sequences. Not perfect. Does not surrogate characters.
338
     *
339
     * @param string $value
340
     *
341
     * @return string
342
     */
343 104
    public static function sanitizeUTF8($value)
344
    {
345 104
        if (self::getIsIconvEnabled()) {
346 104
            $value = @iconv('UTF-8', 'UTF-8', $value);
347
348 104
            return $value;
349
        }
350
351
        $value = mb_convert_encoding($value, 'UTF-8', 'UTF-8');
352
353
        return $value;
354
    }
355
356
    /**
357
     * Check if a string contains UTF8 data.
358
     *
359
     * @param string $value
360
     *
361
     * @return bool
362
     */
363
    public static function isUTF8($value)
364
    {
365
        return $value === '' || preg_match('/^./su', $value) === 1;
366
    }
367
368
    /**
369
     * Formats a numeric value as a string for output in various output writers forcing
370
     * point as decimal separator in case locale is other than English.
371
     *
372
     * @param mixed $value
373
     *
374
     * @return string
375
     */
376 71
    public static function formatNumber($value)
377
    {
378 71
        if (is_float($value)) {
379 71
            return str_replace(',', '.', $value);
380
        }
381
382 60
        return (string) $value;
383
    }
384
385
    /**
386
     * Converts a UTF-8 string into BIFF8 Unicode string data (8-bit string length)
387
     * Writes the string using uncompressed notation, no rich text, no Asian phonetics
388
     * If mbstring extension is not available, ASCII is assumed, and compressed notation is used
389
     * although this will give wrong results for non-ASCII strings
390
     * see OpenOffice.org's Documentation of the Microsoft Excel File Format, sect. 2.5.3.
391
     *
392
     * @param string $value UTF-8 encoded string
393
     * @param mixed[] $arrcRuns Details of rich text runs in $value
394
     *
395
     * @return string
396
     */
397 42
    public static function UTF8toBIFF8UnicodeShort($value, $arrcRuns = [])
398
    {
399
        // character count
400 42
        $ln = self::countCharacters($value, 'UTF-8');
401
        // option flags
402 42
        if (empty($arrcRuns)) {
403 42
            $data = pack('CC', $ln, 0x0001);
404
            // characters
405 42
            $data .= self::convertEncoding($value, 'UTF-16LE', 'UTF-8');
406
        } else {
407 9
            $data = pack('vC', $ln, 0x09);
408 9
            $data .= pack('v', count($arrcRuns));
409
            // characters
410 9
            $data .= self::convertEncoding($value, 'UTF-16LE', 'UTF-8');
411 9
            foreach ($arrcRuns as $cRun) {
412 9
                $data .= pack('v', $cRun['strlen']);
413 9
                $data .= pack('v', $cRun['fontidx']);
414
            }
415
        }
416
417 42
        return $data;
418
    }
419
420
    /**
421
     * Converts a UTF-8 string into BIFF8 Unicode string data (16-bit string length)
422
     * Writes the string using uncompressed notation, no rich text, no Asian phonetics
423
     * If mbstring extension is not available, ASCII is assumed, and compressed notation is used
424
     * although this will give wrong results for non-ASCII strings
425
     * see OpenOffice.org's Documentation of the Microsoft Excel File Format, sect. 2.5.3.
426
     *
427
     * @param string $value UTF-8 encoded string
428
     *
429
     * @return string
430
     */
431 42
    public static function UTF8toBIFF8UnicodeLong($value)
432
    {
433
        // character count
434 42
        $ln = self::countCharacters($value, 'UTF-8');
435
436
        // characters
437 42
        $chars = self::convertEncoding($value, 'UTF-16LE', 'UTF-8');
438
439 42
        $data = pack('vC', $ln, 0x0001) . $chars;
440
441 42
        return $data;
442
    }
443
444
    /**
445
     * Convert string from one encoding to another.
446
     *
447
     * @param string $value
448
     * @param string $to Encoding to convert to, e.g. 'UTF-8'
449
     * @param string $from Encoding to convert from, e.g. 'UTF-16LE'
450
     *
451
     * @return string
452
     */
453 59
    public static function convertEncoding($value, $to, $from)
454
    {
455 59
        if (self::getIsIconvEnabled()) {
456 59
            $result = iconv($from, $to . '//IGNORE//TRANSLIT', $value);
457 59
            if (false !== $result) {
0 ignored issues
show
introduced by
The condition false !== $result can never be false.
Loading history...
458 59
                return $result;
459
            }
460
        }
461
462
        return mb_convert_encoding($value, $to, $from);
463
    }
464
465
    /**
466
     * Get character count.
467
     *
468
     * @param string $value
469
     * @param string $enc Encoding
470
     *
471
     * @return int Character count
472
     */
473 198
    public static function countCharacters($value, $enc = 'UTF-8')
474
    {
475 198
        return mb_strlen($value, $enc);
476
    }
477
478
    /**
479
     * Get a substring of a UTF-8 encoded string.
480
     *
481
     * @param string $pValue UTF-8 encoded string
482
     * @param int $pStart Start offset
483
     * @param int $pLength Maximum number of characters in substring
484
     *
485
     * @return string
486
     */
487 174
    public static function substring($pValue, $pStart, $pLength = 0)
488
    {
489 174
        return mb_substr($pValue, $pStart, $pLength, 'UTF-8');
490
    }
491
492
    /**
493
     * Convert a UTF-8 encoded string to upper case.
494
     *
495
     * @param string $pValue UTF-8 encoded string
496
     *
497
     * @return string
498
     */
499 4
    public static function strToUpper($pValue)
500
    {
501 4
        return mb_convert_case($pValue, MB_CASE_UPPER, 'UTF-8');
502
    }
503
504
    /**
505
     * Convert a UTF-8 encoded string to lower case.
506
     *
507
     * @param string $pValue UTF-8 encoded string
508
     *
509
     * @return string
510
     */
511 4
    public static function strToLower($pValue)
512
    {
513 4
        return mb_convert_case($pValue, MB_CASE_LOWER, 'UTF-8');
514
    }
515
516
    /**
517
     * Convert a UTF-8 encoded string to title/proper case
518
     * (uppercase every first character in each word, lower case all other characters).
519
     *
520
     * @param string $pValue UTF-8 encoded string
521
     *
522
     * @return string
523
     */
524 3
    public static function strToTitle($pValue)
525
    {
526 3
        return mb_convert_case($pValue, MB_CASE_TITLE, 'UTF-8');
527
    }
528
529 21
    public static function mbIsUpper($char)
530
    {
531 21
        return mb_strtolower($char, 'UTF-8') != $char;
532
    }
533
534 21
    public static function mbStrSplit($string)
535
    {
536
        // Split at all position not after the start: ^
537
        // and not before the end: $
538 21
        return preg_split('/(?<!^)(?!$)/u', $string);
539
    }
540
541
    /**
542
     * Reverse the case of a string, so that all uppercase characters become lowercase
543
     * and all lowercase characters become uppercase.
544
     *
545
     * @param string $pValue UTF-8 encoded string
546
     *
547
     * @return string
548
     */
549 21
    public static function strCaseReverse($pValue)
550
    {
551 21
        $characters = self::mbStrSplit($pValue);
552 21
        foreach ($characters as &$character) {
553 21
            if (self::mbIsUpper($character)) {
554 14
                $character = mb_strtolower($character, 'UTF-8');
555
            } else {
556 21
                $character = mb_strtoupper($character, 'UTF-8');
557
            }
558
        }
559
560 21
        return implode('', $characters);
561
    }
562
563
    /**
564
     * Identify whether a string contains a fractional numeric value,
565
     * and convert it to a numeric if it is.
566
     *
567
     * @param string &$operand string value to test
568
     *
569
     * @return bool
570
     */
571 2
    public static function convertToNumberIfFraction(&$operand)
572
    {
573 2
        if (preg_match('/^' . self::STRING_REGEXP_FRACTION . '$/i', $operand, $match)) {
574
            $sign = ($match[1] == '-') ? '-' : '+';
575
            $fractionFormula = '=' . $sign . $match[2] . $sign . $match[3];
576
            $operand = Calculation::getInstance()->_calculateFormulaValue($fractionFormula);
577
578
            return true;
579
        }
580
581 2
        return false;
582
    }
583
584
    //    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...
585
586
    /**
587
     * Get the decimal separator. If it has not yet been set explicitly, try to obtain number
588
     * formatting information from locale.
589
     *
590
     * @return string
591
     */
592 36
    public static function getDecimalSeparator()
593
    {
594 36
        if (!isset(self::$decimalSeparator)) {
595 12
            $localeconv = localeconv();
596 12
            self::$decimalSeparator = ($localeconv['decimal_point'] != '')
597 12
                ? $localeconv['decimal_point'] : $localeconv['mon_decimal_point'];
598
599 12
            if (self::$decimalSeparator == '') {
600
                // Default to .
601
                self::$decimalSeparator = '.';
602
            }
603
        }
604
605 36
        return self::$decimalSeparator;
606
    }
607
608
    /**
609
     * Set the decimal separator. Only used by NumberFormat::toFormattedString()
610
     * to format output by \PhpOffice\PhpSpreadsheet\Writer\Html and \PhpOffice\PhpSpreadsheet\Writer\Pdf.
611
     *
612
     * @param string $pValue Character for decimal separator
613
     */
614 77
    public static function setDecimalSeparator($pValue)
615
    {
616 77
        self::$decimalSeparator = $pValue;
617 77
    }
618
619
    /**
620
     * Get the thousands separator. If it has not yet been set explicitly, try to obtain number
621
     * formatting information from locale.
622
     *
623
     * @return string
624
     */
625 44
    public static function getThousandsSeparator()
626
    {
627 44
        if (!isset(self::$thousandsSeparator)) {
628 12
            $localeconv = localeconv();
629 12
            self::$thousandsSeparator = ($localeconv['thousands_sep'] != '')
630 12
                ? $localeconv['thousands_sep'] : $localeconv['mon_thousands_sep'];
631
632 12
            if (self::$thousandsSeparator == '') {
633
                // Default to .
634
                self::$thousandsSeparator = ',';
635
            }
636
        }
637
638 44
        return self::$thousandsSeparator;
639
    }
640
641
    /**
642
     * Set the thousands separator. Only used by NumberFormat::toFormattedString()
643
     * to format output by \PhpOffice\PhpSpreadsheet\Writer\Html and \PhpOffice\PhpSpreadsheet\Writer\Pdf.
644
     *
645
     * @param string $pValue Character for thousands separator
646
     */
647 77
    public static function setThousandsSeparator($pValue)
648
    {
649 77
        self::$thousandsSeparator = $pValue;
650 77
    }
651
652
    /**
653
     *    Get the currency code. If it has not yet been set explicitly, try to obtain the
654
     *        symbol information from locale.
655
     *
656
     * @return string
657
     */
658 19
    public static function getCurrencyCode()
659
    {
660 19
        if (!empty(self::$currencyCode)) {
661 18
            return self::$currencyCode;
662
        }
663 3
        self::$currencyCode = '$';
664 3
        $localeconv = localeconv();
665 3
        if (!empty($localeconv['currency_symbol'])) {
666 3
            self::$currencyCode = $localeconv['currency_symbol'];
667
668 3
            return self::$currencyCode;
669
        }
670
        if (!empty($localeconv['int_curr_symbol'])) {
671
            self::$currencyCode = $localeconv['int_curr_symbol'];
672
673
            return self::$currencyCode;
674
        }
675
676
        return self::$currencyCode;
677
    }
678
679
    /**
680
     * Set the currency code. Only used by NumberFormat::toFormattedString()
681
     *        to format output by \PhpOffice\PhpSpreadsheet\Writer\Html and \PhpOffice\PhpSpreadsheet\Writer\Pdf.
682
     *
683
     * @param string $pValue Character for currency code
684
     */
685 41
    public static function setCurrencyCode($pValue)
686
    {
687 41
        self::$currencyCode = $pValue;
688 41
    }
689
690
    /**
691
     * Convert SYLK encoded string to UTF-8.
692
     *
693
     * @param string $pValue
694
     *
695
     * @return string UTF-8 encoded string
696
     */
697 2
    public static function SYLKtoUTF8($pValue)
698
    {
699 2
        self::buildCharacterSets();
700
701
        // If there is no escape character in the string there is nothing to do
702 2
        if (strpos($pValue, '') === false) {
703 1
            return $pValue;
704
        }
705
706 1
        foreach (self::$SYLKCharacters as $k => $v) {
707 1
            $pValue = str_replace($k, $v, $pValue);
708
        }
709
710 1
        return $pValue;
711
    }
712
713
    /**
714
     * Retrieve any leading numeric part of a string, or return the full string if no leading numeric
715
     * (handles basic integer or float, but not exponent or non decimal).
716
     *
717
     * @param string $value
718
     *
719
     * @return mixed string or only the leading numeric part of the string
720
     */
721 84
    public static function testStringAsNumeric($value)
722
    {
723 84
        if (is_numeric($value)) {
724 84
            return $value;
725
        }
726 3
        $v = (float) $value;
727
728 3
        return (is_numeric(substr($value, 0, strlen($v)))) ? $v : $value;
729
    }
730
}
731