• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PHPOffice / PHPWord / 29783978122

20 Jul 2026 10:27PM UTC coverage: 98.684% (+1.9%) from 96.738%
29783978122

Pull #2567

github

web-flow
Merge f64cfee48 into 5579bd257
Pull Request #2567: WIP Do Not Install

15594 of 15802 relevant lines covered (98.68%)

55.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.57
/src/PhpWord/Shared/Text.php
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

19
namespace PhpOffice\PhpWord\Shared;
20

21
use PhpOffice\PhpWord\Exception\Exception as WordException;
22

23
class Text
24
{
25
    /**
26
     * Control characters array.
27
     *
28
     * @var string[]
29
     */
30
    private static $controlCharacters = [];
31

32
    /**
33
     * Build control characters array.
34
     */
35
    private static function buildControlCharacters(): void
153✔
36
    {
37
        if (!empty(self::$controlCharacters)) {
153✔
38
            return;
148✔
39
        }
40
        for ($i = 0; $i <= 19; ++$i) {
43✔
41
            if ($i != 9 && $i != 10 && $i != 13) {
43✔
42
                $find = '_x' . sprintf('%04s', strtoupper(dechex($i))) . '_';
43✔
43
                $replace = chr($i);
43✔
44
                self::$controlCharacters[$find] = $replace;
43✔
45
            }
46
        }
47
    }
48

49
    /**
50
     * Convert from PHP control character to OpenXML escaped control character.
51
     *
52
     * Excel 2007 team:
53
     * ----------------
54
     * That's correct, control characters are stored directly in the shared-strings table.
55
     * We do encode characters that cannot be represented in XML using the following escape sequence:
56
     * _xHHHH_ where H represents a hexadecimal character in the character's value...
57
     * So you could end up with something like _x0008_ in a string (either in a cell value (<v>)
58
     * element or in the shared string <t> element.
59
     *
60
     * @param  string $value Value to escape
61
     *
62
     * @return string
63
     */
64
    public static function controlCharacterPHP2OOXML($value = '')
153✔
65
    {
66
        self::buildControlCharacters();
153✔
67

68
        return str_replace(array_values(self::$controlCharacters), array_keys(self::$controlCharacters), $value);
153✔
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)
1✔
80
    {
81
        return number_format($number, $decimals, '.', '');
1✔
82
    }
83

84
    /**
85
     * @param non-negative-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)
1✔
94
    {
95
        if ($dec < 0) {
1✔
96
            return '';
×
97
        }
98
        if ($dec <= 0x7F) {
1✔
99
            return chr($dec);
1✔
100
        }
101
        if ($dec <= 0x7FF) {
1✔
102
            return chr(($dec >> 6) + 192) . chr(($dec & 63) + 128);
1✔
103
        }
104
        if ($dec <= 0xFFFF) {
1✔
105
            return chr(($dec >> 12) + 224) . chr((($dec >> 6) & 63) + 128) . chr(($dec & 63) + 128);
1✔
106
        }
107
        if ($dec <= 0x1FFFFF) {
1✔
108
            return chr(($dec >> 18) + 240) . chr((($dec >> 12) & 63) + 128) . chr((($dec >> 6) & 63) + 128) . chr(($dec & 63) + 128);
1✔
109
        }
110

111
        return '';
1✔
112
    }
113

114
    /**
115
     * Convert from OpenXML escaped control character to PHP control character.
116
     *
117
     * @param string $value Value to unescape
118
     *
119
     * @return string
120
     */
121
    public static function controlCharacterOOXML2PHP($value = '')
1✔
122
    {
123
        self::buildControlCharacters();
1✔
124

125
        return str_replace(array_keys(self::$controlCharacters), array_values(self::$controlCharacters), $value);
1✔
126
    }
127

128
    /**
129
     * Check if a string contains UTF-8 data.
130
     *
131
     * @param string $value
132
     *
133
     * @return bool
134
     */
135
    public static function isUTF8($value = '')
456✔
136
    {
137
        return is_string($value) && ($value === '' || preg_match('/^./su', $value) == 1);
456✔
138
    }
139

140
    /**
141
     * Return UTF8 encoded value.
142
     *
143
     * @param null|string $value
144
     *
145
     * @return ?string
146
     */
147
    public static function toUTF8($value = '')
465✔
148
    {
149
        if (null !== $value && !self::isUTF8($value)) {
465✔
150
            $value = static::mbConvertEncoding($value);
12✔
151
            if ($value === false) {
12✔
152
                throw new WordException('Unable to convert text to UTF-8');
1✔
153
            }
154
        }
155

156
        return $value;
464✔
157
    }
158

159
    /**
160
     * @param string $value
161
     *
162
     * @return false|string
163
     */
164
    protected static function mbConvertEncoding($value)
11✔
165
    {
166
        return mb_convert_encoding($value, 'UTF-8', 'ISO-8859-1');
11✔
167
    }
168

169
    /**
170
     * Returns unicode from UTF8 text.
171
     *
172
     * The function is splitted to reduce cyclomatic complexity
173
     *
174
     * @param string $text UTF8 text
175
     *
176
     * @return string Unicode text
177
     *
178
     * @since 0.11.0
179
     */
180
    public static function toUnicode($text)
1✔
181
    {
182
        return self::unicodeToEntities(self::utf8ToUnicode($text));
1✔
183
    }
184

185
    /**
186
     * Returns unicode array from UTF8 text.
187
     *
188
     * @param string $text UTF8 text
189
     *
190
     * @return array
191
     *
192
     * @since 0.11.0
193
     * @see http://www.randomchaos.com/documents/?source=php_and_unicode
194
     */
195
    public static function utf8ToUnicode($text)
1✔
196
    {
197
        $unicode = [];
1✔
198
        $values = [];
1✔
199
        $lookingFor = 1;
1✔
200

201
        // Gets unicode for each character
202
        for ($i = 0; $i < strlen($text); ++$i) {
1✔
203
            $thisValue = ord($text[$i]);
1✔
204
            if ($thisValue < 128) {
1✔
205
                $unicode[] = $thisValue;
1✔
206
            } else {
207
                if (count($values) == 0) {
1✔
208
                    $lookingFor = $thisValue < 224 ? 2 : 3;
1✔
209
                }
210
                $values[] = $thisValue;
1✔
211
                if (count($values) == $lookingFor) {
1✔
212
                    if ($lookingFor == 3) {
1✔
213
                        $number = (($values[0] % 16) * 4096) + (($values[1] % 64) * 64) + ($values[2] % 64);
1✔
214
                    } else {
215
                        $number = (($values[0] % 32) * 64) + ($values[1] % 64);
1✔
216
                    }
217
                    $unicode[] = $number;
1✔
218
                    $values = [];
1✔
219
                    $lookingFor = 1;
1✔
220
                }
221
            }
222
        }
223

224
        return $unicode;
1✔
225
    }
226

227
    /**
228
     * Returns entites from unicode array.
229
     *
230
     * @param array $unicode
231
     *
232
     * @return string
233
     *
234
     * @since 0.11.0
235
     * @see http://www.randomchaos.com/documents/?source=php_and_unicode
236
     */
237
    private static function unicodeToEntities($unicode)
1✔
238
    {
239
        $entities = '';
1✔
240

241
        foreach ($unicode as $value) {
1✔
242
            if ($value != 65279) {
1✔
243
                $entities .= $value > 127 ? '\uc0{\u' . $value . '}' : chr($value);
1✔
244
            }
245
        }
246

247
        return $entities;
1✔
248
    }
249

250
    /**
251
     * Return name without underscore for < 0.10.0 variable name compatibility.
252
     *
253
     * @param string $value
254
     *
255
     * @return string
256
     */
257
    public static function removeUnderscorePrefix($value)
436✔
258
    {
259
        if (null !== $value) {
436✔
260
            if (substr($value, 0, 1) == '_') {
436✔
261
                $value = substr($value, 1);
1✔
262
            }
263
        }
264

265
        return $value;
436✔
266
    }
267
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc