Skip to content

Commit 49f4e6b

Browse files
committed
RTF Writer: Support for sections, margins, and borders #249
1 parent d97602f commit 49f4e6b

File tree

7 files changed

+263
-9
lines changed

7 files changed

+263
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ This is the changelog between releases of PHPWord. Releases are listed in revers
99
- Element: Ability to add drawing shapes (arc, curve, line, polyline, rect, oval) using new `Shape` element - @ivanlanin GH-123
1010
- Font: New `scale`, `spacing`, and `kerning` property of font style - @ivanlanin
1111
- Paragraph: Added shading to the paragraph style for full width shading - @lrobert GH-264
12+
- RTF Writer: Support for sections, margins, and borders - @ivanlanin GH-249
1213

1314
### Bugfixes
1415

src/PhpWord/Writer/HTML/Style/AbstractStyle.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@
2626
*/
2727
abstract class AbstractStyle
2828
{
29+
/**
30+
* Parent writer
31+
*
32+
* @var \PhpOffice\PhpWord\Writer\AbstractWriter
33+
*/
34+
private $parentWriter;
35+
2936
/**
3037
* Style
3138
*
@@ -48,6 +55,26 @@ public function __construct($style = null)
4855
$this->style = $style;
4956
}
5057

58+
/**
59+
* Set parent writer
60+
*
61+
* @param \PhpOffice\PhpWord\Writer\AbstractWriter $writer
62+
*/
63+
public function setParentWriter($writer)
64+
{
65+
$this->parentWriter = $writer;
66+
}
67+
68+
/**
69+
* Get parent writer
70+
*
71+
* @return \PhpOffice\PhpWord\Writer\AbstractWriter
72+
*/
73+
public function getParentWriter()
74+
{
75+
return $this->parentWriter;
76+
}
77+
5178
/**
5279
* Get style
5380
*

src/PhpWord/Writer/RTF/Part/Document.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@
1919

2020
use PhpOffice\PhpWord\Settings;
2121
use PhpOffice\PhpWord\Writer\RTF\Element\Container;
22+
use PhpOffice\PhpWord\Writer\RTF\Style\Section as SectionStyleWriter;
2223

2324
/**
2425
* RTF document part writer
2526
*
2627
* @since 0.11.0
28+
* @link http://www.biblioscape.com/rtf15_spec.htm#Heading24
2729
*/
2830
class Document extends AbstractPart
2931
{
@@ -103,12 +105,19 @@ private function writeFormatting()
103105
*/
104106
private function writeSections()
105107
{
108+
106109
$content = '';
107110

108111
$sections = $this->getParentWriter()->getPhpWord()->getSections();
109112
foreach ($sections as $section) {
110-
$writer = new Container($this->getParentWriter(), $section);
111-
$content .= $writer->write();
113+
$styleWriter = new SectionStyleWriter($section->getSettings());
114+
$styleWriter->setParentWriter($this->getParentWriter());
115+
$content .= $styleWriter->write();
116+
117+
$elementWriter = new Container($this->getParentWriter(), $section);
118+
$content .= $elementWriter->write();
119+
120+
$content .= '\sect' . PHP_EOL;
112121
}
113122

114123
return $content;

src/PhpWord/Writer/RTF/Part/Header.php

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,15 @@
2525
/**
2626
* RTF header part writer
2727
*
28+
* - Character set
29+
* - Font table
30+
* - File table (not supported yet)
31+
* - Color table
32+
* - Style sheet (not supported yet)
33+
* - List table (not supported yet)
34+
*
2835
* @since 0.11.0
36+
* @link http://www.biblioscape.com/rtf15_spec.htm#Heading6
2937
*/
3038
class Header extends AbstractPart
3139
{
@@ -141,10 +149,10 @@ private function writeColorTable()
141149
$content = '';
142150

143151
$content .= '{';
144-
$content .= '\colortbl';
152+
$content .= '\colortbl;';
145153
foreach ($this->colorTable as $color) {
146154
list($red, $green, $blue) = Drawing::htmlToRGB($color);
147-
$content .= ";\\red{$red}\\green{$green}\\blue{$blue}";
155+
$content .= "\\red{$red}\\green{$green}\\blue{$blue};";
148156
}
149157
$content .= '}';
150158
$content .= PHP_EOL;
@@ -185,6 +193,7 @@ private function registerFont()
185193
$sections = $phpWord->getSections();
186194
foreach ($sections as $section) {
187195
$elements = $section->getElements();
196+
$this->registerBorderColor($section->getSettings());
188197
foreach ($elements as $element) {
189198
if (method_exists($element, 'getFontStyle')) {
190199
$style = $element->getFontStyle();
@@ -194,6 +203,21 @@ private function registerFont()
194203
}
195204
}
196205

206+
/**
207+
* Register border colors
208+
*
209+
* @param \PhpOffice\PhpWord\Style\Border $style
210+
*/
211+
private function registerBorderColor($style)
212+
{
213+
$colors = $style->getBorderColor();
214+
foreach ($colors as $color) {
215+
if ($color !== null) {
216+
$this->registerTableItem($this->colorTable, $color);
217+
}
218+
}
219+
}
220+
197221
/**
198222
* Register fonts and colors
199223
*
@@ -205,9 +229,9 @@ private function registerFontItems($style)
205229
$defaultColor = Settings::DEFAULT_FONT_COLOR;
206230

207231
if ($style instanceof Font) {
208-
$this->registerFontItem($this->fontTable, $style->getName(), $defaultFont);
209-
$this->registerFontItem($this->colorTable, $style->getColor(), $defaultColor);
210-
$this->registerFontItem($this->colorTable, $style->getFgColor(), $defaultColor);
232+
$this->registerTableItem($this->fontTable, $style->getName(), $defaultFont);
233+
$this->registerTableItem($this->colorTable, $style->getColor(), $defaultColor);
234+
$this->registerTableItem($this->colorTable, $style->getFgColor(), $defaultColor);
211235
}
212236
}
213237

@@ -218,7 +242,7 @@ private function registerFontItems($style)
218242
* @param string $value
219243
* @param string $default
220244
*/
221-
private function registerFontItem(&$table, $value, $default)
245+
private function registerTableItem(&$table, $value, $default = null)
222246
{
223247
if (in_array($value, $table) === false && $value !== null && $value != $default) {
224248
$table[] = $value;
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
/**
3+
* This file is part of PHPWord - A pure PHP library for reading and writing
4+
* word processing documents.
5+
*
6+
* PHPWord is free software distributed under the terms of the GNU Lesser
7+
* General Public License version 3 as published by the Free Software Foundation.
8+
*
9+
* For the full copyright and license information, please read the LICENSE
10+
* file that was distributed with this source code. For the full list of
11+
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
12+
*
13+
* @link https://github.com/PHPOffice/PHPWord
14+
* @copyright 2010-2014 PHPWord contributors
15+
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
16+
*/
17+
18+
namespace PhpOffice\PhpWord\Writer\RTF\Style;
19+
20+
use PhpOffice\PhpWord\Shared\XMLWriter;
21+
22+
/**
23+
* Border style writer
24+
*
25+
* @since 0.12.0
26+
*/
27+
class Border extends AbstractStyle
28+
{
29+
/**
30+
* Sizes
31+
*
32+
* @var array
33+
*/
34+
private $sizes = array();
35+
36+
/**
37+
* Colors
38+
*
39+
* @var array
40+
*/
41+
private $colors = array();
42+
43+
/**
44+
* Write style
45+
*
46+
* @return string
47+
*/
48+
public function write()
49+
{
50+
$content = '';
51+
52+
$sides = array('top', 'left', 'right', 'bottom');
53+
$sizeCount = count($this->sizes) - 1;
54+
55+
// Page border measure
56+
// 8 = from text, infront off; 32 = from edge, infront on; 40 = from edge, infront off
57+
$content .= '\pgbrdropt32';
58+
59+
for ($i = 0; $i < $sizeCount; $i++) {
60+
if ($this->sizes[$i] !== null) {
61+
$color = null;
62+
if (isset($this->colors[$i])) {
63+
$color = $this->colors[$i];
64+
}
65+
$content .= $this->writeSide($sides[$i], $this->sizes[$i], $color);
66+
}
67+
}
68+
69+
return $content;
70+
}
71+
72+
/**
73+
* Write side
74+
*
75+
* @param string $side
76+
* @param int $width
77+
* @param string $color
78+
* @return string
79+
*/
80+
private function writeSide($side, $width, $color = '')
81+
{
82+
/** @var \PhpOffice\PhpWord\Writer\RTF $rtfWriter */
83+
$rtfWriter = $this->getParentWriter();
84+
$colorIndex = 0;
85+
if ($rtfWriter !== null) {
86+
$colorTable = $rtfWriter->getColorTable();
87+
$index = array_search($color, $colorTable);
88+
if ($index !== false && $colorIndex !== null) {
89+
$colorIndex = $index + 1;
90+
}
91+
}
92+
93+
$content = '';
94+
95+
$content .= '\pgbrdr' . substr($side, 0, 1);
96+
$content .= '\brdrs'; // Single-thickness border; @todo Get other type of border
97+
$content .= '\brdrw' . $width; // Width
98+
$content .= '\brdrcf' . $colorIndex; // Color
99+
$content .= '\brsp480'; // Space in twips between borders and the paragraph (24pt, following OOXML)
100+
$content .= ' ';
101+
102+
return $content;
103+
}
104+
105+
/**
106+
* Set sizes
107+
*
108+
* @param integer[] $value
109+
*/
110+
public function setSizes($value)
111+
{
112+
$this->sizes = $value;
113+
}
114+
115+
/**
116+
* Set colors
117+
*
118+
* @param string[] $value
119+
*/
120+
public function setColors($value)
121+
{
122+
$this->colors = $value;
123+
}
124+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
/**
3+
* This file is part of PHPWord - A pure PHP library for reading and writing
4+
* word processing documents.
5+
*
6+
* PHPWord is free software distributed under the terms of the GNU Lesser
7+
* General Public License version 3 as published by the Free Software Foundation.
8+
*
9+
* For the full copyright and license information, please read the LICENSE
10+
* file that was distributed with this source code. For the full list of
11+
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
12+
*
13+
* @link https://github.com/PHPOffice/PHPWord
14+
* @copyright 2010-2014 PHPWord contributors
15+
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
16+
*/
17+
18+
namespace PhpOffice\PhpWord\Writer\RTF\Style;
19+
20+
use PhpOffice\PhpWord\Style\Section as SectionStyle;
21+
22+
/**
23+
* RTF section style writer
24+
*
25+
* @since 0.12.0
26+
*/
27+
class Section extends AbstractStyle
28+
{
29+
/**
30+
* Write style
31+
*
32+
* @return string
33+
*/
34+
public function write()
35+
{
36+
$style = $this->getStyle();
37+
if (!$style instanceof SectionStyle) {
38+
return '';
39+
}
40+
41+
$content = '';
42+
43+
$content .= '\sectd ';
44+
45+
// Size & margin
46+
$content .= $this->getValueIf($style->getPageSizeW(), '\pgwsxn' . $style->getPageSizeW());
47+
$content .= $this->getValueIf($style->getPageSizeH(), '\pghsxn' . $style->getPageSizeH());
48+
$content .= ' ';
49+
$content .= $this->getValueIf($style->getMarginTop(), '\margtsxn' . $style->getMarginTop());
50+
$content .= $this->getValueIf($style->getMarginRight(), '\margrsxn' . $style->getMarginRight());
51+
$content .= $this->getValueIf($style->getMarginBottom(), '\margbsxn' . $style->getMarginBottom());
52+
$content .= $this->getValueIf($style->getMarginLeft(), '\marglsxn' . $style->getMarginLeft());
53+
$content .= $this->getValueIf($style->getHeaderHeight(), '\headery' . $style->getHeaderHeight());
54+
$content .= $this->getValueIf($style->getFooterHeight(), '\footery' . $style->getFooterHeight());
55+
$content .= $this->getValueIf($style->getGutter(), '\guttersxn' . $style->getGutter());
56+
$content .= ' ';
57+
58+
// Borders
59+
if ($style->hasBorder()) {
60+
$styleWriter = new Border($style);
61+
$styleWriter->setParentWriter($this->getParentWriter());
62+
$styleWriter->setSizes($style->getBorderSize());
63+
$styleWriter->setColors($style->getBorderColor());
64+
$content .= $styleWriter->write();
65+
}
66+
67+
return $content . PHP_EOL;
68+
}
69+
}

tests/PhpWord/Tests/Writer/RTF/StyleTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class StyleTest extends \PHPUnit_Framework_TestCase
2828
*/
2929
public function testEmptyStyles()
3030
{
31-
$styles = array('Font', 'Paragraph');
31+
$styles = array('Font', 'Paragraph', 'Section');
3232
foreach ($styles as $style) {
3333
$objectClass = 'PhpOffice\\PhpWord\\Writer\\RTF\\Style\\' . $style;
3434
$object = new $objectClass();

0 commit comments

Comments
 (0)