Conditions | 88 |
Paths | > 20000 |
Total Lines | 407 |
Code Lines | 262 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
1 | <?php |
||
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 | } |
||
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.