diff --git a/CHANGELOG.md b/CHANGELOG.md index 19d22c8f..f176fa44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/PhpWord/Writer/HTML/Style/AbstractStyle.php b/src/PhpWord/Writer/HTML/Style/AbstractStyle.php index cd37174a..c729ec55 100644 --- a/src/PhpWord/Writer/HTML/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/HTML/Style/AbstractStyle.php @@ -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 * diff --git a/src/PhpWord/Writer/RTF/Part/Document.php b/src/PhpWord/Writer/RTF/Part/Document.php index 71565044..2f5c2f8e 100644 --- a/src/PhpWord/Writer/RTF/Part/Document.php +++ b/src/PhpWord/Writer/RTF/Part/Document.php @@ -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; diff --git a/src/PhpWord/Writer/RTF/Part/Header.php b/src/PhpWord/Writer/RTF/Part/Header.php index 15a0c303..32debb06 100644 --- a/src/PhpWord/Writer/RTF/Part/Header.php +++ b/src/PhpWord/Writer/RTF/Part/Header.php @@ -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; diff --git a/src/PhpWord/Writer/RTF/Style/Border.php b/src/PhpWord/Writer/RTF/Style/Border.php new file mode 100644 index 00000000..8df6d165 --- /dev/null +++ b/src/PhpWord/Writer/RTF/Style/Border.php @@ -0,0 +1,124 @@ +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; + } +} diff --git a/src/PhpWord/Writer/RTF/Style/Section.php b/src/PhpWord/Writer/RTF/Style/Section.php new file mode 100644 index 00000000..b556e299 --- /dev/null +++ b/src/PhpWord/Writer/RTF/Style/Section.php @@ -0,0 +1,69 @@ +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; + } +} diff --git a/tests/PhpWord/Tests/Writer/RTF/StyleTest.php b/tests/PhpWord/Tests/Writer/RTF/StyleTest.php index 8b4a4441..542e34fe 100644 --- a/tests/PhpWord/Tests/Writer/RTF/StyleTest.php +++ b/tests/PhpWord/Tests/Writer/RTF/StyleTest.php @@ -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();