Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.11% covered (success)
98.11%
52 / 53
90.91% covered (success)
90.91%
10 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
Text
98.11% covered (success)
98.11%
52 / 53
90.91% covered (success)
90.91%
10 / 11
37
0.00% covered (danger)
0.00%
0 / 1
 buildControlCharacters
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
5
 controlCharacterPHP2OOXML
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 numberFormat
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 chr
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
 controlCharacterOOXML2PHP
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
 isUTF8
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
3
 toUTF8
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
4
 toUnicode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 utf8ToUnicode
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
7
 unicodeToEntities
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 removeUnderscorePrefix
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3/**
4 * This file is part of PHPWord - A pure PHP library for reading and writing
5 * word processing documents.
6 *
7 * PHPWord is free software distributed under the terms of the GNU Lesser
8 * General Public License version 3 as published by the Free Software Foundation.
9 *
10 * For the full copyright and license information, please read the LICENSE
11 * file that was distributed with this source code. For the full list of
12 * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
13 *
14 * @see         https://github.com/PHPOffice/PHPWord
15 *
16 * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
17 */
18
19namespace PhpOffice\PhpWord\Shared;
20
21/**
22 * Text.
23 */
24class Text
25{
26    /**
27     * Control characters array.
28     *
29     * @var string[]
30     */
31    private static $controlCharacters = [];
32
33    /**
34     * Build control characters array.
35     */
36    private static function buildControlCharacters(): void
37    {
38        for ($i = 0; $i <= 19; ++$i) {
39            if ($i != 9 && $i != 10 && $i != 13) {
40                $find = '_x' . sprintf('%04s', strtoupper(dechex($i))) . '_';
41                $replace = chr($i);
42                self::$controlCharacters[$find] = $replace;
43            }
44        }
45    }
46
47    /**
48     * Convert from PHP control character to OpenXML escaped control character.
49     *
50     * Excel 2007 team:
51     * ----------------
52     * That's correct, control characters are stored directly in the shared-strings table.
53     * We do encode characters that cannot be represented in XML using the following escape sequence:
54     * _xHHHH_ where H represents a hexadecimal character in the character's value...
55     * So you could end up with something like _x0008_ in a string (either in a cell value (<v>)
56     * element or in the shared string <t> element.
57     *
58     * @param  string $value Value to escape
59     *
60     * @return string
61     */
62    public static function controlCharacterPHP2OOXML($value = '')
63    {
64        if (empty(self::$controlCharacters)) {
65            self::buildControlCharacters();
66        }
67
68        return str_replace(array_values(self::$controlCharacters), array_keys(self::$controlCharacters), $value);
69    }
70
71    /**
72     * Return a number formatted for being integrated in xml files.
73     *
74     * @param float $number
75     * @param int $decimals
76     *
77     * @return string
78     */
79    public static function numberFormat($number, $decimals)
80    {
81        return number_format($number, $decimals, '.', '');
82    }
83
84    /**
85     * @param int $dec
86     *
87     * @see http://stackoverflow.com/a/7153133/2235790
88     *
89     * @author velcrow
90     *
91     * @return string
92     */
93    public static function chr($dec)
94    {
95        if ($dec <= 0x7F) {
96            return chr($dec);
97        }
98        if ($dec <= 0x7FF) {
99            return chr(($dec >> 6) + 192) . chr(($dec & 63) + 128);
100        }
101        if ($dec <= 0xFFFF) {
102            return chr(($dec >> 12) + 224) . chr((($dec >> 6) & 63) + 128) . chr(($dec & 63) + 128);
103        }
104        if ($dec <= 0x1FFFFF) {
105            return chr(($dec >> 18) + 240) . chr((($dec >> 12) & 63) + 128) . chr((($dec >> 6) & 63) + 128) . chr(($dec & 63) + 128);
106        }
107
108        return '';
109    }
110
111    /**
112     * Convert from OpenXML escaped control character to PHP control character.
113     *
114     * @param string $value Value to unescape
115     *
116     * @return string
117     */
118    public static function controlCharacterOOXML2PHP($value = '')
119    {
120        if (empty(self::$controlCharacters)) {
121            self::buildControlCharacters();
122        }
123
124        return str_replace(array_keys(self::$controlCharacters), array_values(self::$controlCharacters), $value);
125    }
126
127    /**
128     * Check if a string contains UTF-8 data.
129     *
130     * @param string $value
131     *
132     * @return bool
133     */
134    public static function isUTF8($value = '')
135    {
136        return is_string($value) && ($value === '' || preg_match('/^./su', $value) == 1);
137    }
138
139    /**
140     * Return UTF8 encoded value.
141     *
142     * @param null|string $value
143     *
144     * @return ?string
145     */
146    public static function toUTF8($value = '')
147    {
148        if (null !== $value && !self::isUTF8($value)) {
149            // PHP8.2 : utf8_encode is deprecated, but mb_convert_encoding always usable
150            $value = (function_exists('mb_convert_encoding')) ? mb_convert_encoding($value, 'UTF-8', 'ISO-8859-1') : utf8_encode($value);
151        }
152
153        return $value;
154    }
155
156    /**
157     * Returns unicode from UTF8 text.
158     *
159     * The function is splitted to reduce cyclomatic complexity
160     *
161     * @param string $text UTF8 text
162     *
163     * @return string Unicode text
164     *
165     * @since 0.11.0
166     */
167    public static function toUnicode($text)
168    {
169        return self::unicodeToEntities(self::utf8ToUnicode($text));
170    }
171
172    /**
173     * Returns unicode array from UTF8 text.
174     *
175     * @param string $text UTF8 text
176     *
177     * @return array
178     *
179     * @since 0.11.0
180     * @see http://www.randomchaos.com/documents/?source=php_and_unicode
181     */
182    public static function utf8ToUnicode($text)
183    {
184        $unicode = [];
185        $values = [];
186        $lookingFor = 1;
187
188        // Gets unicode for each character
189        for ($i = 0; $i < strlen($text); ++$i) {
190            $thisValue = ord($text[$i]);
191            if ($thisValue < 128) {
192                $unicode[] = $thisValue;
193            } else {
194                if (count($values) == 0) {
195                    $lookingFor = $thisValue < 224 ? 2 : 3;
196                }
197                $values[] = $thisValue;
198                if (count($values) == $lookingFor) {
199                    if ($lookingFor == 3) {
200                        $number = (($values[0] % 16) * 4096) + (($values[1] % 64) * 64) + ($values[2] % 64);
201                    } else {
202                        $number = (($values[0] % 32) * 64) + ($values[1] % 64);
203                    }
204                    $unicode[] = $number;
205                    $values = [];
206                    $lookingFor = 1;
207                }
208            }
209        }
210
211        return $unicode;
212    }
213
214    /**
215     * Returns entites from unicode array.
216     *
217     * @param array $unicode
218     *
219     * @return string
220     *
221     * @since 0.11.0
222     * @see http://www.randomchaos.com/documents/?source=php_and_unicode
223     */
224    private static function unicodeToEntities($unicode)
225    {
226        $entities = '';
227
228        foreach ($unicode as $value) {
229            if ($value != 65279) {
230                $entities .= $value > 127 ? '\uc0{\u' . $value . '}' : chr($value);
231            }
232        }
233
234        return $entities;
235    }
236
237    /**
238     * Return name without underscore for < 0.10.0 variable name compatibility.
239     *
240     * @param string $value
241     *
242     * @return string
243     */
244    public static function removeUnderscorePrefix($value)
245    {
246        if (null !== $value) {
247            if (substr($value, 0, 1) == '_') {
248                $value = substr($value, 1);
249            }
250        }
251
252        return $value;
253    }
254}