RTF Writer: Support for sections, margins, and borders #249

This commit is contained in:
Ivan Lanin 2014-06-06 12:53:01 +07:00
parent d97602fa98
commit 49f4e6ba64
7 changed files with 263 additions and 9 deletions

View File

@ -9,6 +9,7 @@ This is the changelog between releases of PHPWord. Releases are listed in revers
- Element: Ability to add drawing shapes (arc, curve, line, polyline, rect, oval) using new `Shape` element - @ivanlanin GH-123 - Element: Ability to add drawing shapes (arc, curve, line, polyline, rect, oval) using new `Shape` element - @ivanlanin GH-123
- Font: New `scale`, `spacing`, and `kerning` property of font style - @ivanlanin - Font: New `scale`, `spacing`, and `kerning` property of font style - @ivanlanin
- Paragraph: Added shading to the paragraph style for full width shading - @lrobert GH-264 - Paragraph: Added shading to the paragraph style for full width shading - @lrobert GH-264
- RTF Writer: Support for sections, margins, and borders - @ivanlanin GH-249
### Bugfixes ### Bugfixes

View File

@ -26,6 +26,13 @@ use PhpOffice\PhpWord\Style\AbstractStyle as Style;
*/ */
abstract class AbstractStyle abstract class AbstractStyle
{ {
/**
* Parent writer
*
* @var \PhpOffice\PhpWord\Writer\AbstractWriter
*/
private $parentWriter;
/** /**
* Style * Style
* *
@ -48,6 +55,26 @@ abstract class AbstractStyle
$this->style = $style; $this->style = $style;
} }
/**
* Set parent writer
*
* @param \PhpOffice\PhpWord\Writer\AbstractWriter $writer
*/
public function setParentWriter($writer)
{
$this->parentWriter = $writer;
}
/**
* Get parent writer
*
* @return \PhpOffice\PhpWord\Writer\AbstractWriter
*/
public function getParentWriter()
{
return $this->parentWriter;
}
/** /**
* Get style * Get style
* *

View File

@ -19,11 +19,13 @@ namespace PhpOffice\PhpWord\Writer\RTF\Part;
use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Writer\RTF\Element\Container; use PhpOffice\PhpWord\Writer\RTF\Element\Container;
use PhpOffice\PhpWord\Writer\RTF\Style\Section as SectionStyleWriter;
/** /**
* RTF document part writer * RTF document part writer
* *
* @since 0.11.0 * @since 0.11.0
* @link http://www.biblioscape.com/rtf15_spec.htm#Heading24
*/ */
class Document extends AbstractPart class Document extends AbstractPart
{ {
@ -103,12 +105,19 @@ class Document extends AbstractPart
*/ */
private function writeSections() private function writeSections()
{ {
$content = ''; $content = '';
$sections = $this->getParentWriter()->getPhpWord()->getSections(); $sections = $this->getParentWriter()->getPhpWord()->getSections();
foreach ($sections as $section) { foreach ($sections as $section) {
$writer = new Container($this->getParentWriter(), $section); $styleWriter = new SectionStyleWriter($section->getSettings());
$content .= $writer->write(); $styleWriter->setParentWriter($this->getParentWriter());
$content .= $styleWriter->write();
$elementWriter = new Container($this->getParentWriter(), $section);
$content .= $elementWriter->write();
$content .= '\sect' . PHP_EOL;
} }
return $content; return $content;

View File

@ -25,7 +25,15 @@ use PhpOffice\PhpWord\Style\Font;
/** /**
* RTF header part writer * RTF header part writer
* *
* - Character set
* - Font table
* - File table (not supported yet)
* - Color table
* - Style sheet (not supported yet)
* - List table (not supported yet)
*
* @since 0.11.0 * @since 0.11.0
* @link http://www.biblioscape.com/rtf15_spec.htm#Heading6
*/ */
class Header extends AbstractPart class Header extends AbstractPart
{ {
@ -141,10 +149,10 @@ class Header extends AbstractPart
$content = ''; $content = '';
$content .= '{'; $content .= '{';
$content .= '\colortbl'; $content .= '\colortbl;';
foreach ($this->colorTable as $color) { foreach ($this->colorTable as $color) {
list($red, $green, $blue) = Drawing::htmlToRGB($color); list($red, $green, $blue) = Drawing::htmlToRGB($color);
$content .= ";\\red{$red}\\green{$green}\\blue{$blue}"; $content .= "\\red{$red}\\green{$green}\\blue{$blue};";
} }
$content .= '}'; $content .= '}';
$content .= PHP_EOL; $content .= PHP_EOL;
@ -185,6 +193,7 @@ class Header extends AbstractPart
$sections = $phpWord->getSections(); $sections = $phpWord->getSections();
foreach ($sections as $section) { foreach ($sections as $section) {
$elements = $section->getElements(); $elements = $section->getElements();
$this->registerBorderColor($section->getSettings());
foreach ($elements as $element) { foreach ($elements as $element) {
if (method_exists($element, 'getFontStyle')) { if (method_exists($element, 'getFontStyle')) {
$style = $element->getFontStyle(); $style = $element->getFontStyle();
@ -194,6 +203,21 @@ class Header extends AbstractPart
} }
} }
/**
* Register border colors
*
* @param \PhpOffice\PhpWord\Style\Border $style
*/
private function registerBorderColor($style)
{
$colors = $style->getBorderColor();
foreach ($colors as $color) {
if ($color !== null) {
$this->registerTableItem($this->colorTable, $color);
}
}
}
/** /**
* Register fonts and colors * Register fonts and colors
* *
@ -205,9 +229,9 @@ class Header extends AbstractPart
$defaultColor = Settings::DEFAULT_FONT_COLOR; $defaultColor = Settings::DEFAULT_FONT_COLOR;
if ($style instanceof Font) { if ($style instanceof Font) {
$this->registerFontItem($this->fontTable, $style->getName(), $defaultFont); $this->registerTableItem($this->fontTable, $style->getName(), $defaultFont);
$this->registerFontItem($this->colorTable, $style->getColor(), $defaultColor); $this->registerTableItem($this->colorTable, $style->getColor(), $defaultColor);
$this->registerFontItem($this->colorTable, $style->getFgColor(), $defaultColor); $this->registerTableItem($this->colorTable, $style->getFgColor(), $defaultColor);
} }
} }
@ -218,7 +242,7 @@ class Header extends AbstractPart
* @param string $value * @param string $value
* @param string $default * @param string $default
*/ */
private function registerFontItem(&$table, $value, $default) private function registerTableItem(&$table, $value, $default = null)
{ {
if (in_array($value, $table) === false && $value !== null && $value != $default) { if (in_array($value, $table) === false && $value !== null && $value != $default) {
$table[] = $value; $table[] = $value;

View File

@ -0,0 +1,124 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2010-2014 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Writer\RTF\Style;
use PhpOffice\PhpWord\Shared\XMLWriter;
/**
* Border style writer
*
* @since 0.12.0
*/
class Border extends AbstractStyle
{
/**
* Sizes
*
* @var array
*/
private $sizes = array();
/**
* Colors
*
* @var array
*/
private $colors = array();
/**
* Write style
*
* @return string
*/
public function write()
{
$content = '';
$sides = array('top', 'left', 'right', 'bottom');
$sizeCount = count($this->sizes) - 1;
// Page border measure
// 8 = from text, infront off; 32 = from edge, infront on; 40 = from edge, infront off
$content .= '\pgbrdropt32';
for ($i = 0; $i < $sizeCount; $i++) {
if ($this->sizes[$i] !== null) {
$color = null;
if (isset($this->colors[$i])) {
$color = $this->colors[$i];
}
$content .= $this->writeSide($sides[$i], $this->sizes[$i], $color);
}
}
return $content;
}
/**
* Write side
*
* @param string $side
* @param int $width
* @param string $color
* @return string
*/
private function writeSide($side, $width, $color = '')
{
/** @var \PhpOffice\PhpWord\Writer\RTF $rtfWriter */
$rtfWriter = $this->getParentWriter();
$colorIndex = 0;
if ($rtfWriter !== null) {
$colorTable = $rtfWriter->getColorTable();
$index = array_search($color, $colorTable);
if ($index !== false && $colorIndex !== null) {
$colorIndex = $index + 1;
}
}
$content = '';
$content .= '\pgbrdr' . substr($side, 0, 1);
$content .= '\brdrs'; // Single-thickness border; @todo Get other type of border
$content .= '\brdrw' . $width; // Width
$content .= '\brdrcf' . $colorIndex; // Color
$content .= '\brsp480'; // Space in twips between borders and the paragraph (24pt, following OOXML)
$content .= ' ';
return $content;
}
/**
* Set sizes
*
* @param integer[] $value
*/
public function setSizes($value)
{
$this->sizes = $value;
}
/**
* Set colors
*
* @param string[] $value
*/
public function setColors($value)
{
$this->colors = $value;
}
}

View File

@ -0,0 +1,69 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2010-2014 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Writer\RTF\Style;
use PhpOffice\PhpWord\Style\Section as SectionStyle;
/**
* RTF section style writer
*
* @since 0.12.0
*/
class Section extends AbstractStyle
{
/**
* Write style
*
* @return string
*/
public function write()
{
$style = $this->getStyle();
if (!$style instanceof SectionStyle) {
return '';
}
$content = '';
$content .= '\sectd ';
// Size & margin
$content .= $this->getValueIf($style->getPageSizeW(), '\pgwsxn' . $style->getPageSizeW());
$content .= $this->getValueIf($style->getPageSizeH(), '\pghsxn' . $style->getPageSizeH());
$content .= ' ';
$content .= $this->getValueIf($style->getMarginTop(), '\margtsxn' . $style->getMarginTop());
$content .= $this->getValueIf($style->getMarginRight(), '\margrsxn' . $style->getMarginRight());
$content .= $this->getValueIf($style->getMarginBottom(), '\margbsxn' . $style->getMarginBottom());
$content .= $this->getValueIf($style->getMarginLeft(), '\marglsxn' . $style->getMarginLeft());
$content .= $this->getValueIf($style->getHeaderHeight(), '\headery' . $style->getHeaderHeight());
$content .= $this->getValueIf($style->getFooterHeight(), '\footery' . $style->getFooterHeight());
$content .= $this->getValueIf($style->getGutter(), '\guttersxn' . $style->getGutter());
$content .= ' ';
// Borders
if ($style->hasBorder()) {
$styleWriter = new Border($style);
$styleWriter->setParentWriter($this->getParentWriter());
$styleWriter->setSizes($style->getBorderSize());
$styleWriter->setColors($style->getBorderColor());
$content .= $styleWriter->write();
}
return $content . PHP_EOL;
}
}

View File

@ -28,7 +28,7 @@ class StyleTest extends \PHPUnit_Framework_TestCase
*/ */
public function testEmptyStyles() public function testEmptyStyles()
{ {
$styles = array('Font', 'Paragraph'); $styles = array('Font', 'Paragraph', 'Section');
foreach ($styles as $style) { foreach ($styles as $style) {
$objectClass = 'PhpOffice\\PhpWord\\Writer\\RTF\\Style\\' . $style; $objectClass = 'PhpOffice\\PhpWord\\Writer\\RTF\\Style\\' . $style;
$object = new $objectClass(); $object = new $objectClass();