Total Complexity | 210 |
Total Lines | 1131 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like FunctionsRtl often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use FunctionsRtl, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
23 | class FunctionsRtl { |
||
24 | const OPEN_PARENTHESES = '([{'; |
||
25 | |||
26 | const CLOSE_PARENTHESES = ')]}'; |
||
27 | |||
28 | const NUMBERS = '0123456789'; |
||
29 | |||
30 | const NUMBER_PREFIX = '+-'; // Treat these like numbers when at beginning or end of numeric strings |
||
31 | |||
32 | const NUMBER_PUNCTUATION = '- ,.:/'; // Treat these like numbers when inside numeric strings |
||
33 | |||
34 | const PUNCTUATION = ',.:;?!'; |
||
35 | |||
36 | /** @var string Were we previously processing LTR or RTL. */ |
||
37 | private static $previousState; |
||
38 | |||
39 | /** @var string Are we currently processing LTR or RTL. */ |
||
40 | private static $currentState; |
||
41 | |||
42 | /** @var string Text waiting to be processed. */ |
||
43 | private static $waitingText; |
||
44 | |||
45 | /** @var string LTR text. */ |
||
46 | private static $startLTR; |
||
47 | |||
48 | /** @var string LTR text. */ |
||
49 | private static $endLTR; |
||
50 | |||
51 | /** @var string RTL text. */ |
||
52 | private static $startRTL; |
||
53 | |||
54 | /** @var string RTL text. */ |
||
55 | private static $endRTL; |
||
56 | |||
57 | /** @var int Offset into the text. */ |
||
58 | private static $lenStart; |
||
59 | |||
60 | /** @var int Offset into the text. */ |
||
61 | private static $lenEnd; |
||
62 | |||
63 | /** @var int Offset into the text. */ |
||
64 | private static $posSpanStart; |
||
65 | |||
66 | /** |
||
67 | * This function strips ‎ and ‏ from the input string. It should be used for all |
||
68 | * text that has been passed through the PrintReady() function before that text is stored |
||
69 | * in the database. The database should NEVER contain these characters. |
||
70 | * |
||
71 | * @param string $inputText The string from which the ‎ and ‏ characters should be stripped |
||
72 | * |
||
73 | * @return string The input string, with ‎ and ‏ stripped |
||
74 | */ |
||
75 | public static function stripLrmRlm($inputText) { |
||
76 | return str_replace([WT_UTF8_LRM, WT_UTF8_RLM, WT_UTF8_LRO, WT_UTF8_RLO, WT_UTF8_LRE, WT_UTF8_RLE, WT_UTF8_PDF, '‎', '‏', '&LRM;', '&RLM;'], '', $inputText); |
||
77 | } |
||
78 | |||
79 | /** |
||
80 | * This function encapsulates all texts in the input with <span dir='xxx'> and </span> |
||
81 | * according to the directionality specified. |
||
82 | * |
||
83 | * @param string $inputText Raw input |
||
84 | * @param string $direction Directionality (LTR, BOTH, RTL) default BOTH |
||
85 | * @param string $class Additional text to insert into output <span dir="xxx"> (such as 'class="yyy"') |
||
86 | * |
||
87 | * @return string The string with all texts encapsulated as required |
||
88 | */ |
||
89 | public static function spanLtrRtl($inputText, $direction = 'BOTH', $class = '') { |
||
90 | if ($inputText == '') { |
||
91 | // Nothing to do |
||
92 | return ''; |
||
93 | } |
||
94 | |||
95 | $workingText = str_replace("\n", '<br>', $inputText); |
||
96 | $workingText = str_replace(['<span class="starredname"><br>', '<span<br>class="starredname">'], '<br><span class="starredname">', $workingText); // Reposition some incorrectly placed line breaks |
||
97 | $workingText = self::stripLrmRlm($workingText); // Get rid of any existing UTF8 control codes |
||
98 | |||
99 | // $nothing = '‌'; // Zero Width Non-Joiner (not sure whether this is still needed to work around a TCPDF bug) |
||
|
|||
100 | $nothing = ''; |
||
101 | |||
102 | self::$startLTR = '<LTR>'; // This will become '<span dir="ltr">' at the end |
||
103 | self::$endLTR = '</LTR>'; // This will become '</span>' at the end |
||
104 | self::$startRTL = '<RTL>'; // This will become '<span dir="rtl">' at the end |
||
105 | self::$endRTL = '</RTL>'; // This will become '</span>' at the end |
||
106 | self::$lenStart = strlen(self::$startLTR); // RTL version MUST have same length |
||
107 | self::$lenEnd = strlen(self::$endLTR); // RTL version MUST have same length |
||
108 | |||
109 | self::$previousState = ''; |
||
110 | self::$currentState = strtoupper(I18N::direction()); |
||
111 | $numberState = false; // Set when we're inside a numeric string |
||
112 | $result = ''; |
||
113 | self::$waitingText = ''; |
||
114 | $openParDirection = []; |
||
115 | |||
116 | self::beginCurrentSpan($result); |
||
117 | |||
118 | while ($workingText != '') { |
||
119 | $charArray = self::getChar($workingText, 0); // Get the next ASCII or UTF-8 character |
||
120 | $currentLetter = $charArray['letter']; |
||
121 | $currentLen = $charArray['length']; |
||
122 | |||
123 | $openParIndex = strpos(self::OPEN_PARENTHESES, $currentLetter); // Which opening parenthesis is this? |
||
124 | $closeParIndex = strpos(self::CLOSE_PARENTHESES, $currentLetter); // Which closing parenthesis is this? |
||
125 | |||
126 | switch ($currentLetter) { |
||
127 | case '<': |
||
128 | // Assume this '<' starts an HTML element |
||
129 | $endPos = strpos($workingText, '>'); // look for the terminating '>' |
||
130 | if ($endPos === false) { |
||
131 | $endPos = 0; |
||
132 | } |
||
133 | $currentLen += $endPos; |
||
134 | $element = substr($workingText, 0, $currentLen); |
||
135 | $temp = strtolower(substr($element, 0, 3)); |
||
136 | if (strlen($element) < 7 && $temp == '<br') { |
||
137 | if ($numberState) { |
||
138 | $numberState = false; |
||
139 | if (self::$currentState == 'RTL') { |
||
140 | self::$waitingText .= WT_UTF8_PDF; |
||
141 | } |
||
142 | } |
||
143 | self::breakCurrentSpan($result); |
||
144 | } elseif (self::$waitingText == '') { |
||
145 | $result .= $element; |
||
146 | } else { |
||
147 | self::$waitingText .= $element; |
||
148 | } |
||
149 | $workingText = substr($workingText, $currentLen); |
||
150 | break; |
||
151 | case '&': |
||
152 | // Assume this '&' starts an HTML entity |
||
153 | $endPos = strpos($workingText, ';'); // look for the terminating ';' |
||
154 | if ($endPos === false) { |
||
155 | $endPos = 0; |
||
156 | } |
||
157 | $currentLen += $endPos; |
||
158 | $entity = substr($workingText, 0, $currentLen); |
||
159 | if (strtolower($entity) == ' ') { |
||
160 | $entity .= ' '; // Ensure consistent case for this entity |
||
161 | } |
||
162 | if (self::$waitingText == '') { |
||
163 | $result .= $entity; |
||
164 | } else { |
||
165 | self::$waitingText .= $entity; |
||
166 | } |
||
167 | $workingText = substr($workingText, $currentLen); |
||
168 | break; |
||
169 | case '{': |
||
170 | if (substr($workingText, 1, 1) == '{') { |
||
171 | // Assume this '{{' starts a TCPDF directive |
||
172 | $endPos = strpos($workingText, '}}'); // look for the terminating '}}' |
||
173 | if ($endPos === false) { |
||
174 | $endPos = 0; |
||
175 | } |
||
176 | $currentLen = $endPos + 2; |
||
177 | $directive = substr($workingText, 0, $currentLen); |
||
178 | $workingText = substr($workingText, $currentLen); |
||
179 | $result = $result . self::$waitingText . $directive; |
||
180 | self::$waitingText = ''; |
||
181 | break; |
||
182 | } |
||
183 | default: |
||
184 | // Look for strings of numbers with optional leading or trailing + or - |
||
185 | // and with optional embedded numeric punctuation |
||
186 | if ($numberState) { |
||
187 | // If we're inside a numeric string, look for reasons to end it |
||
188 | $offset = 0; // Be sure to look at the current character first |
||
189 | $charArray = self::getChar($workingText . "\n", $offset); |
||
190 | if (strpos(self::NUMBERS, $charArray['letter']) === false) { |
||
191 | // This is not a digit. Is it numeric punctuation? |
||
192 | if (substr($workingText . "\n", $offset, 6) == ' ') { |
||
193 | $offset += 6; // This could be numeric punctuation |
||
194 | } elseif (strpos(self::NUMBER_PUNCTUATION, $charArray['letter']) !== false) { |
||
195 | $offset += $charArray['length']; // This could be numeric punctuation |
||
196 | } |
||
197 | // If the next character is a digit, the current character is numeric punctuation |
||
198 | $charArray = self::getChar($workingText . "\n", $offset); |
||
199 | if (strpos(self::NUMBERS, $charArray['letter']) === false) { |
||
200 | // This is not a digit. End the run of digits and punctuation. |
||
201 | $numberState = false; |
||
202 | if (self::$currentState == 'RTL') { |
||
203 | if (strpos(self::NUMBER_PREFIX, $currentLetter) === false) { |
||
204 | $currentLetter = WT_UTF8_PDF . $currentLetter; |
||
205 | } else { |
||
206 | $currentLetter = $currentLetter . WT_UTF8_PDF; // Include a trailing + or - in the run |
||
207 | } |
||
208 | } |
||
209 | } |
||
210 | } |
||
211 | } else { |
||
212 | // If we're outside a numeric string, look for reasons to start it |
||
213 | if (strpos(self::NUMBER_PREFIX, $currentLetter) !== false) { |
||
214 | // This might be a number lead-in |
||
215 | $offset = $currentLen; |
||
216 | $nextChar = substr($workingText . "\n", $offset, 1); |
||
217 | if (strpos(self::NUMBERS, $nextChar) !== false) { |
||
218 | $numberState = true; // We found a digit: the lead-in is therefore numeric |
||
219 | if (self::$currentState == 'RTL') { |
||
220 | $currentLetter = WT_UTF8_LRE . $currentLetter; |
||
221 | } |
||
222 | } |
||
223 | } elseif (strpos(self::NUMBERS, $currentLetter) !== false) { |
||
224 | $numberState = true; // The current letter is a digit |
||
225 | if (self::$currentState == 'RTL') { |
||
226 | $currentLetter = WT_UTF8_LRE . $currentLetter; |
||
227 | } |
||
228 | } |
||
229 | } |
||
230 | |||
231 | // Determine the directionality of the current UTF-8 character |
||
232 | $newState = self::$currentState; |
||
233 | while (true) { |
||
234 | if (I18N::scriptDirection(I18N::textScript($currentLetter)) === 'rtl') { |
||
235 | if (self::$currentState == '') { |
||
236 | $newState = 'RTL'; |
||
237 | break; |
||
238 | } |
||
239 | |||
240 | if (self::$currentState == 'RTL') { |
||
241 | break; |
||
242 | } |
||
243 | // Switch to RTL only if this isn't a solitary RTL letter |
||
244 | $tempText = substr($workingText, $currentLen); |
||
245 | while ($tempText != '') { |
||
246 | $nextCharArray = self::getChar($tempText, 0); |
||
247 | $nextLetter = $nextCharArray['letter']; |
||
248 | $nextLen = $nextCharArray['length']; |
||
249 | $tempText = substr($tempText, $nextLen); |
||
250 | |||
251 | if (I18N::scriptDirection(I18N::textScript($nextLetter)) === 'rtl') { |
||
252 | $newState = 'RTL'; |
||
253 | break 2; |
||
254 | } |
||
255 | |||
256 | if (strpos(self::PUNCTUATION, $nextLetter) !== false || strpos(self::OPEN_PARENTHESES, $nextLetter) !== false) { |
||
257 | $newState = 'RTL'; |
||
258 | break 2; |
||
259 | } |
||
260 | |||
261 | if ($nextLetter === ' ') { |
||
262 | break; |
||
263 | } |
||
264 | $nextLetter .= substr($tempText . "\n", 0, 5); |
||
265 | if ($nextLetter === ' ') { |
||
266 | break; |
||
267 | } |
||
268 | } |
||
269 | // This is a solitary RTL letter : wrap it in UTF8 control codes to force LTR directionality |
||
270 | $currentLetter = WT_UTF8_LRO . $currentLetter . WT_UTF8_PDF; |
||
271 | $newState = 'LTR'; |
||
272 | break; |
||
273 | } |
||
274 | if (($currentLen != 1) || ($currentLetter >= 'A' && $currentLetter <= 'Z') || ($currentLetter >= 'a' && $currentLetter <= 'z')) { |
||
275 | // Since it’s neither Hebrew nor Arabic, this UTF-8 character or ASCII letter must be LTR |
||
276 | $newState = 'LTR'; |
||
277 | break; |
||
278 | } |
||
279 | if ($closeParIndex !== false) { |
||
280 | // This closing parenthesis has to inherit the matching opening parenthesis' directionality |
||
281 | if (!empty($openParDirection[$closeParIndex]) && $openParDirection[$closeParIndex] != '?') { |
||
282 | $newState = $openParDirection[$closeParIndex]; |
||
283 | } |
||
284 | $openParDirection[$closeParIndex] = ''; |
||
285 | break; |
||
286 | } |
||
287 | if ($openParIndex !== false) { |
||
288 | // Opening parentheses always inherit the following directionality |
||
289 | self::$waitingText .= $currentLetter; |
||
290 | $workingText = substr($workingText, $currentLen); |
||
291 | while (true) { |
||
292 | if ($workingText === '') { |
||
293 | break; |
||
294 | } |
||
295 | if (substr($workingText, 0, 1) === ' ') { |
||
296 | // Spaces following this left parenthesis inherit the following directionality too |
||
297 | self::$waitingText .= ' '; |
||
298 | $workingText = substr($workingText, 1); |
||
299 | continue; |
||
300 | } |
||
301 | if (substr($workingText, 0, 6) === ' ') { |
||
302 | // Spaces following this left parenthesis inherit the following directionality too |
||
303 | self::$waitingText .= ' '; |
||
304 | $workingText = substr($workingText, 6); |
||
305 | continue; |
||
306 | } |
||
307 | break; |
||
308 | } |
||
309 | $openParDirection[$openParIndex] = '?'; |
||
310 | break 2; // double break because we're waiting for more information |
||
311 | } |
||
312 | |||
313 | // We have a digit or a "normal" special character. |
||
314 | // |
||
315 | // When this character is not at the start of the input string, it inherits the preceding directionality; |
||
316 | // at the start of the input string, it assumes the following directionality. |
||
317 | // |
||
318 | // Exceptions to this rule will be handled later during final clean-up. |
||
319 | // |
||
320 | self::$waitingText .= $currentLetter; |
||
321 | $workingText = substr($workingText, $currentLen); |
||
322 | if (self::$currentState != '') { |
||
323 | $result .= self::$waitingText; |
||
324 | self::$waitingText = ''; |
||
325 | } |
||
326 | break 2; // double break because we're waiting for more information |
||
327 | } |
||
328 | if ($newState != self::$currentState) { |
||
329 | // A direction change has occurred |
||
330 | self::finishCurrentSpan($result, false); |
||
331 | self::$previousState = self::$currentState; |
||
332 | self::$currentState = $newState; |
||
333 | self::beginCurrentSpan($result); |
||
334 | } |
||
335 | self::$waitingText .= $currentLetter; |
||
336 | $workingText = substr($workingText, $currentLen); |
||
337 | $result .= self::$waitingText; |
||
338 | self::$waitingText = ''; |
||
339 | |||
340 | foreach ($openParDirection as $index => $value) { |
||
341 | // Since we now know the proper direction, remember it for all waiting opening parentheses |
||
342 | if ($value === '?') { |
||
343 | $openParDirection[$index] = self::$currentState; |
||
344 | } |
||
345 | } |
||
346 | |||
347 | break; |
||
348 | } |
||
349 | } |
||
350 | |||
351 | // We're done. Finish last <span> if necessary |
||
352 | if ($numberState) { |
||
353 | if (self::$waitingText === '') { |
||
354 | if (self::$currentState === 'RTL') { |
||
355 | $result .= WT_UTF8_PDF; |
||
356 | } |
||
357 | } else { |
||
358 | if (self::$currentState === 'RTL') { |
||
359 | self::$waitingText .= WT_UTF8_PDF; |
||
360 | } |
||
361 | } |
||
362 | } |
||
363 | self::finishCurrentSpan($result, true); |
||
364 | |||
365 | // Get rid of any waiting text |
||
366 | if (self::$waitingText != '') { |
||
367 | if (I18N::direction() === 'rtl' && self::$currentState === 'LTR') { |
||
368 | $result .= self::$startRTL; |
||
369 | $result .= self::$waitingText; |
||
370 | $result .= self::$endRTL; |
||
371 | } else { |
||
372 | $result .= self::$startLTR; |
||
373 | $result .= self::$waitingText; |
||
374 | $result .= self::$endLTR; |
||
375 | } |
||
376 | self::$waitingText = ''; |
||
377 | } |
||
378 | |||
379 | // Lastly, do some more cleanups |
||
380 | |||
381 | // Move leading RTL numeric strings to following LTR text |
||
382 | // (this happens when the page direction is RTL and the original text begins with a number and is followed by LTR text) |
||
383 | while (substr($result, 0, self::$lenStart + 3) === self::$startRTL . WT_UTF8_LRE) { |
||
384 | $spanEnd = strpos($result, self::$endRTL . self::$startLTR); |
||
385 | if ($spanEnd === false) { |
||
386 | break; |
||
387 | } |
||
388 | $textSpan = self::stripLrmRlm(substr($result, self::$lenStart + 3, $spanEnd - self::$lenStart - 3)); |
||
389 | if (I18N::scriptDirection(I18N::textScript($textSpan)) === 'rtl') { |
||
390 | break; |
||
391 | } |
||
392 | $result = self::$startLTR . substr($result, self::$lenStart, $spanEnd - self::$lenStart) . substr($result, $spanEnd + self::$lenStart + self::$lenEnd); |
||
393 | break; |
||
394 | } |
||
395 | |||
396 | // On RTL pages, put trailing "." in RTL numeric strings into its own RTL span |
||
397 | if (I18N::direction() === 'rtl') { |
||
398 | $result = str_replace(WT_UTF8_PDF . '.' . self::$endRTL, WT_UTF8_PDF . self::$endRTL . self::$startRTL . '.' . self::$endRTL, $result); |
||
399 | } |
||
400 | |||
401 | // Trim trailing blanks preceding <br> in LTR text |
||
402 | while (self::$previousState != 'RTL') { |
||
403 | if (strpos($result, ' <LTRbr>') !== false) { |
||
404 | $result = str_replace(' <LTRbr>', '<LTRbr>', $result); |
||
405 | continue; |
||
406 | } |
||
407 | if (strpos($result, ' <LTRbr>') !== false) { |
||
408 | $result = str_replace(' <LTRbr>', '<LTRbr>', $result); |
||
409 | continue; |
||
410 | } |
||
411 | if (strpos($result, ' <br>') !== false) { |
||
412 | $result = str_replace(' <br>', '<br>', $result); |
||
413 | continue; |
||
414 | } |
||
415 | if (strpos($result, ' <br>') !== false) { |
||
416 | $result = str_replace(' <br>', '<br>', $result); |
||
417 | continue; |
||
418 | } |
||
419 | break; // Neither space nor : we're done |
||
420 | } |
||
421 | |||
422 | // Trim trailing blanks preceding <br> in RTL text |
||
423 | while (true) { |
||
424 | if (strpos($result, ' <RTLbr>') !== false) { |
||
425 | $result = str_replace(' <RTLbr>', '<RTLbr>', $result); |
||
426 | continue; |
||
427 | } |
||
428 | if (strpos($result, ' <RTLbr>') !== false) { |
||
429 | $result = str_replace(' <RTLbr>', '<RTLbr>', $result); |
||
430 | continue; |
||
431 | } |
||
432 | break; // Neither space nor : we're done |
||
433 | } |
||
434 | |||
435 | // Convert '<LTRbr>' and '<RTLbr /' |
||
436 | $result = str_replace(['<LTRbr>', '<RTLbr>'], [self::$endLTR . '<br>' . self::$startLTR, self::$endRTL . '<br>' . self::$startRTL], $result); |
||
437 | |||
438 | // Include leading indeterminate directional text in whatever follows |
||
439 | if (substr($result . "\n", 0, self::$lenStart) != self::$startLTR && substr($result . "\n", 0, self::$lenStart) != self::$startRTL && substr($result . "\n", 0, 6) != '<br>') { |
||
440 | $leadingText = ''; |
||
441 | while (true) { |
||
442 | if ($result == '') { |
||
443 | $result = $leadingText; |
||
444 | break; |
||
445 | } |
||
446 | if (substr($result . "\n", 0, self::$lenStart) != self::$startLTR && substr($result . "\n", 0, self::$lenStart) != self::$startRTL) { |
||
447 | $leadingText .= substr($result, 0, 1); |
||
448 | $result = substr($result, 1); |
||
449 | continue; |
||
450 | } |
||
451 | $result = substr($result, 0, self::$lenStart) . $leadingText . substr($result, self::$lenStart); |
||
452 | break; |
||
453 | } |
||
454 | } |
||
455 | |||
456 | // Include solitary "-" and "+" in surrounding RTL text |
||
457 | $result = str_replace([self::$endRTL . self::$startLTR . '-' . self::$endLTR . self::$startRTL, self::$endRTL . self::$startLTR . '-' . self::$endLTR . self::$startRTL], ['-', '+'], $result); |
||
458 | |||
459 | // Remove empty spans |
||
460 | $result = str_replace([self::$startLTR . self::$endLTR, self::$startRTL . self::$endRTL], '', $result); |
||
461 | |||
462 | // Finally, correct '<LTR>', '</LTR>', '<RTL>', and '</RTL>' |
||
463 | switch ($direction) { |
||
464 | case 'BOTH': |
||
465 | case 'both': |
||
466 | // LTR text: <span dir="ltr"> text </span> |
||
467 | // RTL text: <span dir="rtl"> text </span> |
||
468 | $sLTR = '<span dir="ltr" ' . $class . '>' . $nothing; |
||
469 | $eLTR = $nothing . '</span>'; |
||
470 | $sRTL = '<span dir="rtl" ' . $class . '>' . $nothing; |
||
471 | $eRTL = $nothing . '</span>'; |
||
472 | break; |
||
473 | case 'LTR': |
||
474 | case 'ltr': |
||
475 | // LTR text: <span dir="ltr"> text </span> |
||
476 | // RTL text: text |
||
477 | $sLTR = '<span dir="ltr" ' . $class . '>' . $nothing; |
||
478 | $eLTR = $nothing . '</span>'; |
||
479 | $sRTL = ''; |
||
480 | $eRTL = ''; |
||
481 | break; |
||
482 | case 'RTL': |
||
483 | case 'rtl': |
||
484 | default: |
||
485 | // LTR text: text |
||
486 | // RTL text: <span dir="rtl"> text </span> |
||
487 | $sLTR = ''; |
||
488 | $eLTR = ''; |
||
489 | $sRTL = '<span dir="rtl" ' . $class . '>' . $nothing; |
||
490 | $eRTL = $nothing . '</span>'; |
||
491 | break; |
||
492 | } |
||
493 | $result = str_replace([self::$startLTR, self::$endLTR, self::$startRTL, self::$endRTL], [$sLTR, $eLTR, $sRTL, $eRTL], $result); |
||
494 | |||
495 | return $result; |
||
496 | } |
||
497 | |||
498 | /** |
||
499 | * Wrap words that have an asterisk suffix in <u> and </u> tags. |
||
500 | * This should underline starred names to show the preferred name. |
||
501 | * |
||
502 | * @param string $textSpan |
||
503 | * @param string $direction |
||
504 | * |
||
505 | * @return string |
||
506 | */ |
||
507 | public static function starredName($textSpan, $direction) { |
||
508 | // To avoid a TCPDF bug that mixes up the word order, insert those <u> and </u> tags |
||
509 | // only when page and span directions are identical. |
||
510 | if ($direction === strtoupper(I18N::direction())) { |
||
511 | while (true) { |
||
512 | $starPos = strpos($textSpan, '*'); |
||
513 | if ($starPos === false) { |
||
514 | break; |
||
515 | } |
||
516 | $trailingText = substr($textSpan, $starPos + 1); |
||
517 | $textSpan = substr($textSpan, 0, $starPos); |
||
518 | $wordStart = strrpos($textSpan, ' '); // Find the start of the word |
||
519 | if ($wordStart !== false) { |
||
520 | $leadingText = substr($textSpan, 0, $wordStart + 1); |
||
521 | $wordText = substr($textSpan, $wordStart + 1); |
||
522 | } else { |
||
523 | $leadingText = ''; |
||
524 | $wordText = $textSpan; |
||
525 | } |
||
526 | $textSpan = $leadingText . '<u>' . $wordText . '</u>' . $trailingText; |
||
527 | } |
||
528 | $textSpan = preg_replace('~<span class="starredname">(.*)</span>~', '<u>\1</u>', $textSpan); |
||
529 | // The is a work-around for a TCPDF bug eating blanks. |
||
530 | $textSpan = str_replace([' <u>', '</u> '], [' <u>', '</u> '], $textSpan); |
||
531 | } else { |
||
532 | // Text and page directions differ: remove the <span> and </span> |
||
533 | $textSpan = preg_replace('~(.*)\*~', '\1', $textSpan); |
||
534 | $textSpan = preg_replace('~<span class="starredname">(.*)</span>~', '\1', $textSpan); |
||
535 | } |
||
536 | |||
537 | return $textSpan; |
||
538 | } |
||
539 | |||
540 | /** |
||
541 | * Get the next character from an input string |
||
542 | * |
||
543 | * @param string $text |
||
544 | * @param string $offset |
||
545 | * |
||
546 | * @return array |
||
547 | */ |
||
548 | public static function getChar($text, $offset) { |
||
549 | if ($text == '') { |
||
550 | return ['letter' => '', 'length' => 0]; |
||
551 | } |
||
552 | |||
553 | $char = substr($text, $offset, 1); |
||
554 | $length = 1; |
||
555 | if ((ord($char) & 0xE0) == 0xC0) { |
||
556 | $length = 2; |
||
557 | } |
||
558 | if ((ord($char) & 0xF0) == 0xE0) { |
||
559 | $length = 3; |
||
560 | } |
||
561 | if ((ord($char) & 0xF8) == 0xF0) { |
||
562 | $length = 4; |
||
563 | } |
||
564 | $letter = substr($text, $offset, $length); |
||
565 | |||
566 | return ['letter' => $letter, 'length' => $length]; |
||
567 | } |
||
568 | |||
569 | /** |
||
570 | * Insert <br> into current span |
||
571 | * |
||
572 | * @param string $result |
||
573 | */ |
||
574 | public static function breakCurrentSpan(&$result) { |
||
575 | // Interrupt the current span, insert that <br>, and then continue the current span |
||
576 | $result .= self::$waitingText; |
||
577 | self::$waitingText = ''; |
||
578 | |||
579 | $breakString = '<' . self::$currentState . 'br>'; |
||
580 | $result .= $breakString; |
||
581 | } |
||
582 | |||
583 | /** |
||
584 | * Begin current span |
||
585 | * |
||
586 | * @param string $result |
||
587 | */ |
||
588 | public static function beginCurrentSpan(&$result) { |
||
597 | } |
||
598 | |||
599 | /** |
||
600 | * Finish current span |
||
601 | * |
||
602 | * @param string $result |
||
603 | * @param bool $theEnd |
||
604 | */ |
||
605 | public static function finishCurrentSpan(&$result, $theEnd = false) { |
||
1102 | } |
||
1103 | |||
1104 | /** |
||
1105 | * Wrap text, similar to the PHP wordwrap() function. |
||
1106 | * |
||
1107 | * @param string $string |
||
1108 | * @param int $width |
||
1109 | * @param string $sep |
||
1110 | * @param bool $cut |
||
1111 | * |
||
1112 | * @return string |
||
1113 | */ |
||
1114 | public static function utf8WordWrap($string, $width = 75, $sep = "\n", $cut = false) { |
||
1156 |
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.