summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/Report/ReportPdfCell.php4
-rw-r--r--app/Report/ReportPdfText.php4
-rw-r--r--app/Reports/RightToLeftSupport.php (renamed from app/Functions/FunctionsRtl.php)27
-rw-r--r--tests/app/Reports/RightToLeftSupportTest.php257
4 files changed, 277 insertions, 15 deletions
diff --git a/app/Report/ReportPdfCell.php b/app/Report/ReportPdfCell.php
index 67330b9ddd..417dd12fc2 100644
--- a/app/Report/ReportPdfCell.php
+++ b/app/Report/ReportPdfCell.php
@@ -19,7 +19,7 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Report;
-use Fisharebest\Webtrees\Functions\FunctionsRtl;
+use Fisharebest\Webtrees\Reports\RightToLeftSupport;
use function hexdec;
use function is_array;
@@ -130,7 +130,7 @@ class ReportPdfCell extends ReportBaseCell
if ($renderer->checkPageBreakPDF($cHT)) {
$this->top = $renderer->tcpdf->GetY();
}
- $temptext = FunctionsRtl::spanLtrRtl($temptext);
+ $temptext = RightToLeftSupport::spanLtrRtl($temptext);
}
// HTML ready - last value is true
$renderer->tcpdf->MultiCell(
diff --git a/app/Report/ReportPdfText.php b/app/Report/ReportPdfText.php
index 40b28306d2..6c7188d2d3 100644
--- a/app/Report/ReportPdfText.php
+++ b/app/Report/ReportPdfText.php
@@ -19,7 +19,7 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Report;
-use Fisharebest\Webtrees\Functions\FunctionsRtl;
+use Fisharebest\Webtrees\Reports\RightToLeftSupport;
use function count;
use function explode;
@@ -66,7 +66,7 @@ class ReportPdfText extends ReportBaseText
} else {
$renderer->tcpdf->SetTextColor(0, 0, 0);
}
- $temptext = FunctionsRtl::spanLtrRtl($temptext);
+ $temptext = RightToLeftSupport::spanLtrRtl($temptext);
$temptext = str_replace(
[
'<br><span dir="rtl">',
diff --git a/app/Functions/FunctionsRtl.php b/app/Reports/RightToLeftSupport.php
index 936fae9833..a991c3b72e 100644
--- a/app/Functions/FunctionsRtl.php
+++ b/app/Reports/RightToLeftSupport.php
@@ -17,16 +17,16 @@
declare(strict_types=1);
-namespace Fisharebest\Webtrees\Functions;
+namespace Fisharebest\Webtrees\Reports;
use Fisharebest\Webtrees\I18N;
use function str_contains;
/**
- * RTL Functions for use in the PDF/HTML reports
+ * RTL Functions for use in the PDF reports
*/
-class FunctionsRtl
+class RightToLeftSupport
{
private const UTF8_LRM = "\xE2\x80\x8E"; // U+200E (Left to Right mark: zero-width character with LTR directionality)
private const UTF8_RLM = "\xE2\x80\x8F"; // U+200F (Right to Left mark: zero-width character with RTL directionality)
@@ -77,7 +77,7 @@ class FunctionsRtl
*
* @return string The input string, with &lrm; and &rlm; stripped
*/
- public static function stripLrmRlm(string $inputText): string
+ private static function stripLrmRlm(string $inputText): string
{
return str_replace([
self::UTF8_LRM,
@@ -167,7 +167,7 @@ class FunctionsRtl
$currentLen += $endPos;
$entity = substr($workingText, 0, $currentLen);
if (strtolower($entity) === '&nbsp;') {
- $entity .= '&nbsp;'; // Ensure consistent case for this entity
+ $entity = '&nbsp;'; // Ensure consistent case for this entity
}
if (self::$waitingText === '') {
$result .= $entity;
@@ -474,12 +474,17 @@ class FunctionsRtl
// Include solitary "-" and "+" in surrounding RTL text
$result = str_replace([
self::END_RTL . self::START_LTR . '-' . self::END_LTR . self::START_RTL,
- self::END_RTL . self::START_LTR . '-' . self::END_LTR . self::START_RTL,
+ self::END_RTL . self::START_LTR . '+' . self::END_LTR . self::START_RTL,
], [
'-',
'+',
], $result);
+ //$result = strtr($result, [
+ // self::END_RTL . self::START_LTR . '-' . self::END_LTR . self::START_RTL => '-',
+ // self::END_RTL . self::START_LTR . '+' . self::END_LTR . self::START_RTL => '+',
+ //]);
+
// Remove empty spans
$result = str_replace([
self::START_LTR . self::END_LTR,
@@ -514,7 +519,7 @@ class FunctionsRtl
*
* @return string
*/
- public static function starredName(string $textSpan, string $direction): string
+ private static function starredName(string $textSpan, string $direction): string
{
// To avoid a TCPDF bug that mixes up the word order, insert those <u> and </u> tags
// only when page and span directions are identical.
@@ -562,7 +567,7 @@ class FunctionsRtl
*
* @return array{'letter':string,'length':int}
*/
- public static function getChar(string $text, int $offset): array
+ private static function getChar(string $text, int $offset): array
{
if ($text === '') {
return [
@@ -597,7 +602,7 @@ class FunctionsRtl
*
* @return void
*/
- public static function breakCurrentSpan(string &$result): void
+ private static function breakCurrentSpan(string &$result): void
{
// Interrupt the current span, insert that <br>, and then continue the current span
$result .= self::$waitingText;
@@ -614,7 +619,7 @@ class FunctionsRtl
*
* @return void
*/
- public static function beginCurrentSpan(string &$result): void
+ private static function beginCurrentSpan(string &$result): void
{
if (self::$currentState === 'LTR') {
$result .= self::START_LTR;
@@ -634,7 +639,7 @@ class FunctionsRtl
*
* @return void
*/
- public static function finishCurrentSpan(string &$result, bool $theEnd = false): void
+ private static function finishCurrentSpan(string &$result, bool $theEnd = false): void
{
$textSpan = substr($result, self::$posSpanStart);
$result = substr($result, 0, self::$posSpanStart);
diff --git a/tests/app/Reports/RightToLeftSupportTest.php b/tests/app/Reports/RightToLeftSupportTest.php
new file mode 100644
index 0000000000..5b0de222a7
--- /dev/null
+++ b/tests/app/Reports/RightToLeftSupportTest.php
@@ -0,0 +1,257 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2021 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Reports;
+
+use Fisharebest\Webtrees\I18N;
+use Fisharebest\Webtrees\TestCase;
+
+/**
+ * Test the RTL functions. This is very old code, and poorly understood.
+ * These tests exist to capture the existing functionality, and prevent regression during refactoring.
+ */
+class RightToLeftSupportTest extends TestCase
+{
+ /**
+ * @covers \Fisharebest\Webtrees\Reports\RightToLeftSupport
+ *
+ * @return void
+ */
+ public function testEmptyString(): void
+ {
+ I18N::init('en-US', true);
+ $this->assertSame(
+
+ '',
+ RightToLeftSupport::spanLtrRtl('')
+ );
+
+ I18N::init('he', true);
+ $this->assertSame(
+ '',
+ RightToLeftSupport::spanLtrRtl('')
+ );
+ }
+
+ /**
+ * @covers \Fisharebest\Webtrees\Reports\RightToLeftSupport
+ *
+ * @return void
+ */
+ public function testStripControlCharacters(): void
+ {
+ I18N::init('en-US', true);
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl('foo&lrm;bar')
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl('foo&rlm;bar')
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\xE2\x80\x8Ebar")
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\xE2\x80\x8Fbar")
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\xE2\x80\xADbar")
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\xE2\x80\xAEbar")
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\xE2\x80\xAAbar")
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\xE2\x80\xABbar")
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\xE2\x80\xACbar")
+ );
+
+ I18N::init('he', true);
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl('foo&lrm;bar')
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl('foo&rlm;bar')
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\xE2\x80\x8Ebar")
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\xE2\x80\x8Fbar")
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\xE2\x80\xADbar")
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\xE2\x80\xAEbar")
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\xE2\x80\xAAbar")
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\xE2\x80\xABbar")
+ );
+ $this->assertSame(
+ '<span dir="ltr">foobar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\xE2\x80\xACbar")
+ );
+ }
+
+ /**
+ * @covers \Fisharebest\Webtrees\Reports\RightToLeftSupport
+ *
+ * @return void
+ */
+ public function testNewLinesBecomeHTMLBreaks(): void
+ {
+ I18N::init('en-US', true);
+ $this->assertSame(
+ '<span dir="ltr">foo</span><br><span dir="ltr">bar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\nbar")
+ );
+ $this->assertSame(
+ '<span dir="rtl">אבג</span><br><span dir="rtl">דהו</span>',
+ RightToLeftSupport::spanLtrRtl("אבג\nדהו")
+ );
+
+ I18N::init('he', true);
+ $this->assertSame(
+ '<span dir="ltr">foo</span><br><span dir="ltr">bar</span>',
+ RightToLeftSupport::spanLtrRtl("foo\nbar")
+ );
+ $this->assertSame(
+ '<span dir="rtl">אבג</span><br><span dir="rtl">דהו</span>',
+ RightToLeftSupport::spanLtrRtl("אבג\nדהו")
+ );
+ }
+
+ /**
+ * @covers \Fisharebest\Webtrees\Reports\RightToLeftSupport
+ *
+ * @return void
+ */
+ public function testLineBreaks(): void
+ {
+ I18N::init('en-US', true);
+ $this->assertSame(
+ '<span dir="ltr">foo</span><br><span dir="ltr">bar</span>',
+ RightToLeftSupport::spanLtrRtl("foo<br>bar")
+ );
+ $this->assertSame(
+ '<span dir="rtl">אבג</span><br><span dir="rtl">דהו</span>',
+ RightToLeftSupport::spanLtrRtl("אבג<br>דהו")
+ );
+
+ I18N::init('he', true);
+ $this->assertSame(
+ '<span dir="ltr">foo</span><br><span dir="ltr">bar</span>',
+ RightToLeftSupport::spanLtrRtl("foo<br>bar")
+ );
+ $this->assertSame(
+ '<span dir="rtl">אבג</span><br><span dir="rtl">דהו</span>',
+ RightToLeftSupport::spanLtrRtl("אבג<br>דהו")
+ );
+ }
+
+ /**
+ * @covers \Fisharebest\Webtrees\Reports\RightToLeftSupport
+ *
+ * @return void
+ */
+ public function testHtmlEntities(): void
+ {
+ I18N::init('en-US', true);
+ $this->assertSame(
+ '<span dir="ltr">foo&nbsp;bar</span>',
+ RightToLeftSupport::spanLtrRtl("foo&nbsp;bar")
+ );
+ $this->assertSame(
+ '<span dir="rtl">אבג&nbsp;דהו</span>',
+ RightToLeftSupport::spanLtrRtl("אבג&nbsp;דהו")
+ );
+
+ I18N::init('he', true);
+ $this->assertSame(
+ '<span dir="ltr">foo&nbsp;bar</span>',
+ RightToLeftSupport::spanLtrRtl("foo&nbsp;bar")
+ );
+ $this->assertSame(
+ '<span dir="rtl">אבג&nbsp;דהו</span>',
+ RightToLeftSupport::spanLtrRtl("אבג&nbsp;דהו")
+ );
+ }
+
+ /**
+ * @covers \Fisharebest\Webtrees\Reports\RightToLeftSupport
+ *
+ * @return void
+ */
+ public function xtestLeftToRight(): void
+ {
+ $this->assertSame('<span dir="ltr">foo&eacutebar</span>', RightToLeftSupport::spanLtrRtl('foo&eacutebar'));
+ // Number
+ $this->assertSame('<span dir="ltr">foo 123,456.78 bar</span>', RightToLeftSupport::spanLtrRtl('foo 123,456.78 bar'));
+ $this->assertSame('<span dir="ltr">foo -123,456.78 bar</span>', RightToLeftSupport::spanLtrRtl('foo -123,456.78 bar'));
+ $this->assertSame('<span dir="ltr">foo +123,456.78 bar</span>', RightToLeftSupport::spanLtrRtl('foo +123,456.78 bar'));
+ $this->assertSame('<span dir="rtl">אבג</span><span dir="ltr"> ‪123,456.78‬ bar</span>', RightToLeftSupport::spanLtrRtl('אבג 123,456.78 bar'));
+ $this->assertSame('<span dir="rtl">אבג</span><span dir="ltr"> ‪-123,456.78‬ bar</span>', RightToLeftSupport::spanLtrRtl('אבג -123,456.78 bar'));
+ $this->assertSame('<span dir="rtl">אבג</span><span dir="ltr"> ‪+123,456.78‬ bar</span>', RightToLeftSupport::spanLtrRtl('אבג +123,456.78 bar'));
+ // TCPDF directive
+ $this->assertSame('<span dir="ltr">{{FOO BAR}}</span>', RightToLeftSupport::spanLtrRtl('{{FOO BAR}}'));
+ // Broken TCPDF directive
+ $this->assertSame('<span dir="ltr">{{FOO BAR</span>', RightToLeftSupport::spanLtrRtl('{{FOO BAR'));
+ // Starred name.
+ $this->assertSame('<span dir="ltr">John&nbsp;<u>Paul</u>&nbsp;Sartre</span>', RightToLeftSupport::spanLtrRtl('John <span class="starredname">Paul</span> Sartre'));
+ // Unclosed HTML tag
+ $this->assertSame('<span dir="ltr"><foo</span>', RightToLeftSupport::spanLtrRtl('<foo'));
+ // All LTR/RTL
+ $this->assertSame('<span dir="ltr">foo</span>', RightToLeftSupport::spanLtrRtl('foo'));
+ $this->assertSame('<span dir="rtl">אבג</span>', RightToLeftSupport::spanLtrRtl('אבג'));
+ // Leading/trailing spaces
+ $this->assertSame('<span dir="ltr"> foo </span>', RightToLeftSupport::spanLtrRtl(' foo '));
+ $this->assertSame('<span dir="ltr"> </span><span dir="rtl">אבג</span><span dir="ltr"> </span>', RightToLeftSupport::spanLtrRtl(' אבג '));
+ $this->assertSame('<span dir="ltr">&nbsp;foo&nbsp;</span>', RightToLeftSupport::spanLtrRtl('&nbsp;foo&nbsp;'));
+ $this->assertSame('<span dir="ltr">&nbsp;</span><span dir="rtl">אבג</span><span dir="ltr"> </span>', RightToLeftSupport::spanLtrRtl('&nbsp;אבג&nbsp;'));
+ // Spaces stick to the LTR text
+ $this->assertSame('<span dir="ltr">foo </span><span dir="rtl">אבג</span>', RightToLeftSupport::spanLtrRtl('foo אבג'));
+ $this->assertSame('<span dir="rtl">אבג</span><span dir="ltr"> foo</span>', RightToLeftSupport::spanLtrRtl('אבג foo'));
+ // Line breaks
+ $this->assertSame('<span dir="ltr">foo</span><br><span dir="rtl">אבג</span><br><span dir="ltr">bar</span>', RightToLeftSupport::spanLtrRtl('foo<br>אבג<br>bar'));
+ }
+}