From 50ef633d50e6b671322f6ef345a7adde1cd6066f Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 20:35:56 -0500 Subject: [PATCH 01/38] Update Paragraph.php - Add Pagination Also fixes hasPageBreakBefore() triggering wrong RTF tag. --- src/PhpWord/Writer/RTF/Style/Paragraph.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index 040c60b5aa..1346144126 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -94,9 +94,12 @@ public function write() $lineHeightAdjusted = (int) ($lineHeight * 240); $content .= "\\sl$lineHeightAdjusted\\slmult1"; } - if ($style->hasPageBreakBefore()) { - $content .= '\\page'; - } + + // Pagination + $content .= $this->getValueIf($style->hasWidowControl(), '\widctlpar'); + $content .= $this->getValueIf($style->isKeepNext(), '\keepn'); + $content .= $this->getValueIf($style->isKeepLines(), '\keep'); + $content .= $this->getValueIf($style->hasPageBreakBefore(), '\pagebb'); $styles = $style->getStyleValues(); $content .= $this->writeTabs($styles['tabs']); From 5e9976ed4b0f2318ab262836adb7e238b1e2a2d7 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 20:52:38 -0500 Subject: [PATCH 02/38] Update Paragraph.php - Fix widow/orphan control --- src/PhpWord/Writer/RTF/Style/Paragraph.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index 1346144126..b1e3383a0a 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -76,7 +76,7 @@ public function write() $content = ''; if ($this->nestedLevel == 0) { - $content .= '\pard\nowidctlpar '; + $content .= '\pard '; } $alignment = $style->getAlignment(); $bidi = $style->isBidi(); @@ -97,6 +97,7 @@ public function write() // Pagination $content .= $this->getValueIf($style->hasWidowControl(), '\widctlpar'); + $content .= $this->getValueIf(!$style->hasWidowControl(), '\nowidctlpar'); $content .= $this->getValueIf($style->isKeepNext(), '\keepn'); $content .= $this->getValueIf($style->isKeepLines(), '\keep'); $content .= $this->getValueIf($style->hasPageBreakBefore(), '\pagebb'); From 0c66a6515018c3d3cb391b23ced7279974ced61a Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 20:54:51 -0500 Subject: [PATCH 03/38] Update 1.5.0.md - Changelog for Pull 2824 --- docs/changes/1.x/1.5.0.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/changes/1.x/1.5.0.md b/docs/changes/1.x/1.5.0.md index b96865bada..8454d7b74e 100644 --- a/docs/changes/1.x/1.5.0.md +++ b/docs/changes/1.x/1.5.0.md @@ -7,6 +7,7 @@ ### Bug fixes - Set writeAttribute return type by [@radarhere](https://github.com/radarhere) fixing [#2204](https://github.com/PHPOffice/PHPWord/issues/2204) in [#2776](https://github.com/PHPOffice/PHPWord/pull/2776) +- Writer RTF: Add/Fix pagination in Paragraph by [@rasamassen](https://github.com/rasamassen) in [#2824](https://github.com/PHPOffice/PHPWord/pull/2824) ### Miscellaneous @@ -16,4 +17,4 @@ ### BC Breaks -### Notes \ No newline at end of file +### Notes From e61dfd6d068357026c0d5a4fe78e5a5eed7fee8b Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 20:57:25 -0500 Subject: [PATCH 04/38] Update Paragraph.php - Just making the spacing look nice. --- src/PhpWord/Writer/RTF/Style/Paragraph.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index b1e3383a0a..88df6c27de 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -76,7 +76,7 @@ public function write() $content = ''; if ($this->nestedLevel == 0) { - $content .= '\pard '; + $content .= '\pard'; } $alignment = $style->getAlignment(); $bidi = $style->isBidi(); @@ -105,7 +105,7 @@ public function write() $styles = $style->getStyleValues(); $content .= $this->writeTabs($styles['tabs']); - return $content; + return $content . ' '; } /** From 33ba3bc2e0faff68a8a6e8e00f7a43c74c904dd5 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 20:59:08 -0500 Subject: [PATCH 05/38] Update RtfEscaper2Test.php - Replace nowidctlpar with widctlpar - Widow/Orphan controls is default true. --- tests/PhpWordTests/Escaper/RtfEscaper2Test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PhpWordTests/Escaper/RtfEscaper2Test.php b/tests/PhpWordTests/Escaper/RtfEscaper2Test.php index d65b543f21..79e564ecc8 100644 --- a/tests/PhpWordTests/Escaper/RtfEscaper2Test.php +++ b/tests/PhpWordTests/Escaper/RtfEscaper2Test.php @@ -23,7 +23,7 @@ */ class RtfEscaper2Test extends \PHPUnit\Framework\TestCase { - const HEADER = '\\pard\\nowidctlpar {\\cf0\\f0 '; + const HEADER = '\\pard\\widctlpar {\\cf0\\f0 '; const TRAILER = '}\\par'; public function escapestring($str) From a547f04b7dd2a247603d3556f0b0185d1a636275 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 20:59:46 -0500 Subject: [PATCH 06/38] Update RtfEscaper3Test.php - Replace nowidctlpar with widctlpar - Widow/Orphan controls is default true. --- tests/PhpWordTests/Escaper/RtfEscaper3Test.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/PhpWordTests/Escaper/RtfEscaper3Test.php b/tests/PhpWordTests/Escaper/RtfEscaper3Test.php index 1aebea52f0..93032e06cb 100644 --- a/tests/PhpWordTests/Escaper/RtfEscaper3Test.php +++ b/tests/PhpWordTests/Escaper/RtfEscaper3Test.php @@ -25,8 +25,8 @@ */ class RtfEscaper3Test extends \PHPUnit\Framework\TestCase { - const HEADER = '\\pard\\nowidctlpar \ql{\\cf0\\f0 '; - const HEADER_RTL = '\\pard\\nowidctlpar \qr{\\rtlch\\cf0\\f0 '; + const HEADER = '\\pard\\widctlpar \ql{\\cf0\\f0 '; + const HEADER_RTL = '\\pard\\widctlpar \qr{\\rtlch\\cf0\\f0 '; const TRAILER = '}\\par'; protected function tearDown(): void From 6a4ba01508396dfd5b70835af8e25223041cf462 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 21:01:29 -0500 Subject: [PATCH 07/38] Update Element2Test.php - Replace nowidctlpar with widctlpar - Widow/Orphan controls is default true. --- tests/PhpWordTests/Writer/RTF/Element2Test.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/PhpWordTests/Writer/RTF/Element2Test.php b/tests/PhpWordTests/Writer/RTF/Element2Test.php index 2220d93b68..d2798dda1d 100644 --- a/tests/PhpWordTests/Writer/RTF/Element2Test.php +++ b/tests/PhpWordTests/Writer/RTF/Element2Test.php @@ -47,7 +47,7 @@ public function testTextRun(): void $element->addText('Hello '); $element->addText('there.'); $textrun = new WriterTextRun($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\ql{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; + $expect = "\\pard\\widctlpar \\ql{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } @@ -59,7 +59,7 @@ public function testTextRunParagraphStyle(): void $element->addText('Hello '); $element->addText('there.'); $textrun = new WriterTextRun($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\ql\\sb0\\sa0{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; + $expect = "\\pard\\widctlpar \\ql\\sb0\\sa0{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } @@ -72,7 +72,7 @@ public function testTitle(): void $section = $phpWord->addSection(); $element = $section->addTitle('First Heading', 1); $elwrite = new WriterTitle($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\ql\\sb0\\sa0{\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}"; + $expect = "\\pard\\widctlpar \\ql\\sb0\\sa0{\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}"; self::assertEquals($expect, $this->removeCr($elwrite)); Settings::setDefaultRtl(null); } From 97ddc80673d4b9e4593c997d81c2da278479e47e Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 21:01:46 -0500 Subject: [PATCH 08/38] Update ElementTest.php - Replace nowidctlpar with widctlpar - Widow/Orphan controls is default true. --- tests/PhpWordTests/Writer/RTF/ElementTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/PhpWordTests/Writer/RTF/ElementTest.php b/tests/PhpWordTests/Writer/RTF/ElementTest.php index 36504a18f8..5983b4c34e 100644 --- a/tests/PhpWordTests/Writer/RTF/ElementTest.php +++ b/tests/PhpWordTests/Writer/RTF/ElementTest.php @@ -149,7 +149,7 @@ public function testTextRun(): void $element->addText('Hello '); $element->addText('there.'); $textrun = new RTF\Element\TextRun($parentWriter, $element); - $expect = "\\pard\\nowidctlpar {{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; + $expect = "\\pard\\widctlpar {{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } @@ -160,7 +160,7 @@ public function testTextRunParagraphStyle(): void $element->addText('Hello '); $element->addText('there.'); $textrun = new RTF\Element\TextRun($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\sb0\\sa0{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; + $expect = "\\pard\\widctlpar \\sb0\\sa0{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } @@ -172,7 +172,7 @@ public function testTitle(): void $section = $phpWord->addSection(); $element = $section->addTitle('First Heading', 1); $elwrite = new RTF\Element\Title($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\sb0\\sa0{\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}"; + $expect = "\\pard\\widctlpar \\sb0\\sa0{\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}"; self::assertEquals($expect, $this->removeCr($elwrite)); } @@ -188,7 +188,7 @@ public function testRuby(): void $element->addRuby($baseTextRun, $rubyTextRun, $properties); $textrun = new RTF\Element\TextRun($parentWriter, $element); - $expect = "\\pard\\nowidctlpar {{base text (ruby)}}\\par\n"; + $expect = "\\pard\\widctlpar {{base text (ruby)}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } @@ -213,7 +213,7 @@ public function testRubyTitle(): void $element = $section->addTitle($textRun, 1); $elwrite = new RTF\Element\Title($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\sb0\\sa2{\\outlinelevel0{\\cf0\\f0\\fs48\\b base text (ruby)}\\par\n}"; + $expect = "\\pard\\widctlpar \\sb0\\sa2{\\outlinelevel0{\\cf0\\f0\\fs48\\b base text (ruby)}\\par\n}"; self::assertEquals($expect, $this->removeCr($elwrite)); } } From bf7f10b1f0a93c7f6b30ba6829483e7a5c1daefa Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 21:02:17 -0500 Subject: [PATCH 09/38] Update StyleTest.php - Replace nowidctlpar with widctlpar - Widow/Orphan controls is default true. --- tests/PhpWordTests/Writer/RTF/StyleTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/PhpWordTests/Writer/RTF/StyleTest.php b/tests/PhpWordTests/Writer/RTF/StyleTest.php index 8ba2bcb9c9..e03e68aa7e 100644 --- a/tests/PhpWordTests/Writer/RTF/StyleTest.php +++ b/tests/PhpWordTests/Writer/RTF/StyleTest.php @@ -126,7 +126,7 @@ public function testRTL(): void $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('אב גד', ['RTL' => true]); $text = new RTF\Element\Text($parentWriter, $element); - $expect = "\\pard\\nowidctlpar {\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; + $expect = "\\pard\\widctlpar {\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } @@ -136,7 +136,7 @@ public function testRTL2(): void $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('אב גד'); $text = new RTF\Element\Text($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\qr{\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; + $expect = "\\pard\\widctlpar \\qr{\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } @@ -145,7 +145,7 @@ public function testPageBreakLineHeight(): void $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('New page', null, ['lineHeight' => 1.08, 'pageBreakBefore' => true]); $text = new RTF\Element\Text($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\sl259\\slmult1\\page{\\cf0\\f0 New page}\\par\n"; + $expect = "\\pard\\widctlpar \\sl259\\slmult1\\page{\\cf0\\f0 New page}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } @@ -155,7 +155,7 @@ public function testPageBreakLineHeight2(): void $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('New page', null, ['lineHeight' => 1.08, 'pageBreakBefore' => true]); $text = new RTF\Element\Text($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\ql\\sl259\\slmult1\\page{\\cf0\\f0 New page}\\par\n"; + $expect = "\\pard\\widctlpar \\ql\\sl259\\slmult1\\page{\\cf0\\f0 New page}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } From 097c050093a5654b6192177da83b3f8c568fbfc2 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 22:45:15 -0500 Subject: [PATCH 10/38] Update RtfEscaper3Test.php - Fix Test --- tests/PhpWordTests/Escaper/RtfEscaper3Test.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/PhpWordTests/Escaper/RtfEscaper3Test.php b/tests/PhpWordTests/Escaper/RtfEscaper3Test.php index 93032e06cb..5af39f6e63 100644 --- a/tests/PhpWordTests/Escaper/RtfEscaper3Test.php +++ b/tests/PhpWordTests/Escaper/RtfEscaper3Test.php @@ -25,8 +25,8 @@ */ class RtfEscaper3Test extends \PHPUnit\Framework\TestCase { - const HEADER = '\\pard\\widctlpar \ql{\\cf0\\f0 '; - const HEADER_RTL = '\\pard\\widctlpar \qr{\\rtlch\\cf0\\f0 '; + const HEADER = '\\pard\\ql\\widctlpar {\\cf0\\f0 '; + const HEADER_RTL = '\\pard\\qr\\widctlpar {\\rtlch\\cf0\\f0 '; const TRAILER = '}\\par'; protected function tearDown(): void From fcf45f29b209b85daad9b8453583185a55a2afeb Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 22:46:29 -0500 Subject: [PATCH 11/38] Update TableTest.php - Fix test --- tests/PhpWordTests/Writer/RTF/Element/TableTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PhpWordTests/Writer/RTF/Element/TableTest.php b/tests/PhpWordTests/Writer/RTF/Element/TableTest.php index 7c1ceac68e..8f930c8773 100644 --- a/tests/PhpWordTests/Writer/RTF/Element/TableTest.php +++ b/tests/PhpWordTests/Writer/RTF/Element/TableTest.php @@ -67,7 +67,7 @@ public function testTable(): void '\\row', "\\trowd \\cellx$width \\cellx$width2 ", '\\intbl', - '\\ql{\\cf0\\f0 3}\\par', + '\\ql\\widctlpar {\\cf0\\f0 3}\\par', '\\cell', '\\intbl', '{\\cf0\\f0 4}\par', From 7e30fd61e60a0f23de711410cde95ceae37277b9 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 22:47:14 -0500 Subject: [PATCH 12/38] Update Element2Test.php - Fix Test --- tests/PhpWordTests/Writer/RTF/Element2Test.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/PhpWordTests/Writer/RTF/Element2Test.php b/tests/PhpWordTests/Writer/RTF/Element2Test.php index d2798dda1d..ed33b92e21 100644 --- a/tests/PhpWordTests/Writer/RTF/Element2Test.php +++ b/tests/PhpWordTests/Writer/RTF/Element2Test.php @@ -47,7 +47,7 @@ public function testTextRun(): void $element->addText('Hello '); $element->addText('there.'); $textrun = new WriterTextRun($parentWriter, $element); - $expect = "\\pard\\widctlpar \\ql{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; + $expect = "\\pard\\ql\\widctlpar {{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } @@ -59,7 +59,7 @@ public function testTextRunParagraphStyle(): void $element->addText('Hello '); $element->addText('there.'); $textrun = new WriterTextRun($parentWriter, $element); - $expect = "\\pard\\widctlpar \\ql\\sb0\\sa0{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; + $expect = "\\pard\\ql\\sb0\\sa0\\widctlpar {{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } @@ -72,7 +72,7 @@ public function testTitle(): void $section = $phpWord->addSection(); $element = $section->addTitle('First Heading', 1); $elwrite = new WriterTitle($parentWriter, $element); - $expect = "\\pard\\widctlpar \\ql\\sb0\\sa0{\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}"; + $expect = "\\pard\\ql\\sb0\\sa0\\widctlpar {\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}"; self::assertEquals($expect, $this->removeCr($elwrite)); Settings::setDefaultRtl(null); } From 63559b56a3620594ff1a693abc0e712b7ce69546 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 22:48:14 -0500 Subject: [PATCH 13/38] Update ElementTest.php - Fix Test --- tests/PhpWordTests/Writer/RTF/ElementTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/PhpWordTests/Writer/RTF/ElementTest.php b/tests/PhpWordTests/Writer/RTF/ElementTest.php index 5983b4c34e..8cd04996e0 100644 --- a/tests/PhpWordTests/Writer/RTF/ElementTest.php +++ b/tests/PhpWordTests/Writer/RTF/ElementTest.php @@ -160,7 +160,7 @@ public function testTextRunParagraphStyle(): void $element->addText('Hello '); $element->addText('there.'); $textrun = new RTF\Element\TextRun($parentWriter, $element); - $expect = "\\pard\\widctlpar \\sb0\\sa0{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; + $expect = "\\pard\\sb0\\sa0\\widctlpar {{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } @@ -172,7 +172,7 @@ public function testTitle(): void $section = $phpWord->addSection(); $element = $section->addTitle('First Heading', 1); $elwrite = new RTF\Element\Title($parentWriter, $element); - $expect = "\\pard\\widctlpar \\sb0\\sa0{\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}"; + $expect = "\\pard\\sb0\\sa0\\widctlpar {\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}"; self::assertEquals($expect, $this->removeCr($elwrite)); } @@ -213,7 +213,7 @@ public function testRubyTitle(): void $element = $section->addTitle($textRun, 1); $elwrite = new RTF\Element\Title($parentWriter, $element); - $expect = "\\pard\\widctlpar \\sb0\\sa2{\\outlinelevel0{\\cf0\\f0\\fs48\\b base text (ruby)}\\par\n}"; + $expect = "\\pard\\sb0\\sa2\\widctlpar {\\outlinelevel0{\\cf0\\f0\\fs48\\b base text (ruby)}\\par\n}"; self::assertEquals($expect, $this->removeCr($elwrite)); } } From 1e333b6695128d40fa4fe14a6a2b4c0322025d20 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 22:49:36 -0500 Subject: [PATCH 14/38] Update StyleTest.php - Fix test --- tests/PhpWordTests/Writer/RTF/StyleTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/PhpWordTests/Writer/RTF/StyleTest.php b/tests/PhpWordTests/Writer/RTF/StyleTest.php index e03e68aa7e..789d0e4821 100644 --- a/tests/PhpWordTests/Writer/RTF/StyleTest.php +++ b/tests/PhpWordTests/Writer/RTF/StyleTest.php @@ -136,7 +136,7 @@ public function testRTL2(): void $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('אב גד'); $text = new RTF\Element\Text($parentWriter, $element); - $expect = "\\pard\\widctlpar \\qr{\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; + $expect = "\\pard\\qr\\widctlpar {\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } @@ -145,7 +145,7 @@ public function testPageBreakLineHeight(): void $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('New page', null, ['lineHeight' => 1.08, 'pageBreakBefore' => true]); $text = new RTF\Element\Text($parentWriter, $element); - $expect = "\\pard\\widctlpar \\sl259\\slmult1\\page{\\cf0\\f0 New page}\\par\n"; + $expect = "\\pard\\sl259\\slmult1\\widctlpar\\pagebb {\\cf0\\f0 New page}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } @@ -155,7 +155,7 @@ public function testPageBreakLineHeight2(): void $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('New page', null, ['lineHeight' => 1.08, 'pageBreakBefore' => true]); $text = new RTF\Element\Text($parentWriter, $element); - $expect = "\\pard\\widctlpar \\ql\\sl259\\slmult1\\page{\\cf0\\f0 New page}\\par\n"; + $expect = "\\pard\\ql\\sl259\\slmult1\\widctlpar\\pagebb {\\cf0\\f0 New page}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } From b8aac4856726fd1d9b255a647e3adab694be1e58 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 22:56:39 -0500 Subject: [PATCH 15/38] Update TableTest.php - Fix test --- tests/PhpWordTests/Writer/RTF/Element/TableTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/PhpWordTests/Writer/RTF/Element/TableTest.php b/tests/PhpWordTests/Writer/RTF/Element/TableTest.php index 8f930c8773..182d0e7199 100644 --- a/tests/PhpWordTests/Writer/RTF/Element/TableTest.php +++ b/tests/PhpWordTests/Writer/RTF/Element/TableTest.php @@ -59,7 +59,7 @@ public function testTable(): void '\\pard', "\\trowd \\cellx$width \\cellx$width2 ", '\\intbl', - '\\ql{\\cf0\\f0 1}\\par', + '\\ql\\widctlpar {\\cf0\\f0 1}\\par', '\\cell', '\\intbl', '{\\cf0\\f0 2}\\par', @@ -70,7 +70,7 @@ public function testTable(): void '\\ql\\widctlpar {\\cf0\\f0 3}\\par', '\\cell', '\\intbl', - '{\\cf0\\f0 4}\par', + '\\widctlpar {\\cf0\\f0 4}\par', '\\cell', '\\row', '\\pard', @@ -102,7 +102,7 @@ public function testTableStyle(): void '\\clbrdrr\\brdrs\\brdrw2\\brdrcf0', "\\cellx$width ", '\\intbl', - '\\ql{\\cf0\\f0 1}\\par', + '\\ql\\widctlpar {\\cf0\\f0 1}\\par', '\\cell', '\\row', '\\pard', @@ -128,7 +128,7 @@ public function testTableStyleNotExisting(): void '\\pard', "\\trowd \\cellx$width ", '\\intbl', - '\\ql{\\cf0\\f0 1}\\par', + '\\ql\\widctlpar {\\cf0\\f0 1}\\par', '\\cell', '\\row', '\\pard', @@ -158,7 +158,7 @@ public function testTableCellStyle(): void '\\clbrdrr\\brdrdot\\brdrw2\\brdrcf0', "\\cellx$width ", '\\intbl', - '\\ql{\\cf0\\f0 1}\\par', + '\\ql\\widctlpar {\\cf0\\f0 1}\\par', '\\cell', '\\row', '\\pard', From 5c22beb8b24de03a47f891241dbdf616e8733a2a Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 23:01:38 -0500 Subject: [PATCH 16/38] Update TableTest.php - Hopefully final Fix test --- tests/PhpWordTests/Writer/RTF/Element/TableTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/PhpWordTests/Writer/RTF/Element/TableTest.php b/tests/PhpWordTests/Writer/RTF/Element/TableTest.php index 182d0e7199..0158e21260 100644 --- a/tests/PhpWordTests/Writer/RTF/Element/TableTest.php +++ b/tests/PhpWordTests/Writer/RTF/Element/TableTest.php @@ -59,7 +59,7 @@ public function testTable(): void '\\pard', "\\trowd \\cellx$width \\cellx$width2 ", '\\intbl', - '\\ql\\widctlpar {\\cf0\\f0 1}\\par', + '\\widctlpar {\\cf0\\f0 1}\\par', '\\cell', '\\intbl', '{\\cf0\\f0 2}\\par', @@ -67,10 +67,10 @@ public function testTable(): void '\\row', "\\trowd \\cellx$width \\cellx$width2 ", '\\intbl', - '\\ql\\widctlpar {\\cf0\\f0 3}\\par', + '\\widctlpar {\\cf0\\f0 3}\\par', '\\cell', '\\intbl', - '\\widctlpar {\\cf0\\f0 4}\par', + '{\\cf0\\f0 4}\par', '\\cell', '\\row', '\\pard', From d7045a212320d65c5622bc5f0a00b69e2d888ea0 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 23:04:14 -0500 Subject: [PATCH 17/38] Update TableTest.php - Fix test --- tests/PhpWordTests/Writer/RTF/Element/TableTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/PhpWordTests/Writer/RTF/Element/TableTest.php b/tests/PhpWordTests/Writer/RTF/Element/TableTest.php index 0158e21260..df8c0e6258 100644 --- a/tests/PhpWordTests/Writer/RTF/Element/TableTest.php +++ b/tests/PhpWordTests/Writer/RTF/Element/TableTest.php @@ -59,7 +59,7 @@ public function testTable(): void '\\pard', "\\trowd \\cellx$width \\cellx$width2 ", '\\intbl', - '\\widctlpar {\\cf0\\f0 1}\\par', + '\\ql\\widctlpar {\\cf0\\f0 1}\\par', '\\cell', '\\intbl', '{\\cf0\\f0 2}\\par', @@ -67,7 +67,7 @@ public function testTable(): void '\\row', "\\trowd \\cellx$width \\cellx$width2 ", '\\intbl', - '\\widctlpar {\\cf0\\f0 3}\\par', + '\\ql\\widctlpar {\\cf0\\f0 3}\\par', '\\cell', '\\intbl', '{\\cf0\\f0 4}\par', From 3d63e9614c47d973cf82bfba077dc401e1386208 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Mon, 8 Sep 2025 23:05:02 -0500 Subject: [PATCH 18/38] Update ElementTest.php - Fix tests --- tests/PhpWordTests/Writer/RTF/ElementTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/PhpWordTests/Writer/RTF/ElementTest.php b/tests/PhpWordTests/Writer/RTF/ElementTest.php index 8cd04996e0..1c2de17ca7 100644 --- a/tests/PhpWordTests/Writer/RTF/ElementTest.php +++ b/tests/PhpWordTests/Writer/RTF/ElementTest.php @@ -121,7 +121,7 @@ public function testTable(): void '\\pard', "\\trowd \\cellx$width \\cellx$width2 ", '\\intbl', - '{\\cf0\\f0 1}\\par', + '\\widctlpar {\\cf0\\f0 1}\\par', '\\cell', '\\intbl', '{\\cf0\\f0 2}\\par', @@ -129,7 +129,7 @@ public function testTable(): void '\\row', "\\trowd \\cellx$width \\cellx$width2 ", '\\intbl', - '{\\cf0\\f0 3}\\par', + '\\widctlpar {\\cf0\\f0 3}\\par', '\\cell', '\\intbl', '{\\cf0\\f0 4}\par', From 06c7c8598e28f2264ff1509c12a05d56f282aee0 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 17:50:37 -0500 Subject: [PATCH 19/38] Update Paragraph.php - Fix deprecated features --- src/PhpWord/Writer/RTF/Style/Paragraph.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index 88df6c27de..88e599ea5d 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -36,9 +36,9 @@ class Paragraph extends AbstractStyle */ private $nestedLevel = 0; - private const LEFT = Jc::LEFT; - private const RIGHT = Jc::RIGHT; - private const JUSTIFY = Jc::JUSTIFY; + private const LEFT = Jc::START; + private const RIGHT = Jc::END; + private const JUSTIFY = Jc::BOTH; /** * Write style. From 66de8748c7ad242d46e0b6264d319ded91edc2d7 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 18:08:54 -0500 Subject: [PATCH 20/38] Update Paragraph.php - Fix justification, add missing options. --- src/PhpWord/Writer/RTF/Style/Paragraph.php | 26 +++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index 88e599ea5d..3148d882fb 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -36,10 +36,6 @@ class Paragraph extends AbstractStyle */ private $nestedLevel = 0; - private const LEFT = Jc::START; - private const RIGHT = Jc::END; - private const JUSTIFY = Jc::BOTH; - /** * Write style. * @@ -57,18 +53,28 @@ public function write() Jc::END => '\qr', Jc::CENTER => '\qc', Jc::BOTH => '\qj', - self::LEFT => '\ql', - self::RIGHT => '\qr', - self::JUSTIFY => '\qj', + Jc::LEFT => '\ql', + Jc::RIGHT => '\qr', + Jc::JUSTIFY => '\qj', + Jc::DISTRIBUTE => '\qd', + Jc::THAI_DISTRIBUTE => '\qt', + Jc::HIGH_KASHIDA => '\qk20', + Jc::MEDIUM_KASHIDA => '\qk10', + Jc::LOW_KASHIDA => '\qk0', ]; $bidiAlignments = [ Jc::START => '\qr', Jc::END => '\ql', Jc::CENTER => '\qc', Jc::BOTH => '\qj', - self::LEFT => '\ql', - self::RIGHT => '\qr', - self::JUSTIFY => '\qj', + Jc::LEFT => '\ql', + Jc::RIGHT => '\qr', + Jc::JUSTIFY => '\qj', + Jc::DISTRIBUTE => '\qd', + Jc::THAI_DISTRIBUTE => '\qt', + Jc::HIGH_KASHIDA => '\qk20', + Jc::MEDIUM_KASHIDA => '\qk10', + Jc::LOW_KASHIDA => '\qk0', ]; $spaceAfter = $style->getSpaceAfter(); From 0c7f3b252ee1ac56670485e2b664d220f41e198b Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 18:10:42 -0500 Subject: [PATCH 21/38] Create ParagraphTest.php - Initial build --- .../Writer/RTF/Style/ParagraphTest.php | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php diff --git a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php new file mode 100644 index 0000000000..e7bd22859e --- /dev/null +++ b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php @@ -0,0 +1,55 @@ +write()); + } + + /** + * Test alignment. + * See page 79 of RTF Specification 1.9.1. + */ + public function testParagraphAlign(): void + { + $parentWriter = new RTF(); + $style = new ParagraphStyle()->setAlignment(Jc::START); + $writer = new ParagraphWriter($parentWriter, $style); + $expect = "\\pard\\ql "; + self::assertEquals($expect, $this->removeCr($writer)); + } +} From 1a8897fb01a7283ddd85781f18a1a75ff16a00f9 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 18:14:26 -0500 Subject: [PATCH 22/38] Update ParagraphTest.php --- tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php index e7bd22859e..567667f74b 100644 --- a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php @@ -47,7 +47,8 @@ public function removeCr($field): string public function testParagraphAlign(): void { $parentWriter = new RTF(); - $style = new ParagraphStyle()->setAlignment(Jc::START); + $style = new ParagraphStyle(); + $style->setAlignment(Jc::START); $writer = new ParagraphWriter($parentWriter, $style); $expect = "\\pard\\ql "; self::assertEquals($expect, $this->removeCr($writer)); From 953cc31adb961ec73bb1e26fa28198a8ee51d651 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 18:21:38 -0500 Subject: [PATCH 23/38] Update ParagraphTest.php --- tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php index 567667f74b..ca5573dc3b 100644 --- a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php @@ -16,7 +16,7 @@ * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ -namespace PhpOffice\PhpWordTests\Writer\RTF\Styke; +namespace PhpOffice\PhpWordTests\Writer\RTF\Style; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\Style\Paragraph as ParagraphStyle; @@ -49,7 +49,8 @@ public function testParagraphAlign(): void $parentWriter = new RTF(); $style = new ParagraphStyle(); $style->setAlignment(Jc::START); - $writer = new ParagraphWriter($parentWriter, $style); + $writer = new ParagraphWriter($style); + $writer->setParentWriter($parentWriter); $expect = "\\pard\\ql "; self::assertEquals($expect, $this->removeCr($writer)); } From 6eb482a29eb9d608e55cbcc1805a8f66da342c3c Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 18:25:43 -0500 Subject: [PATCH 24/38] Update ParagraphTest.php --- tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php index ca5573dc3b..b314767390 100644 --- a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php @@ -51,7 +51,11 @@ public function testParagraphAlign(): void $style->setAlignment(Jc::START); $writer = new ParagraphWriter($style); $writer->setParentWriter($parentWriter); - $expect = "\\pard\\ql "; + $expect = '\\pard\\ql\\widctlpar '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setAlignment(Jc::CENTER); + $expect = '\\pard\\qc\\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); } } From 5aa739649973ef7d18dccd0f6f397e68aab160d0 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 19:02:49 -0500 Subject: [PATCH 25/38] Update ParagraphTest.php - Add tests --- .../Writer/RTF/Style/ParagraphTest.php | 110 +++++++++++++++++- 1 file changed, 108 insertions(+), 2 deletions(-) diff --git a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php index b314767390..e1b49f14ed 100644 --- a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php @@ -18,9 +18,10 @@ namespace PhpOffice\PhpWordTests\Writer\RTF\Style; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\SimpleType\Jc; +use PhpOffice\PhpWord\SimpleType\LineSpacingRule; use PhpOffice\PhpWord\Style\Paragraph as ParagraphStyle; -use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Writer\RTF; use PhpOffice\PhpWord\Writer\RTF\Style\Paragraph as ParagraphWriter; use PHPUnit\Framework\TestCase; @@ -57,5 +58,110 @@ public function testParagraphAlign(): void $style->setAlignment(Jc::CENTER); $expect = '\\pard\\qc\\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); - } + + $style->setAlignment(Jc::END); + $expect = '\\pard\\qr\\widctlpar '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setAlignment(Jc::BOTH); + $expect = '\\pard\\qj\\widctlpar '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setAlignment(Jc::DISTRIBUTE); + $expect = '\\pard\\qd\\widctlpar '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setAlignment(Jc::THAI_DISTRIBUTE); + $expect = '\\pard\\qt\\widctlpar '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setAlignment(Jc::HIGH_KASHIDA); + $expect = '\\pard\\qk20\\widctlpar '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setAlignment(Jc::MEDIUM_KASHIDA); + $expect = '\\pard\\qk10\\widctlpar '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setAlignment(Jc::LOW_KASHIDA); + $expect = '\\pard\\qk0\\widctlpar '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setAlignment(Jc::START); + $style->setBidi(true); + $expect = '\\pard\\qr\\widctlpar '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setAlignment(Jc::END); + $style->setBidi(true); + $expect = '\\pard\\ql\\widctlpar '; + self::assertEquals($expect, $this->removeCr($writer)); + } + + /** + * Test indentation. + * See PHPOFfice\Tests\Writer\RTF\Style\IndentationTest + */ + + /** + * Test formatting. + * See page 79 of RTF Specification 1.9.1. + */ + public function testParagraphFormatting(): void + { + $parentWriter = new RTF(); + $style = new ParagraphStyle(); + $style->setSuppressAutoHyphens(true); + $style->setKeepLines(true); + $style->setKeepNext(true); + $style->setWidowControl(true); + $style->setPageBreakBefore(true); + $writer = new ParagraphWriter($style); + $writer->setParentWriter($parentWriter); + $expect = '\\pard\\widctlpar\\keepn\\keep\\pagebb\\hyphpar '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setSuppressAutoHyphens(false); + $style->setKeepLines(false); + $style->setKeepNext(false); + $style->setWidowControl(false); + $style->setPageBreakBefore(false); + $expect = '\\pard\\nowidctlpar '; + self::assertEquals($expect, $this->removeCr($writer)); + } + + /** + * Test spacing. + * See page 80 of RTF Specification 1.9.1. + */ + public function testParagraphSpacing(): void + { + $parentWriter = new RTF(); + $style = new ParagraphStyle(); + $style->setSpaceBefore(240); + $style->setSpaceAfter(120); + $style->setLineHeight(1.5); + $style->setContextualSpacing(false); + $writer = new ParagraphWriter($style); + $writer->setParentWriter($parentWriter); + $expect = '\\pard\\sb240\\sa120\\sl360\\simult1\\widctlpar '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setSpaceBefore(480); + $style->setSpaceAfter(360); + $style->setSpacing(30); + $style->setSpacingLineRule(LineSpacingRule::EXACT); + $style->setContextualSpacing(true); + $expect = '\\pard\\sb480\\sa360\\sl30\\simult0\\contextualspace\\widctlpar '; + self::assertEquals($expect, $this->removeCr($writer)); + } + + /** + * Test tabs. + * See PHPOFfice\Tests\Writer\RTF\Style\TabTest + */ + + /** + * Not Done: basedOn, next, numLevel, numStyle, shading, textAlignment. + */ } From eecc70d455b37032b5258e89557d7882b93b023e Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 19:16:42 -0500 Subject: [PATCH 26/38] Update Paragraph.php - add missing features --- src/PhpWord/Writer/RTF/Style/Paragraph.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index 3148d882fb..08e624c949 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -100,6 +100,7 @@ public function write() $lineHeightAdjusted = (int) ($lineHeight * 240); $content .= "\\sl$lineHeightAdjusted\\slmult1"; } + $content .= $this->getValueIf($style->hasContextualSpacing(), '\contextualspace'); // Pagination $content .= $this->getValueIf($style->hasWidowControl(), '\widctlpar'); @@ -107,6 +108,7 @@ public function write() $content .= $this->getValueIf($style->isKeepNext(), '\keepn'); $content .= $this->getValueIf($style->isKeepLines(), '\keep'); $content .= $this->getValueIf($style->hasPageBreakBefore(), '\pagebb'); + $content .= $this->getValueIf($style->hasSuppressAutoHyphens(), '\hyphpar0'); $styles = $style->getStyleValues(); $content .= $this->writeTabs($styles['tabs']); From f43e923c3df6d722382521ed761b396d5211b173 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 19:16:46 -0500 Subject: [PATCH 27/38] Update ParagraphTest.php --- .../Writer/RTF/Style/ParagraphTest.php | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php index e1b49f14ed..d1defe1dd1 100644 --- a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php @@ -49,9 +49,10 @@ public function testParagraphAlign(): void { $parentWriter = new RTF(); $style = new ParagraphStyle(); - $style->setAlignment(Jc::START); $writer = new ParagraphWriter($style); $writer->setParentWriter($parentWriter); + + $style->setAlignment(Jc::START); $expect = '\\pard\\ql\\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); @@ -62,7 +63,7 @@ public function testParagraphAlign(): void $style->setAlignment(Jc::END); $expect = '\\pard\\qr\\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); - + $style->setAlignment(Jc::BOTH); $expect = '\\pard\\qj\\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); @@ -96,11 +97,11 @@ public function testParagraphAlign(): void $style->setBidi(true); $expect = '\\pard\\ql\\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); - } + } /** * Test indentation. - * See PHPOFfice\Tests\Writer\RTF\Style\IndentationTest + * See PHPOFfice\Tests\Writer\RTF\Style\IndentationTest. */ /** @@ -111,14 +112,15 @@ public function testParagraphFormatting(): void { $parentWriter = new RTF(); $style = new ParagraphStyle(); + $writer = new ParagraphWriter($style); + $writer->setParentWriter($parentWriter); + $style->setSuppressAutoHyphens(true); $style->setKeepLines(true); $style->setKeepNext(true); $style->setWidowControl(true); $style->setPageBreakBefore(true); - $writer = new ParagraphWriter($style); - $writer->setParentWriter($parentWriter); - $expect = '\\pard\\widctlpar\\keepn\\keep\\pagebb\\hyphpar '; + $expect = '\\pard\\widctlpar\\keepn\\keep\\pagebb\\hyphpar0 '; self::assertEquals($expect, $this->removeCr($writer)); $style->setSuppressAutoHyphens(false); @@ -128,7 +130,7 @@ public function testParagraphFormatting(): void $style->setPageBreakBefore(false); $expect = '\\pard\\nowidctlpar '; self::assertEquals($expect, $this->removeCr($writer)); - } + } /** * Test spacing. @@ -138,13 +140,14 @@ public function testParagraphSpacing(): void { $parentWriter = new RTF(); $style = new ParagraphStyle(); + $writer = new ParagraphWriter($style); + $writer->setParentWriter($parentWriter); + $style->setSpaceBefore(240); $style->setSpaceAfter(120); $style->setLineHeight(1.5); $style->setContextualSpacing(false); - $writer = new ParagraphWriter($style); - $writer->setParentWriter($parentWriter); - $expect = '\\pard\\sb240\\sa120\\sl360\\simult1\\widctlpar '; + $expect = '\\pard\\sb240\\sa120\\sl360\\slmult1\\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); $style->setSpaceBefore(480); @@ -152,13 +155,13 @@ public function testParagraphSpacing(): void $style->setSpacing(30); $style->setSpacingLineRule(LineSpacingRule::EXACT); $style->setContextualSpacing(true); - $expect = '\\pard\\sb480\\sa360\\sl30\\simult0\\contextualspace\\widctlpar '; + $expect = '\\pard\\sb480\\sa360\\sl30\\slmult0\\contextualspace\\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); - } + } /** * Test tabs. - * See PHPOFfice\Tests\Writer\RTF\Style\TabTest + * See PHPOFfice\Tests\Writer\RTF\Style\TabTest. */ /** From d238a7ea695bd46c1414bd130a0c159cefd271b4 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 19:28:14 -0500 Subject: [PATCH 28/38] Update Paragraph.php - add spacing and spacingLineRule --- src/PhpWord/Writer/RTF/Style/Paragraph.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index 08e624c949..a4fff1bc70 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -19,6 +19,7 @@ namespace PhpOffice\PhpWord\Writer\RTF\Style; use PhpOffice\PhpWord\SimpleType\Jc; +use PhpOffice\PhpWord\SimpleType\LineSpacingRule; /** * RTF paragraph style writer. @@ -76,6 +77,11 @@ public function write() Jc::MEDIUM_KASHIDA => '\qk10', Jc::LOW_KASHIDA => '\qk0', ]; + $spacingRules = [ + LineSpacingRule::AUTO => '\slmult1', + LineSpacingRule::EXACT => '\slmult0', + LineSpacingRule::AT_LEAST => '\slmult0', + ]; $spaceAfter = $style->getSpaceAfter(); $spaceBefore = $style->getSpaceBefore(); @@ -98,8 +104,15 @@ public function write() $lineHeight = $style->getLineHeight(); if ($lineHeight) { $lineHeightAdjusted = (int) ($lineHeight * 240); - $content .= "\\sl$lineHeightAdjusted\\slmult1"; + $content .= "\\sl$lineHeightAdjusted"; + } else { + $content .= $this->getValueIf($style->getSpacing() !== null, '\sl' . round($style->getSpacing() ?? 0)); + $spacingRule = $style->getSpacingLineRule(); + if (isset($spacingRules[$spacingRule])) { + $content .= $spacingRules[$spacingRule]; + } } + $content .= $this->getValueIf($style->hasContextualSpacing(), '\contextualspace'); // Pagination From 995692f209b4f2a2fc0c29f39d45b3a3ab7a0c8c Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 19:28:17 -0500 Subject: [PATCH 29/38] Update ParagraphTest.php --- tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php index d1defe1dd1..6d1e904e48 100644 --- a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php @@ -150,6 +150,7 @@ public function testParagraphSpacing(): void $expect = '\\pard\\sb240\\sa120\\sl360\\slmult1\\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); + $style = new ParagraphStyle(); $style->setSpaceBefore(480); $style->setSpaceAfter(360); $style->setSpacing(30); From 0b08710359b7b03b888315d8012b17d6025603e8 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 19:31:50 -0500 Subject: [PATCH 30/38] Update Paragraph.php --- src/PhpWord/Writer/RTF/Style/Paragraph.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index a4fff1bc70..a8a023eb76 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -109,10 +109,10 @@ public function write() $content .= $this->getValueIf($style->getSpacing() !== null, '\sl' . round($style->getSpacing() ?? 0)); $spacingRule = $style->getSpacingLineRule(); if (isset($spacingRules[$spacingRule])) { - $content .= $spacingRules[$spacingRule]; + $content .= $this->getValueIf($style->getSpacing() !== null$spacingRules[$spacingRule]); } } - + $content .= $this->getValueIf($style->hasContextualSpacing(), '\contextualspace'); // Pagination From 7d4ce32bf658dfad7297a327692ddd5287ac88cc Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 19:33:01 -0500 Subject: [PATCH 31/38] Update Paragraph.php --- src/PhpWord/Writer/RTF/Style/Paragraph.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index a8a023eb76..42cd8fb3ea 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -108,9 +108,9 @@ public function write() } else { $content .= $this->getValueIf($style->getSpacing() !== null, '\sl' . round($style->getSpacing() ?? 0)); $spacingRule = $style->getSpacingLineRule(); - if (isset($spacingRules[$spacingRule])) { - $content .= $this->getValueIf($style->getSpacing() !== null$spacingRules[$spacingRule]); - } + } + if (isset($spacingRules[$spacingRule])) { + $content .= $this->getValueIf($style->getSpacing() !== null$spacingRules[$spacingRule]); } $content .= $this->getValueIf($style->hasContextualSpacing(), '\contextualspace'); From ff94ce8a578e6d0422ccc6fabb554d1d9ac53388 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 19:35:47 -0500 Subject: [PATCH 32/38] Update Paragraph.php --- src/PhpWord/Writer/RTF/Style/Paragraph.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index 42cd8fb3ea..d043488be2 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -110,7 +110,7 @@ public function write() $spacingRule = $style->getSpacingLineRule(); } if (isset($spacingRules[$spacingRule])) { - $content .= $this->getValueIf($style->getSpacing() !== null$spacingRules[$spacingRule]); + $content .= $this->getValueIf($style->getSpacing() !== null, $spacingRules[$spacingRule]); } $content .= $this->getValueIf($style->hasContextualSpacing(), '\contextualspace'); From 9143d56065c4010c88bbc90eae9116a46f4a7cbf Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 19:40:11 -0500 Subject: [PATCH 33/38] Update Paragraph.php --- src/PhpWord/Writer/RTF/Style/Paragraph.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index d043488be2..92711097b8 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -98,6 +98,7 @@ public function write() if (isset($alignments[$alignment])) { $content .= $bidi ? $bidiAlignments[$alignment] : $alignments[$alignment]; } + $content .= $this->getValueIf($style->isBidi(), '\rtlpar'); $content .= $this->writeIndentation($style->getIndentation()); $content .= $this->getValueIf($spaceBefore !== null, '\sb' . round($spaceBefore ?? 0)); $content .= $this->getValueIf($spaceAfter !== null, '\sa' . round($spaceAfter ?? 0)); @@ -107,8 +108,8 @@ public function write() $content .= "\\sl$lineHeightAdjusted"; } else { $content .= $this->getValueIf($style->getSpacing() !== null, '\sl' . round($style->getSpacing() ?? 0)); - $spacingRule = $style->getSpacingLineRule(); } + $spacingRule = $style->getSpacingLineRule(); if (isset($spacingRules[$spacingRule])) { $content .= $this->getValueIf($style->getSpacing() !== null, $spacingRules[$spacingRule]); } From fcba983fac5915638f6f965e832e8bb2eef9aa3e Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 19:51:37 -0500 Subject: [PATCH 34/38] Update ParagraphTest.php --- .../Writer/RTF/Style/ParagraphTest.php | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php index 6d1e904e48..c8ab8a9499 100644 --- a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php @@ -43,7 +43,8 @@ public function removeCr($field): string /** * Test alignment. - * See page 79 of RTF Specification 1.9.1. + * See page 79 of RTF Specification 1.9.1 for Alignment. + * See page 81 of RTF Specification 1.9.1 for Bidirectional Controls. */ public function testParagraphAlign(): void { @@ -53,49 +54,49 @@ public function testParagraphAlign(): void $writer->setParentWriter($parentWriter); $style->setAlignment(Jc::START); - $expect = '\\pard\\ql\\widctlpar '; + $expect = '\pard\ql\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); $style->setAlignment(Jc::CENTER); - $expect = '\\pard\\qc\\widctlpar '; + $expect = '\pard\qc\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); $style->setAlignment(Jc::END); - $expect = '\\pard\\qr\\widctlpar '; + $expect = '\pard\qr\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); $style->setAlignment(Jc::BOTH); - $expect = '\\pard\\qj\\widctlpar '; + $expect = '\pard\qj\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); $style->setAlignment(Jc::DISTRIBUTE); - $expect = '\\pard\\qd\\widctlpar '; + $expect = '\pard\qd\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); $style->setAlignment(Jc::THAI_DISTRIBUTE); - $expect = '\\pard\\qt\\widctlpar '; + $expect = '\pard\qt\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); $style->setAlignment(Jc::HIGH_KASHIDA); - $expect = '\\pard\\qk20\\widctlpar '; + $expect = '\pard\qk20\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); $style->setAlignment(Jc::MEDIUM_KASHIDA); - $expect = '\\pard\\qk10\\widctlpar '; + $expect = '\pard\qk10\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); $style->setAlignment(Jc::LOW_KASHIDA); - $expect = '\\pard\\qk0\\widctlpar '; + $expect = '\pard\qk0\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); $style->setAlignment(Jc::START); $style->setBidi(true); - $expect = '\\pard\\qr\\widctlpar '; + $expect = '\pard\qr\rtlpar\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); $style->setAlignment(Jc::END); $style->setBidi(true); - $expect = '\\pard\\ql\\widctlpar '; + $expect = '\pard\ql\rtlpar\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); } @@ -106,7 +107,7 @@ public function testParagraphAlign(): void /** * Test formatting. - * See page 79 of RTF Specification 1.9.1. + * See page 78 of RTF Specification 1.9.1 for Formatting. */ public function testParagraphFormatting(): void { @@ -120,7 +121,7 @@ public function testParagraphFormatting(): void $style->setKeepNext(true); $style->setWidowControl(true); $style->setPageBreakBefore(true); - $expect = '\\pard\\widctlpar\\keepn\\keep\\pagebb\\hyphpar0 '; + $expect = '\pard\widctlpar\keepn\keep\pagebb\hyphpar0 '; self::assertEquals($expect, $this->removeCr($writer)); $style->setSuppressAutoHyphens(false); @@ -128,13 +129,13 @@ public function testParagraphFormatting(): void $style->setKeepNext(false); $style->setWidowControl(false); $style->setPageBreakBefore(false); - $expect = '\\pard\\nowidctlpar '; + $expect = '\pard\nowidctlpar '; self::assertEquals($expect, $this->removeCr($writer)); } /** * Test spacing. - * See page 80 of RTF Specification 1.9.1. + * See page 80 of RTF Specification 1.9.1 for Spacing. */ public function testParagraphSpacing(): void { @@ -147,16 +148,19 @@ public function testParagraphSpacing(): void $style->setSpaceAfter(120); $style->setLineHeight(1.5); $style->setContextualSpacing(false); - $expect = '\\pard\\sb240\\sa120\\sl360\\slmult1\\widctlpar '; + $expect = '\pard\sb240\sa120\sl360\slmult1\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); $style = new ParagraphStyle(); + $writer = new ParagraphWriter($style); + $writer->setParentWriter($parentWriter); + $style->setSpaceBefore(480); $style->setSpaceAfter(360); $style->setSpacing(30); $style->setSpacingLineRule(LineSpacingRule::EXACT); $style->setContextualSpacing(true); - $expect = '\\pard\\sb480\\sa360\\sl30\\slmult0\\contextualspace\\widctlpar '; + $expect = '\pard\sb480\sa360\sl30\slmult0\contextualspace\widctlpar '; self::assertEquals($expect, $this->removeCr($writer)); } From cbb2cbd57699fc308695d765242df3bd041512dd Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 19:55:47 -0500 Subject: [PATCH 35/38] Update StyleTest.php --- tests/PhpWordTests/Writer/RTF/StyleTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PhpWordTests/Writer/RTF/StyleTest.php b/tests/PhpWordTests/Writer/RTF/StyleTest.php index 789d0e4821..bd0e452476 100644 --- a/tests/PhpWordTests/Writer/RTF/StyleTest.php +++ b/tests/PhpWordTests/Writer/RTF/StyleTest.php @@ -136,7 +136,7 @@ public function testRTL2(): void $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('אב גד'); $text = new RTF\Element\Text($parentWriter, $element); - $expect = "\\pard\\qr\\widctlpar {\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; + $expect = "\\pard\\qr\\rtlpar\\widctlpar {\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } From 2c4c25d9b9a2bfc3fb8d86d0761837454c5c9d10 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 19:56:24 -0500 Subject: [PATCH 36/38] Update RtfEscaper3Test.php --- tests/PhpWordTests/Escaper/RtfEscaper3Test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PhpWordTests/Escaper/RtfEscaper3Test.php b/tests/PhpWordTests/Escaper/RtfEscaper3Test.php index 5af39f6e63..1460db0e0f 100644 --- a/tests/PhpWordTests/Escaper/RtfEscaper3Test.php +++ b/tests/PhpWordTests/Escaper/RtfEscaper3Test.php @@ -26,7 +26,7 @@ class RtfEscaper3Test extends \PHPUnit\Framework\TestCase { const HEADER = '\\pard\\ql\\widctlpar {\\cf0\\f0 '; - const HEADER_RTL = '\\pard\\qr\\widctlpar {\\rtlch\\cf0\\f0 '; + const HEADER_RTL = '\\pard\\qr\\rtlpar\\widctlpar {\\rtlch\\cf0\\f0 '; const TRAILER = '}\\par'; protected function tearDown(): void From 0516d307f654324321f2d75b38c4609ccc28812d Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 19:58:35 -0500 Subject: [PATCH 37/38] Update ParagraphTest.php --- tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php index c8ab8a9499..007a6d8373 100644 --- a/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Writer/RTF/Style/ParagraphTest.php @@ -154,7 +154,7 @@ public function testParagraphSpacing(): void $style = new ParagraphStyle(); $writer = new ParagraphWriter($style); $writer->setParentWriter($parentWriter); - + $style->setSpaceBefore(480); $style->setSpaceAfter(360); $style->setSpacing(30); From b394c75c3c8e34307f0e20fcbb8a940976497007 Mon Sep 17 00:00:00 2001 From: rasamassen Date: Fri, 3 Oct 2025 20:03:16 -0500 Subject: [PATCH 38/38] Update 1.5.0.md --- docs/changes/1.x/1.5.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changes/1.x/1.5.0.md b/docs/changes/1.x/1.5.0.md index 8454d7b74e..c5ede40ead 100644 --- a/docs/changes/1.x/1.5.0.md +++ b/docs/changes/1.x/1.5.0.md @@ -7,7 +7,7 @@ ### Bug fixes - Set writeAttribute return type by [@radarhere](https://github.com/radarhere) fixing [#2204](https://github.com/PHPOffice/PHPWord/issues/2204) in [#2776](https://github.com/PHPOffice/PHPWord/pull/2776) -- Writer RTF: Add/Fix pagination in Paragraph by [@rasamassen](https://github.com/rasamassen) in [#2824](https://github.com/PHPOffice/PHPWord/pull/2824) +- Writer RTF: Add multiple missing controls and fix existing controls in Paragraph by [@rasamassen](https://github.com/rasamassen) in [#2824](https://github.com/PHPOffice/PHPWord/pull/2824) ### Miscellaneous