Skip to content

Commit b577547

Browse files
committed
Rasamassen PR's 2815, 2816, 2830, 2840
I made RTF usable some time ago. @rasamassen has recently done a lot of useful work to cover many missing areas. Since who knows when those changes will be merged, I intend to incorporate much of that work. I will do this with several pushes, each based on one or more of those changes. This one is based on PR PHPOffice#2815 (partially addressing issue PHPOffice#862), PR PHPOffice#2816, PR PHPOffice#2830 (partially addressing issue PHPOffice#1656), and PR PHPOffice#2840 (partially addressing issue PHPOffice#909).
1 parent 882f98f commit b577547

File tree

9 files changed

+341
-98
lines changed

9 files changed

+341
-98
lines changed

samples/Sample_09_Tables.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@
125125

126126
$row = $table->addRow();
127127
$row->addCell(1000, ['vMerge' => 'continue']);
128-
$row->addCell(1000)->addText('C');
129-
$row->addCell(1000)->addText('D');
128+
$row->addCell(500)->addText('C');
129+
$row->addCell(500)->addText('D');
130130
$row->addCell(1000)->addText('3');
131131

132132
// 5. Nested table

src/PhpWord/Style/Paper.php

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
namespace PhpOffice\PhpWord\Style;
2020

21+
use InvalidArgumentException;
2122
use PhpOffice\PhpWord\Shared\Converter;
2223

2324
/**
@@ -97,16 +98,21 @@ class Paper extends AbstractStyle
9798
/**
9899
* Paper sizes.
99100
*
100-
* @var array
101+
* @var array<string, array{0: float|int, 1: float|int, 2: string}>
101102
*/
102103
private $sizes = [
103104
'A3' => [297, 420, 'mm'],
104105
'A4' => [210, 297, 'mm'],
105106
'A5' => [148, 210, 'mm'],
107+
'B4' => [250, 353, 'mm'],
106108
'B5' => [176, 250, 'mm'],
109+
'Executive' => [7.25, 10.5, 'in'],
107110
'Folio' => [8.5, 13, 'in'],
111+
'Ledger' => [17, 11, 'in'],
108112
'Legal' => [8.5, 14, 'in'],
109113
'Letter' => [8.5, 11, 'in'],
114+
'Statement' => [5.5, 8.5, 'in'],
115+
'Tabloid' => [11, 17, 'in'],
110116
];
111117

112118
/**
@@ -151,24 +157,37 @@ public function getSize()
151157
}
152158

153159
/**
154-
* Set size.
160+
* Set size. Normally called with 1 parameter, corresponding to a key
161+
* in the $sizes array. However, for sizes not in that table,
162+
* it can be called with explicit width, height, and unit.
155163
*
156164
* @param string $size
165+
* @param float|int $width
166+
* @param float|int $height
167+
* @param string $unit
157168
*
158169
* @return self
159170
*/
160-
public function setSize($size)
171+
public function setSize($size, $width = 0, $height = 0, $unit = '')
161172
{
162-
$this->size = $this->setEnumVal($size, array_keys($this->sizes), $this->size);
163-
164-
[$width, $height, $unit] = $this->sizes[$this->size];
173+
if ($width != 0 || $height != 0 || $unit !== '') {
174+
$this->size = $size;
175+
} else {
176+
$this->size = $this->setEnumVal($size, array_keys($this->sizes), $this->size);
177+
[$width, $height, $unit] = $this->sizes[$this->size];
178+
}
165179

166-
if ($unit == 'mm') {
180+
if ($width <= 0 || $height <= 0) {
181+
throw new InvalidArgumentException('width and height must be positive');
182+
}
183+
if ($unit === 'mm') {
167184
$this->width = Converter::cmToTwip($width / 10);
168185
$this->height = Converter::cmToTwip($height / 10);
169-
} else {
186+
} elseif ($unit === 'in') {
170187
$this->width = Converter::inchToTwip($width);
171188
$this->height = Converter::inchToTwip($height);
189+
} else {
190+
throw new InvalidArgumentException('unit must be mm or in');
172191
}
173192

174193
return $this;

src/PhpWord/Writer/RTF/Element/TextBreak.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ public function write()
3636
$parentWriter = $this->parentWriter;
3737
$parentWriter->setLastParagraphStyle();
3838

39+
if ($this->withoutP) {
40+
return '\line' . PHP_EOL;
41+
}
42+
3943
return '\pard\par' . PHP_EOL;
4044
}
4145
}

src/PhpWord/Writer/RTF/Style/Tab.php

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
namespace PhpOffice\PhpWord\Writer\RTF\Style;
2020

21+
use PhpOffice\PhpWord\Style\Tab as TabStyle;
22+
2123
/**
2224
* Line numbering style writer.
2325
*
@@ -31,19 +33,31 @@ class Tab extends AbstractStyle
3133
public function write()
3234
{
3335
$style = $this->getStyle();
34-
if (!$style instanceof \PhpOffice\PhpWord\Style\Tab) {
36+
if (!$style instanceof TabStyle) {
3537
return;
3638
}
3739
$tabs = [
38-
\PhpOffice\PhpWord\Style\Tab::TAB_STOP_RIGHT => '\tqr',
39-
\PhpOffice\PhpWord\Style\Tab::TAB_STOP_CENTER => '\tqc',
40-
\PhpOffice\PhpWord\Style\Tab::TAB_STOP_DECIMAL => '\tqdec',
40+
TabStyle::TAB_STOP_RIGHT => '\tqr',
41+
TabStyle::TAB_STOP_CENTER => '\tqc',
42+
TabStyle::TAB_STOP_DECIMAL => '\tqdec',
43+
TabStyle::TAB_LEADER_DOT => '\tldot',
44+
TabStyle::TAB_LEADER_HYPHEN => '\tlhyph',
45+
TabStyle::TAB_LEADER_UNDERSCORE => '\tlul',
46+
TabStyle::TAB_LEADER_HEAVY => '\tlth',
47+
TabStyle::TAB_LEADER_MIDDLEDOT => '\tlmdot',
4148
];
4249
$content = '';
4350
if (isset($tabs[$style->getType()])) {
4451
$content .= $tabs[$style->getType()];
4552
}
46-
$content .= '\tx' . round($style->getPosition());
53+
if (isset($tabs[$style->getLeader()]) && $style->getType() !== TabStyle::TAB_STOP_BAR) {
54+
$content .= $tabs[$style->getLeader()];
55+
}
56+
if ($style->getType() == TabStyle::TAB_STOP_BAR) {
57+
$content .= '\tb' . round($style->getPosition());
58+
} else {
59+
$content .= '\tx' . round($style->getPosition());
60+
}
4761

4862
return $content;
4963
}

tests/PhpWordTests/Style/PaperTest.php

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,14 @@
1818

1919
namespace PhpOffice\PhpWordTests\Style;
2020

21+
use InvalidArgumentException;
2122
use PhpOffice\PhpWord\Style\Paper;
22-
use PhpOffice\PhpWordTests\TestHelperDOCX;
2323

2424
/**
2525
* Test class for PhpOffice\PhpWord\Style\Paper.
2626
*/
2727
class PaperTest extends \PHPUnit\Framework\TestCase
2828
{
29-
/**
30-
* Tear down after each test.
31-
*/
32-
protected function tearDown(): void
33-
{
34-
TestHelperDOCX::clear();
35-
}
36-
3729
/**
3830
* Test initiation for paper.
3931
*/
@@ -68,4 +60,41 @@ public function testFolioSize(): void
6860
self::assertEqualsWithDelta(12240, $object->getWidth(), 0.1);
6961
self::assertEqualsWithDelta(18720, $object->getHeight(), 0.1);
7062
}
63+
64+
/**
65+
* Test paper size for Folio format invoked with explicit values.
66+
*/
67+
public function testFolioSizeExplicit(): void
68+
{
69+
$object = new Paper();
70+
$object->setSize('XFolio', 8.5, 13, 'in');
71+
72+
self::assertEquals('XFolio', $object->getSize());
73+
self::assertEqualsWithDelta(12240, $object->getWidth(), 0.1);
74+
self::assertEqualsWithDelta(18720, $object->getHeight(), 0.1);
75+
}
76+
77+
public function testBadUnit(): void
78+
{
79+
$this->expectException(InvalidArgumentException::class);
80+
$this->expectExceptionMessage('unit must be mm or in');
81+
$object = new Paper();
82+
$object->setSize('XFolio', 8.5, 13, 'inx');
83+
}
84+
85+
public function testBadWidthHeight(): void
86+
{
87+
$this->expectException(InvalidArgumentException::class);
88+
$this->expectExceptionMessage('width and height must be positive');
89+
$object = new Paper();
90+
$object->setSize('XFolio', 0, 13, 'inx');
91+
}
92+
93+
public function testUnknownSize(): void
94+
{
95+
$this->expectException(InvalidArgumentException::class);
96+
$this->expectExceptionMessage('Invalid style value');
97+
$object = new Paper();
98+
$object->setSize('XFolio');
99+
}
71100
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
/**
4+
* This file is part of PHPWord - A pure PHP library for reading and writing
5+
* word processing documents.
6+
*
7+
* PHPWord is free software distributed under the terms of the GNU Lesser
8+
* General Public License version 3 as published by the Free Software Foundation.
9+
*
10+
* For the full copyright and license information, please read the LICENSE
11+
* file that was distributed with this source code. For the full list of
12+
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
13+
*
14+
* @see https://github.com/PHPOffice/PHPWord
15+
*
16+
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
17+
*/
18+
19+
namespace PhpOffice\PhpWordTests\Writer\RTF\Element;
20+
21+
use PhpOffice\PhpWord\Element\TextBreak as TextBreakElement;
22+
use PhpOffice\PhpWord\Writer\RTF;
23+
use PhpOffice\PhpWord\Writer\RTF\Element\TextBreak as TextBreakWriter;
24+
use PHPUnit\Framework\TestCase;
25+
26+
class TextBreakTest extends TestCase
27+
{
28+
/**
29+
* @param TextBreakWriter $field
30+
*/
31+
public function removeCr($field): string
32+
{
33+
return str_replace("\r\n", "\n", $field->write());
34+
}
35+
36+
/**
37+
* Test a normal textBreak.
38+
* See page 142-143 of RTF Specification 1.9.1.
39+
*/
40+
public function testTextBreakParagraph(): void
41+
{
42+
$parentWriter = new RTF();
43+
$element = new TextBreakElement();
44+
$writer = new TextBreakWriter($parentWriter, $element);
45+
$expect = "\\pard\\par\n";
46+
self::assertEquals($expect, $this->removeCr($writer));
47+
}
48+
49+
/**
50+
* Test a textBreak as a line break.
51+
* See page 142-143 of RTF Specification 1.9.1.
52+
*/
53+
public function testTextBreakLine(): void
54+
{
55+
$parentWriter = new RTF();
56+
$element = new TextBreakElement();
57+
$writer = new TextBreakWriter($parentWriter, $element, true);
58+
$expect = "\\line\n";
59+
self::assertEquals($expect, $this->removeCr($writer));
60+
}
61+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
/**
4+
* This file is part of PHPWord - A pure PHP library for reading and writing
5+
* word processing documents.
6+
*
7+
* PHPWord is free software distributed under the terms of the GNU Lesser
8+
* General Public License version 3 as published by the Free Software Foundation.
9+
*
10+
* For the full copyright and license information, please read the LICENSE
11+
* file that was distributed with this source code. For the full list of
12+
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
13+
*
14+
* @see https://github.com/PHPOffice/PHPWord
15+
*
16+
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
17+
*/
18+
19+
namespace PhpOffice\PhpWordTests\Writer\RTF\Style;
20+
21+
use PhpOffice\PhpWord\Settings;
22+
use PhpOffice\PhpWord\Writer\RTF;
23+
24+
/**
25+
* Test class for PhpOffice\PhpWord\Writer\RTF\Style subnamespace.
26+
*/
27+
class RtlTest extends \PHPUnit\Framework\TestCase
28+
{
29+
protected function tearDown(): void
30+
{
31+
Settings::setDefaultRtl(null);
32+
}
33+
34+
/**
35+
* @param RTF\Element\Text $field
36+
*/
37+
public function removeCr($field): string
38+
{
39+
return str_replace("\r\n", "\n", $field->write());
40+
}
41+
42+
public function testRTL(): void
43+
{
44+
$parentWriter = new RTF();
45+
$element = new \PhpOffice\PhpWord\Element\Text('אב גד', ['RTL' => true]);
46+
$text = new RTF\Element\Text($parentWriter, $element);
47+
$expect = "\\pard\\nowidctlpar {\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n";
48+
self::assertEquals($expect, $this->removeCr($text));
49+
}
50+
51+
public function testRTL2(): void
52+
{
53+
Settings::setDefaultRtl(true);
54+
$parentWriter = new RTF();
55+
$element = new \PhpOffice\PhpWord\Element\Text('אב גד');
56+
$text = new RTF\Element\Text($parentWriter, $element);
57+
$expect = "\\pard\\nowidctlpar \\qr{\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n";
58+
self::assertEquals($expect, $this->removeCr($text));
59+
}
60+
61+
public function testPageBreakLineHeight2(): void
62+
{
63+
Settings::setDefaultRtl(false);
64+
$parentWriter = new RTF();
65+
$element = new \PhpOffice\PhpWord\Element\Text('New page', null, ['lineHeight' => 1.08, 'pageBreakBefore' => true]);
66+
$text = new RTF\Element\Text($parentWriter, $element);
67+
$expect = "\\pard\\nowidctlpar \\ql\\sl259\\slmult1\\page{\\cf0\\f0 New page}\\par\n";
68+
self::assertEquals($expect, $this->removeCr($text));
69+
}
70+
}

0 commit comments

Comments
 (0)