Completed
Push — develop ( 8fd182...67581a )
by Adrien
20:40 queued 11:47
created

StringHelper::controlCharacterOOXML2PHP()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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