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

PHPOffice / PHPWord / 16478895114

23 Jul 2025 06:32PM UTC coverage: 96.895% (+0.1%) from 96.757%
16478895114

Pull #2567

github

web-flow
Merge b7b30ac1a into 0ab0b4940
Pull Request #2567: WIP Do Not Install

300 of 307 new or added lines in 26 files covered. (97.72%)

164 existing lines in 23 files now uncovered.

12701 of 13108 relevant lines covered (96.9%)

37.38 hits per line

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

96.36
/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;
22

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

35
    /**
36
     * Build control characters array.
37
     */
38
    private static function buildControlCharacters(): void
39
    {
40
        for ($i = 0; $i <= 19; ++$i) {
40✔
41
            if ($i != 9 && $i != 10 && $i != 13) {
40✔
42
                $find = '_x' . sprintf('%04s', strtoupper(dechex($i))) . '_';
40✔
43
                $replace = chr($i);
40✔
44
                self::$controlCharacters[$find] = $replace;
40✔
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 = '')
65
    {
66
        if (empty(self::$controlCharacters)) {
106✔
67
            self::buildControlCharacters();
40✔
68
        }
69

70
        return str_replace(array_values(self::$controlCharacters), array_keys(self::$controlCharacters), $value);
106✔
71
    }
72

73
    /**
74
     * Return a number formatted for being integrated in xml files.
75
     *
76
     * @param float $number
77
     * @param int $decimals
78
     *
79
     * @return string
80
     */
81
    public static function numberFormat($number, $decimals)
82
    {
83
        return number_format($number, $decimals, '.', '');
1✔
84
    }
85

86
    /**
87
     * @param int $dec
88
     *
89
     * @see http://stackoverflow.com/a/7153133/2235790
90
     *
91
     * @author velcrow
92
     *
93
     * @return string
94
     */
95
    public static function chr($dec)
96
    {
97
        if ($dec <= 0x7F) {
1✔
98
            return chr($dec);
1✔
99
        }
100
        if ($dec <= 0x7FF) {
1✔
101
            return chr(($dec >> 6) + 192) . chr(($dec & 63) + 128);
1✔
102
        }
103
        if ($dec <= 0xFFFF) {
1✔
104
            return chr(($dec >> 12) + 224) . chr((($dec >> 6) & 63) + 128) . chr(($dec & 63) + 128);
1✔
105
        }
106
        if ($dec <= 0x1FFFFF) {
1✔
107
            return chr(($dec >> 18) + 240) . chr((($dec >> 12) & 63) + 128) . chr((($dec >> 6) & 63) + 128) . chr(($dec & 63) + 128);
1✔
108
        }
109

110
        return '';
1✔
111
    }
112

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

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

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

141
    /**
142
     * Return UTF8 encoded value.
143
     *
144
     * @param null|string $value
145
     *
146
     * @return ?string
147
     */
148
    public static function toUTF8($value = '')
149
    {
150
        if (null !== $value && !self::isUTF8($value)) {
371✔
151
            // PHP8.2 : utf8_encode is deprecated, but mb_convert_encoding always usable
152
            $value = (function_exists('mb_convert_encoding')) ? mb_convert_encoding($value, 'UTF-8', 'ISO-8859-1') : utf8_encode($value);
11✔
153
            if ($value === false) {
11✔
UNCOV
154
                throw new Exception('Unable to convert text to UTF-8');
×
155
            }
156
        }
157

158
        return $value;
371✔
159
    }
160

161
    /**
162
     * Returns unicode from UTF8 text.
163
     *
164
     * The function is splitted to reduce cyclomatic complexity
165
     *
166
     * @param string $text UTF8 text
167
     *
168
     * @return string Unicode text
169
     *
170
     * @since 0.11.0
171
     */
172
    public static function toUnicode($text)
173
    {
174
        return self::unicodeToEntities(self::utf8ToUnicode($text));
3✔
175
    }
176

177
    /**
178
     * Returns unicode array from UTF8 text.
179
     *
180
     * @param string $text UTF8 text
181
     *
182
     * @return array
183
     *
184
     * @since 0.11.0
185
     * @see http://www.randomchaos.com/documents/?source=php_and_unicode
186
     */
187
    public static function utf8ToUnicode($text)
188
    {
189
        $unicode = [];
3✔
190
        $values = [];
3✔
191
        $lookingFor = 1;
3✔
192

193
        // Gets unicode for each character
194
        for ($i = 0; $i < strlen($text); ++$i) {
3✔
195
            $thisValue = ord($text[$i]);
3✔
196
            if ($thisValue < 128) {
3✔
197
                $unicode[] = $thisValue;
3✔
198
            } else {
199
                if (count($values) == 0) {
1✔
200
                    $lookingFor = $thisValue < 224 ? 2 : 3;
1✔
201
                }
202
                $values[] = $thisValue;
1✔
203
                if (count($values) == $lookingFor) {
1✔
204
                    if ($lookingFor == 3) {
1✔
205
                        $number = (($values[0] % 16) * 4096) + (($values[1] % 64) * 64) + ($values[2] % 64);
1✔
206
                    } else {
207
                        $number = (($values[0] % 32) * 64) + ($values[1] % 64);
1✔
208
                    }
209
                    $unicode[] = $number;
1✔
210
                    $values = [];
1✔
211
                    $lookingFor = 1;
1✔
212
                }
213
            }
214
        }
215

216
        return $unicode;
3✔
217
    }
218

219
    /**
220
     * Returns entites from unicode array.
221
     *
222
     * @param array $unicode
223
     *
224
     * @return string
225
     *
226
     * @since 0.11.0
227
     * @see http://www.randomchaos.com/documents/?source=php_and_unicode
228
     */
229
    private static function unicodeToEntities($unicode)
230
    {
231
        $entities = '';
3✔
232

233
        foreach ($unicode as $value) {
3✔
234
            if ($value != 65279) {
3✔
235
                $entities .= $value > 127 ? '\uc0{\u' . $value . '}' : chr($value);
3✔
236
            }
237
        }
238

239
        return $entities;
3✔
240
    }
241

242
    /**
243
     * Return name without underscore for < 0.10.0 variable name compatibility.
244
     *
245
     * @param string $value
246
     *
247
     * @return string
248
     */
249
    public static function removeUnderscorePrefix($value)
250
    {
251
        if (null !== $value) {
352✔
252
            if (substr($value, 0, 1) == '_') {
352✔
253
                $value = substr($value, 1);
1✔
254
            }
255
        }
256

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

© 2026 Coveralls, Inc