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
- 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
- RTF Writer: Support for sections, margins, and borders - @ivanlanin GH-249
### Bugfixes

View File

@ -26,6 +26,13 @@ use PhpOffice\PhpWord\Style\AbstractStyle as Style;
*/
abstract class AbstractStyle
{
/**
* Parent writer
*
* @var \PhpOffice\PhpWord\Writer\AbstractWriter
*/
private $parentWriter;
/**
* Style
*
@ -48,6 +55,26 @@ abstract class AbstractStyle
$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
*

View File

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

View File

@ -25,7 +25,15 @@ use PhpOffice\PhpWord\Style\Font;
/**
* 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
* @link http://www.biblioscape.com/rtf15_spec.htm#Heading6
*/
class Header extends AbstractPart
{
@ -141,10 +149,10 @@ class Header extends AbstractPart
$content = '';
$content .= '{';
$content .= '\colortbl';
$content .= '\colortbl;';
foreach ($this->colorTable as $color) {
list($red, $green, $blue) = Drawing::htmlToRGB($color);
$content .= ";\\red{$red}\\green{$green}\\blue{$blue}";
$content .= "\\red{$red}\\green{$green}\\blue{$blue};";
}
$content .= '}';
$content .= PHP_EOL;
@ -185,6 +193,7 @@ class Header extends AbstractPart
$sections = $phpWord->getSections();
foreach ($sections as $section) {
$elements = $section->getElements();
$this->registerBorderColor($section->getSettings());
foreach ($elements as $element) {
if (method_exists($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
*
@ -205,9 +229,9 @@ class Header extends AbstractPart
$defaultColor = Settings::DEFAULT_FONT_COLOR;
if ($style instanceof Font) {
$this->registerFontItem($this->fontTable, $style->getName(), $defaultFont);
$this->registerFontItem($this->colorTable, $style->getColor(), $defaultColor);
$this->registerFontItem($this->colorTable, $style->getFgColor(), $defaultColor);
$this->registerTableItem($this->fontTable, $style->getName(), $defaultFont);
$this->registerTableItem($this->colorTable, $style->getColor(), $defaultColor);
$this->registerTableItem($this->colorTable, $style->getFgColor(), $defaultColor);
}
}
@ -218,7 +242,7 @@ class Header extends AbstractPart
* @param string $value
* @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) {
$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()
{
$styles = array('Font', 'Paragraph');
$styles = array('Font', 'Paragraph', 'Section');
foreach ($styles as $style) {
$objectClass = 'PhpOffice\\PhpWord\\Writer\\RTF\\Style\\' . $style;
$object = new $objectClass();