Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
50ef633
Update Paragraph.php - Add Pagination
rasamassen Sep 9, 2025
5e9976e
Update Paragraph.php - Fix widow/orphan control
rasamassen Sep 9, 2025
0c66a65
Update 1.5.0.md - Changelog for Pull 2824
rasamassen Sep 9, 2025
e61dfd6
Update Paragraph.php - Just making the spacing look nice.
rasamassen Sep 9, 2025
33ba3bc
Update RtfEscaper2Test.php - Replace nowidctlpar with widctlpar - Wid…
rasamassen Sep 9, 2025
a547f04
Update RtfEscaper3Test.php - Replace nowidctlpar with widctlpar - Wid…
rasamassen Sep 9, 2025
6a4ba01
Update Element2Test.php - Replace nowidctlpar with widctlpar - Widow/…
rasamassen Sep 9, 2025
97ddc80
Update ElementTest.php - Replace nowidctlpar with widctlpar - Widow/O…
rasamassen Sep 9, 2025
bf7f10b
Update StyleTest.php - Replace nowidctlpar with widctlpar - Widow/Orp…
rasamassen Sep 9, 2025
097c050
Update RtfEscaper3Test.php - Fix Test
rasamassen Sep 9, 2025
fcf45f2
Update TableTest.php - Fix test
rasamassen Sep 9, 2025
7e30fd6
Update Element2Test.php - Fix Test
rasamassen Sep 9, 2025
63559b5
Update ElementTest.php - Fix Test
rasamassen Sep 9, 2025
1e333b6
Update StyleTest.php - Fix test
rasamassen Sep 9, 2025
b8aac48
Update TableTest.php - Fix test
rasamassen Sep 9, 2025
5c22beb
Update TableTest.php - Hopefully final Fix test
rasamassen Sep 9, 2025
d7045a2
Update TableTest.php - Fix test
rasamassen Sep 9, 2025
3d63e96
Update ElementTest.php - Fix tests
rasamassen Sep 9, 2025
06c7c85
Update Paragraph.php - Fix deprecated features
rasamassen Oct 3, 2025
66de874
Update Paragraph.php - Fix justification, add missing options.
rasamassen Oct 3, 2025
0c7f3b2
Create ParagraphTest.php - Initial build
rasamassen Oct 3, 2025
1a8897f
Update ParagraphTest.php
rasamassen Oct 3, 2025
953cc31
Update ParagraphTest.php
rasamassen Oct 3, 2025
6eb482a
Update ParagraphTest.php
rasamassen Oct 3, 2025
5aa7396
Update ParagraphTest.php - Add tests
rasamassen Oct 4, 2025
eecc70d
Update Paragraph.php - add missing features
rasamassen Oct 4, 2025
f43e923
Update ParagraphTest.php
rasamassen Oct 4, 2025
d238a7e
Update Paragraph.php - add spacing and spacingLineRule
rasamassen Oct 4, 2025
995692f
Update ParagraphTest.php
rasamassen Oct 4, 2025
0b08710
Update Paragraph.php
rasamassen Oct 4, 2025
7d4ce32
Update Paragraph.php
rasamassen Oct 4, 2025
ff94ce8
Update Paragraph.php
rasamassen Oct 4, 2025
9143d56
Update Paragraph.php
rasamassen Oct 4, 2025
fcba983
Update ParagraphTest.php
rasamassen Oct 4, 2025
cbb2cbd
Update StyleTest.php
rasamassen Oct 4, 2025
2c4c25d
Update RtfEscaper3Test.php
rasamassen Oct 4, 2025
0516d30
Update ParagraphTest.php
rasamassen Oct 4, 2025
b394c75
Update 1.5.0.md
rasamassen Oct 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/changes/1.x/1.5.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 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

Expand All @@ -16,4 +17,4 @@

### BC Breaks

### Notes
### Notes
56 changes: 41 additions & 15 deletions src/PhpWord/Writer/RTF/Style/Paragraph.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
namespace PhpOffice\PhpWord\Writer\RTF\Style;

use PhpOffice\PhpWord\SimpleType\Jc;
use PhpOffice\PhpWord\SimpleType\LineSpacingRule;

/**
* RTF paragraph style writer.
Expand All @@ -36,10 +37,6 @@ class Paragraph extends AbstractStyle
*/
private $nestedLevel = 0;

private const LEFT = Jc::LEFT;
private const RIGHT = Jc::RIGHT;
private const JUSTIFY = Jc::JUSTIFY;

/**
* Write style.
*
Expand All @@ -57,26 +54,41 @@ 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',
];
$spacingRules = [
LineSpacingRule::AUTO => '\slmult1',
LineSpacingRule::EXACT => '\slmult0',
LineSpacingRule::AT_LEAST => '\slmult0',
];

$spaceAfter = $style->getSpaceAfter();
$spaceBefore = $style->getSpaceBefore();

$content = '';
if ($this->nestedLevel == 0) {
$content .= '\pard\nowidctlpar ';
$content .= '\pard';
}
$alignment = $style->getAlignment();
$bidi = $style->isBidi();
Expand All @@ -86,22 +98,36 @@ 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));
$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));
}
if ($style->hasPageBreakBefore()) {
$content .= '\\page';
$spacingRule = $style->getSpacingLineRule();
if (isset($spacingRules[$spacingRule])) {
$content .= $this->getValueIf($style->getSpacing() !== null, $spacingRules[$spacingRule]);
}

$content .= $this->getValueIf($style->hasContextualSpacing(), '\contextualspace');

// 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');
$content .= $this->getValueIf($style->hasSuppressAutoHyphens(), '\hyphpar0');

$styles = $style->getStyleValues();
$content .= $this->writeTabs($styles['tabs']);

return $content;
return $content . ' ';
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/PhpWordTests/Escaper/RtfEscaper2Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions tests/PhpWordTests/Escaper/RtfEscaper3Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -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\\ql\\widctlpar {\\cf0\\f0 ';
const HEADER_RTL = '\\pard\\qr\\rtlpar\\widctlpar {\\rtlch\\cf0\\f0 ';
const TRAILER = '}\\par';

protected function tearDown(): void
Expand Down
10 changes: 5 additions & 5 deletions tests/PhpWordTests/Writer/RTF/Element/TableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ 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',
'\\cell',
'\\row',
"\\trowd \\cellx$width \\cellx$width2 ",
'\\intbl',
'\\ql{\\cf0\\f0 3}\\par',
'\\ql\\widctlpar {\\cf0\\f0 3}\\par',
'\\cell',
'\\intbl',
'{\\cf0\\f0 4}\par',
Expand Down Expand Up @@ -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',
Expand All @@ -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',
Expand Down Expand Up @@ -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',
Expand Down
6 changes: 3 additions & 3 deletions tests/PhpWordTests/Writer/RTF/Element2Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -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\\ql\\widctlpar {{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n";
self::assertEquals($expect, $this->removeCr($textrun));
}

Expand All @@ -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\\ql\\sb0\\sa0\\widctlpar {{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n";
self::assertEquals($expect, $this->removeCr($textrun));
}

Expand All @@ -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\\ql\\sb0\\sa0\\widctlpar {\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}";
self::assertEquals($expect, $this->removeCr($elwrite));
Settings::setDefaultRtl(null);
}
Expand Down
14 changes: 7 additions & 7 deletions tests/PhpWordTests/Writer/RTF/ElementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,15 +121,15 @@ 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',
'\\cell',
'\\row',
"\\trowd \\cellx$width \\cellx$width2 ",
'\\intbl',
'{\\cf0\\f0 3}\\par',
'\\widctlpar {\\cf0\\f0 3}\\par',
'\\cell',
'\\intbl',
'{\\cf0\\f0 4}\par',
Expand All @@ -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));
}

Expand All @@ -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\\sb0\\sa0\\widctlpar {{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n";
self::assertEquals($expect, $this->removeCr($textrun));
}

Expand All @@ -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\\sb0\\sa0\\widctlpar {\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}";
self::assertEquals($expect, $this->removeCr($elwrite));
}

Expand All @@ -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));
}

Expand All @@ -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\\sb0\\sa2\\widctlpar {\\outlinelevel0{\\cf0\\f0\\fs48\\b base text (ruby)}\\par\n}";
self::assertEquals($expect, $this->removeCr($elwrite));
}
}
Loading
Loading