From b7480d81c0a507f7d6a83ca3c35f6f299e06314f Mon Sep 17 00:00:00 2001 From: Ivan Lanin Date: Fri, 25 Apr 2014 10:33:45 +0700 Subject: [PATCH] Refactor: Apply composite design pattern to Word2007/OOXML writer --- phpmd.xml | 7 +- src/PhpWord/Element/AbstractElement.php | 8 +- src/PhpWord/Element/Section.php | 5 +- src/PhpWord/Element/TOC.php | 163 ++++ src/PhpWord/Shared/XMLWriter.php | 12 +- src/PhpWord/Shared/ZipArchive.php | 2 - src/PhpWord/Style/Tab.php | 2 - src/PhpWord/TOC.php | 138 +--- src/PhpWord/Writer/HTML.php | 8 +- src/PhpWord/Writer/HTML/Element/Element.php | 2 +- src/PhpWord/Writer/HTML/Element/Image.php | 4 + src/PhpWord/Writer/HTML/Element/Note.php | 5 +- src/PhpWord/Writer/Word2007/Base.php | 751 +----------------- src/PhpWord/Writer/Word2007/Document.php | 153 ---- .../Writer/Word2007/Element/CheckBox.php | 88 ++ .../Writer/Word2007/Element/Element.php | 78 ++ .../Writer/Word2007/Element/Endnote.php | 26 + .../Writer/Word2007/Element/Footnote.php | 26 + src/PhpWord/Writer/Word2007/Element/Image.php | 148 ++++ src/PhpWord/Writer/Word2007/Element/Link.php | 51 ++ .../Writer/Word2007/Element/ListItem.php | 50 ++ src/PhpWord/Writer/Word2007/Element/Note.php | 43 + .../Writer/Word2007/Element/Object.php | 69 ++ .../Writer/Word2007/Element/PageBreak.php | 32 + .../Writer/Word2007/Element/PreserveText.php | 80 ++ src/PhpWord/Writer/Word2007/Element/TOC.php | 150 ++++ src/PhpWord/Writer/Word2007/Element/Table.php | 129 +++ src/PhpWord/Writer/Word2007/Element/Text.php | 49 ++ .../Writer/Word2007/Element/TextBreak.php | 49 ++ .../Writer/Word2007/Element/TextRun.php | 33 + src/PhpWord/Writer/Word2007/Element/Title.php | 65 ++ tests/PhpWord/Tests/Element/SectionTest.php | 3 +- tests/PhpWord/Tests/Element/TOCTest.php | 80 ++ tests/PhpWord/Tests/TOCTest.php | 61 -- tests/PhpWord/Tests/Writer/HTMLTest.php | 2 +- 35 files changed, 1454 insertions(+), 1118 deletions(-) create mode 100644 src/PhpWord/Element/TOC.php create mode 100644 src/PhpWord/Writer/Word2007/Element/CheckBox.php create mode 100644 src/PhpWord/Writer/Word2007/Element/Element.php create mode 100644 src/PhpWord/Writer/Word2007/Element/Endnote.php create mode 100644 src/PhpWord/Writer/Word2007/Element/Footnote.php create mode 100644 src/PhpWord/Writer/Word2007/Element/Image.php create mode 100644 src/PhpWord/Writer/Word2007/Element/Link.php create mode 100644 src/PhpWord/Writer/Word2007/Element/ListItem.php create mode 100644 src/PhpWord/Writer/Word2007/Element/Note.php create mode 100644 src/PhpWord/Writer/Word2007/Element/Object.php create mode 100644 src/PhpWord/Writer/Word2007/Element/PageBreak.php create mode 100644 src/PhpWord/Writer/Word2007/Element/PreserveText.php create mode 100644 src/PhpWord/Writer/Word2007/Element/TOC.php create mode 100644 src/PhpWord/Writer/Word2007/Element/Table.php create mode 100644 src/PhpWord/Writer/Word2007/Element/Text.php create mode 100644 src/PhpWord/Writer/Word2007/Element/TextBreak.php create mode 100644 src/PhpWord/Writer/Word2007/Element/TextRun.php create mode 100644 src/PhpWord/Writer/Word2007/Element/Title.php create mode 100644 tests/PhpWord/Tests/Element/TOCTest.php diff --git a/phpmd.xml b/phpmd.xml index 29542881..29b67bc4 100644 --- a/phpmd.xml +++ b/phpmd.xml @@ -4,14 +4,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd" xsi:noNamespaceSchemaLocation=" http://pmd.sf.net/ruleset_xml_schema.xsd"> - PHPPowerPoint ruleset - - - - - + diff --git a/src/PhpWord/Element/AbstractElement.php b/src/PhpWord/Element/AbstractElement.php index 9d55017a..152bdc98 100644 --- a/src/PhpWord/Element/AbstractElement.php +++ b/src/PhpWord/Element/AbstractElement.php @@ -18,7 +18,7 @@ use PhpOffice\PhpWord\Exception\InvalidObjectException; use PhpOffice\PhpWord\Shared\String; /** - * Container abstract class + * Element abstract class * * @since 0.10.0 */ @@ -567,7 +567,7 @@ abstract class AbstractElement ); // Special condition, e.g. preservetext can only exists in cell when // the cell is located in header or footer - $validContainerInContainers = array( + $validSubcontainers = array( 'preservetext' => array(array('cell'), array('header', 'footer')), 'footnote' => array(array('cell', 'textrun'), array('section')), 'endnote' => array(array('cell', 'textrun'), array('section')), @@ -580,8 +580,8 @@ abstract class AbstractElement } } // Check if a method is valid for current container, located in other container - if (array_key_exists($method, $validContainerInContainers)) { - $rules = $validContainerInContainers[$method]; + if (array_key_exists($method, $validSubcontainers)) { + $rules = $validSubcontainers[$method]; $containers = $rules[0]; $allowedDocParts = $rules[1]; foreach ($containers as $container) { diff --git a/src/PhpWord/Element/Section.php b/src/PhpWord/Element/Section.php index d3c4447b..d78904eb 100644 --- a/src/PhpWord/Element/Section.php +++ b/src/PhpWord/Element/Section.php @@ -11,7 +11,8 @@ namespace PhpOffice\PhpWord\Element; use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\Style\Section as SectionSettings; -use PhpOffice\PhpWord\TOC; +use PhpOffice\PhpWord\Element\PageBreak; +use PhpOffice\PhpWord\Element\TOC; /** * Section @@ -96,7 +97,7 @@ class Section extends AbstractElement * @param mixed $styleTOC * @param integer $minDepth * @param integer $maxDepth - * @return \PhpOffice\PhpWord\TOC + * @return \PhpOffice\PhpWord\Element\TOC */ public function addTOC($styleFont = null, $styleTOC = null, $minDepth = 1, $maxDepth = 9) { diff --git a/src/PhpWord/Element/TOC.php b/src/PhpWord/Element/TOC.php new file mode 100644 index 00000000..8f9559c9 --- /dev/null +++ b/src/PhpWord/Element/TOC.php @@ -0,0 +1,163 @@ +TOCStyle = new TOCStyle(); + + if (!is_null($styleTOC) && is_array($styleTOC)) { + foreach ($styleTOC as $key => $value) { + $this->TOCStyle->setStyleValue($key, $value); + } + } + + if (!is_null($styleFont)) { + if (is_array($styleFont)) { + $this->fontStyle = new Font(); + foreach ($styleFont as $key => $value) { + $this->fontStyle->setStyleValue($key, $value); + } + } else { + $this->fontStyle = $styleFont; + } + } + + $this->minDepth = $minDepth; + $this->maxDepth = $maxDepth; + } + + /** + * Get all titles + * + * @return array + */ + public function getTitles() + { + $titles = Titles::getTitles(); + foreach ($titles as $i => $title) { + if ($this->minDepth > $title['depth']) { + unset($titles[$i]); + } + if (($this->maxDepth != 0) && ($this->maxDepth < $title['depth'])) { + unset($titles[$i]); + } + } + $titles = array_merge(array(), $titles); + + return $titles; + } + + /** + * Get TOC Style + * + * @return \PhpOffice\PhpWord\Style\TOC + */ + public function getStyleTOC() + { + return $this->TOCStyle; + } + + /** + * Get Font Style + * + * @return \PhpOffice\PhpWord\Style\Font + */ + public function getStyleFont() + { + return $this->fontStyle; + } + + /** + * Set max depth + * + * @param int $value + */ + public function setMaxDepth($value) + { + $this->maxDepth = $value; + } + + /** + * Get Max Depth + * + * @return int Max depth of titles + */ + public function getMaxDepth() + { + return $this->maxDepth; + } + + /** + * Set min depth + * + * @param int $value + */ + public function setMinDepth($value) + { + $this->minDepth = $value; + } + + /** + * Get Min Depth + * + * @return int Min depth of titles + */ + public function getMinDepth() + { + return $this->minDepth; + } +} diff --git a/src/PhpWord/Shared/XMLWriter.php b/src/PhpWord/Shared/XMLWriter.php index 44b2313f..53f5e893 100644 --- a/src/PhpWord/Shared/XMLWriter.php +++ b/src/PhpWord/Shared/XMLWriter.php @@ -29,7 +29,7 @@ if (!defined('DATE_W3C')) { */ class XMLWriter { - /** Temporary storage method */ + /** Temporary storage location */ const STORAGE_MEMORY = 1; const STORAGE_DISK = 2; @@ -50,20 +50,20 @@ class XMLWriter /** * Create new XMLWriter * - * @param int $pTemporaryStorage Temporary storage location - * @param string $pTemporaryStorageFolder Temporary storage folder + * @param int $tempLocation Temporary storage location + * @param string $tempFolder Temporary storage folder */ - public function __construct($pTemporaryStorage = self::STORAGE_MEMORY, $pTemporaryStorageFolder = './') + public function __construct($tempLocation = self::STORAGE_MEMORY, $tempFolder = './') { // Create internal XMLWriter $this->xmlWriter = new \XMLWriter(); // Open temporary storage - if ($pTemporaryStorage == self::STORAGE_MEMORY) { + if ($tempLocation == self::STORAGE_MEMORY) { $this->xmlWriter->openMemory(); } else { // Create temporary filename - $this->tempFile = @tempnam($pTemporaryStorageFolder, 'xml'); + $this->tempFile = @tempnam($tempFolder, 'xml'); // Open storage if ($this->xmlWriter->openUri($this->tempFile) === false) { diff --git a/src/PhpWord/Shared/ZipArchive.php b/src/PhpWord/Shared/ZipArchive.php index 65c54e8d..2da7573c 100644 --- a/src/PhpWord/Shared/ZipArchive.php +++ b/src/PhpWord/Shared/ZipArchive.php @@ -9,8 +9,6 @@ namespace PhpOffice\PhpWord\Shared; -use PhpOffice\PhpWord\Exception\Exception; - // PCLZIP needs the temp path to end in a back slash // @codeCoverageIgnoreStart if (!defined('PCLZIP_TEMPORARY_DIR')) { diff --git a/src/PhpWord/Style/Tab.php b/src/PhpWord/Style/Tab.php index 7d17b01c..eb721821 100644 --- a/src/PhpWord/Style/Tab.php +++ b/src/PhpWord/Style/Tab.php @@ -9,8 +9,6 @@ namespace PhpOffice\PhpWord\Style; -use PhpOffice\PhpWord\Shared\XMLWriter; - /** * Tab style */ diff --git a/src/PhpWord/TOC.php b/src/PhpWord/TOC.php index 2513d921..af9982fa 100644 --- a/src/PhpWord/TOC.php +++ b/src/PhpWord/TOC.php @@ -24,20 +24,6 @@ class TOC */ private static $titles = array(); - /** - * TOC style - * - * @var \PhpOffice\PhpWord\Style\TOC - */ - private static $TOCStyle; - - /** - * Font style - * - * @var \PhpOffice\PhpWord\Style\Font|array|string - */ - private static $fontStyle; - /** * Title anchor * @@ -52,55 +38,6 @@ class TOC */ private static $bookmarkId = 0; - - /** - * Min title depth to show - * - * @var int - */ - private $minDepth = 1; - - /** - * Max title depth to show - * - * @var int - */ - private $maxDepth = 9; - - - /** - * Create a new Table-of-Contents Element - * - * @param mixed $styleFont - * @param array $styleTOC - * @param integer $minDepth - * @param integer $maxDepth - */ - public function __construct($styleFont = null, $styleTOC = null, $minDepth = 1, $maxDepth = 9) - { - self::$TOCStyle = new TOCStyle(); - - if (!is_null($styleTOC) && is_array($styleTOC)) { - foreach ($styleTOC as $key => $value) { - self::$TOCStyle->setStyleValue($key, $value); - } - } - - if (!is_null($styleFont)) { - if (is_array($styleFont)) { - self::$fontStyle = new Font(); - foreach ($styleFont as $key => $value) { - self::$fontStyle->setStyleValue($key, $value); - } - } else { - self::$fontStyle = $styleFont; - } - } - - $this->minDepth = $minDepth; - $this->maxDepth = $maxDepth; - } - /** * Add a Title * @@ -129,20 +66,9 @@ class TOC * * @return array */ - public function getTitles() + public static function getTitles() { - $titles = self::$titles; - foreach ($titles as $i => $title) { - if ($this->minDepth > $title['depth']) { - unset($titles[$i]); - } - if (($this->maxDepth != 0) && ($this->maxDepth < $title['depth'])) { - unset($titles[$i]); - } - } - $titles = array_merge(array(), $titles); - - return $titles; + return self::$titles; } /** @@ -152,64 +78,4 @@ class TOC { self::$titles = array(); } - - /** - * Get TOC Style - * - * @return \PhpOffice\PhpWord\Style\TOC - */ - public static function getStyleTOC() - { - return self::$TOCStyle; - } - - /** - * Get Font Style - * - * @return \PhpOffice\PhpWord\Style\Font - */ - public static function getStyleFont() - { - return self::$fontStyle; - } - - /** - * Set max depth - * - * @param int $value - */ - public function setMaxDepth($value) - { - $this->maxDepth = $value; - } - - /** - * Get Max Depth - * - * @return int Max depth of titles - */ - public function getMaxDepth() - { - return $this->maxDepth; - } - - /** - * Set min depth - * - * @param int $value - */ - public function setMinDepth($value) - { - $this->minDepth = $value; - } - - /** - * Get Min Depth - * - * @return int Min depth of titles - */ - public function getMinDepth() - { - return $this->minDepth; - } } diff --git a/src/PhpWord/Writer/HTML.php b/src/PhpWord/Writer/HTML.php index b2f71943..ad1425af 100644 --- a/src/PhpWord/Writer/HTML.php +++ b/src/PhpWord/Writer/HTML.php @@ -9,8 +9,6 @@ namespace PhpOffice\PhpWord\Writer; -use PhpOffice\PhpWord\Endnotes; -use PhpOffice\PhpWord\Footnotes; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Element\AbstractElement; @@ -168,16 +166,14 @@ class HTML extends AbstractWriter implements WriterInterface */ private function writeNotes() { - $footnote = Footnotes::getElements(); - $endnote = Endnotes::getElements(); $html = ''; - if (!empty($this->notes)) { $html .= "
"; foreach ($this->notes as $noteId => $noteMark) { $noteAnchor = "note-{$noteId}"; list($noteType, $noteTypeId) = explode('-', $noteMark); - $collection = $$noteType; + $collectionObject = 'PhpOffice\\PhpWord\\' . ($noteType == 'endnote' ? 'Endnotes' : 'Footnotes'); + $collection = $collectionObject::getElements(); if (array_key_exists($noteTypeId, $collection)) { $element = $collection[$noteTypeId]; $elmWriter = new TextRunWriter($element, true); diff --git a/src/PhpWord/Writer/HTML/Element/Element.php b/src/PhpWord/Writer/HTML/Element/Element.php index 26a1618c..c68d2743 100644 --- a/src/PhpWord/Writer/HTML/Element/Element.php +++ b/src/PhpWord/Writer/HTML/Element/Element.php @@ -77,7 +77,7 @@ class Element /** * Set parent writer * - * @param \PhpOffice\PhpWord\Writer\HTML $pWriter + * @param \PhpOffice\PhpWord\Writer\HTML $writer */ public function setParentWriter(HTML $writer) { diff --git a/src/PhpWord/Writer/HTML/Element/Image.php b/src/PhpWord/Writer/HTML/Element/Image.php index e585a278..5c15f12f 100644 --- a/src/PhpWord/Writer/HTML/Element/Image.php +++ b/src/PhpWord/Writer/HTML/Element/Image.php @@ -26,6 +26,10 @@ class Image extends Element */ public function write() { + $html = ''; + if (!$this->element instanceof ImageElement) { + return $html; + } if (!$this->getParentWriter()->isPdf()) { $imageData = $this->getBase64ImageData($this->element); if (!is_null($imageData)) { diff --git a/src/PhpWord/Writer/HTML/Element/Note.php b/src/PhpWord/Writer/HTML/Element/Note.php index ae303e1b..92fab7df 100644 --- a/src/PhpWord/Writer/HTML/Element/Note.php +++ b/src/PhpWord/Writer/HTML/Element/Note.php @@ -9,9 +9,6 @@ namespace PhpOffice\PhpWord\Writer\HTML\Element; -use PhpOffice\PhpWord\Element\Endnote; -use PhpOffice\PhpWord\Element\Footnote; - /** * Note element HTML writer * @@ -27,7 +24,7 @@ class Note extends Element public function write() { $noteId = count($this->getParentWriter()->getNotes()) + 1; - $prefix = ($this->element instanceof Endnote) ? 'endnote' : 'footnote'; + $prefix = ($this->element instanceof \PhpOffice\PhpWord\Element\Endnote) ? 'endnote' : 'footnote'; $noteMark = $prefix . '-' . $this->element->getRelationId(); $this->getParentWriter()->addNote($noteId, $noteMark); $html = "{$noteId}"; diff --git a/src/PhpWord/Writer/Word2007/Base.php b/src/PhpWord/Writer/Word2007/Base.php index e491d55c..d2b609b3 100644 --- a/src/PhpWord/Writer/Word2007/Base.php +++ b/src/PhpWord/Writer/Word2007/Base.php @@ -9,29 +9,16 @@ namespace PhpOffice\PhpWord\Writer\Word2007; -use PhpOffice\PhpWord\Element\AbstractElement; -use PhpOffice\PhpWord\Element\CheckBox; -use PhpOffice\PhpWord\Element\Endnote; -use PhpOffice\PhpWord\Element\Footnote; -use PhpOffice\PhpWord\Element\Image; -use PhpOffice\PhpWord\Element\Link; -use PhpOffice\PhpWord\Element\ListItem; -use PhpOffice\PhpWord\Element\Object; -use PhpOffice\PhpWord\Element\PreserveText; -use PhpOffice\PhpWord\Element\Table; -use PhpOffice\PhpWord\Element\Text; -use PhpOffice\PhpWord\Element\TextBreak; -use PhpOffice\PhpWord\Element\TextRun; -use PhpOffice\PhpWord\Element\Title; -use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\PhpWord; -use PhpOffice\PhpWord\Shared\String; +use PhpOffice\PhpWord\Element\AbstractElement; +use PhpOffice\PhpWord\Element\TextBreak; +use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\Shared\XMLWriter; use PhpOffice\PhpWord\Style\Cell; use PhpOffice\PhpWord\Style\Font; -use PhpOffice\PhpWord\Style\Image as ImageStyle; use PhpOffice\PhpWord\Style\Paragraph; use PhpOffice\PhpWord\Style\Table as TableStyle; +use PhpOffice\PhpWord\Writer\Word2007\Element\Element as ElementWriter; /** * Word2007 base part writer @@ -40,690 +27,6 @@ use PhpOffice\PhpWord\Style\Table as TableStyle; */ class Base extends AbstractWriterPart { - /** - * Write text element - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param \PhpOffice\PhpWord\Element\Text $text - * @param boolean $withoutP - */ - protected function writeText(XMLWriter $xmlWriter, Text $text, $withoutP = false) - { - $styleFont = $text->getFontStyle(); - $styleParagraph = $text->getParagraphStyle(); - $strText = htmlspecialchars($text->getText()); - $strText = String::controlCharacterPHP2OOXML($strText); - - if (!$withoutP) { - $xmlWriter->startElement('w:p'); - $this->writeInlineParagraphStyle($xmlWriter, $styleParagraph); - } - $xmlWriter->startElement('w:r'); - $this->writeInlineFontStyle($xmlWriter, $styleFont); - $xmlWriter->startElement('w:t'); - $xmlWriter->writeAttribute('xml:space', 'preserve'); - $xmlWriter->writeRaw($strText); - $xmlWriter->endElement(); - $xmlWriter->endElement(); // w:r - if (!$withoutP) { - $xmlWriter->endElement(); // w:p - } - } - - /** - * Write textrun element - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param \PhpOffice\PhpWord\Element\TextRun $textrun - */ - protected function writeTextRun(XMLWriter $xmlWriter, TextRun $textrun) - { - $styleParagraph = $textrun->getParagraphStyle(); - $xmlWriter->startElement('w:p'); - $this->writeInlineParagraphStyle($xmlWriter, $styleParagraph); - $this->writeContainerElements($xmlWriter, $textrun); - $xmlWriter->endElement(); // w:p - } - - /** - * Write link element - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param \PhpOffice\PhpWord\Element\Link $link - * @param boolean $withoutP - */ - protected function writeLink(XMLWriter $xmlWriter, Link $link, $withoutP = false) - { - $rId = $link->getRelationId() + ($link->isInSection() ? 6 : 0); - $linkName = $link->getLinkName(); - if (is_null($linkName)) { - $linkName = $link->getLinkSrc(); - } - $styleFont = $link->getFontStyle(); - $styleParagraph = $link->getParagraphStyle(); - - if (!$withoutP) { - $xmlWriter->startElement('w:p'); - $this->writeInlineParagraphStyle($xmlWriter, $styleParagraph); - } - $xmlWriter->startElement('w:hyperlink'); - $xmlWriter->writeAttribute('r:id', 'rId' . $rId); - $xmlWriter->writeAttribute('w:history', '1'); - $xmlWriter->startElement('w:r'); - $this->writeInlineFontStyle($xmlWriter, $styleFont); - $xmlWriter->startElement('w:t'); - $xmlWriter->writeAttribute('xml:space', 'preserve'); // needed because of drawing spaces before and after text - $xmlWriter->writeRaw($linkName); - $xmlWriter->endElement(); // w:t - $xmlWriter->endElement(); // w:r - $xmlWriter->endElement(); // w:hyperlink - if (!$withoutP) { - $xmlWriter->endElement(); // w:p - } - } - - /** - * Write title element - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param \PhpOffice\PhpWord\Element\Title $title - */ - protected function writeTitle(XMLWriter $xmlWriter, Title $title) - { - $text = htmlspecialchars($title->getText()); - $text = String::controlCharacterPHP2OOXML($text); - $anchor = $title->getAnchor(); - $bookmarkId = $title->getBookmarkId(); - $style = $title->getStyle(); - - $xmlWriter->startElement('w:p'); - - if (!empty($style)) { - $xmlWriter->startElement('w:pPr'); - $xmlWriter->startElement('w:pStyle'); - $xmlWriter->writeAttribute('w:val', $style); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - } - - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:fldChar'); - $xmlWriter->writeAttribute('w:fldCharType', 'end'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - - $xmlWriter->startElement('w:bookmarkStart'); - $xmlWriter->writeAttribute('w:id', $bookmarkId); - $xmlWriter->writeAttribute('w:name', $anchor); - $xmlWriter->endElement(); - - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:t'); - $xmlWriter->writeRaw($text); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - - $xmlWriter->startElement('w:bookmarkEnd'); - $xmlWriter->writeAttribute('w:id', $bookmarkId); - $xmlWriter->endElement(); - - $xmlWriter->endElement(); - } - - /** - * Write preserve text element - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param \PhpOffice\PhpWord\Element\PreserveText $textrun - */ - protected function writePreserveText(XMLWriter $xmlWriter, PreserveText $textrun) - { - $styleFont = $textrun->getFontStyle(); - $styleParagraph = $textrun->getParagraphStyle(); - - $arrText = $textrun->getText(); - if (!is_array($arrText)) { - $arrText = array($arrText); - } - - $xmlWriter->startElement('w:p'); - $this->writeInlineParagraphStyle($xmlWriter, $styleParagraph); - foreach ($arrText as $text) { - if (substr($text, 0, 1) == '{') { - $text = substr($text, 1, -1); - - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:fldChar'); - $xmlWriter->writeAttribute('w:fldCharType', 'begin'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - - $xmlWriter->startElement('w:r'); - $this->writeInlineFontStyle($xmlWriter, $styleFont); - $xmlWriter->startElement('w:instrText'); - $xmlWriter->writeAttribute('xml:space', 'preserve'); - $xmlWriter->writeRaw($text); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:fldChar'); - $xmlWriter->writeAttribute('w:fldCharType', 'separate'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:fldChar'); - $xmlWriter->writeAttribute('w:fldCharType', 'end'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - } else { - $text = htmlspecialchars($text); - $text = String::controlCharacterPHP2OOXML($text); - - $xmlWriter->startElement('w:r'); - $this->writeInlineFontStyle($xmlWriter, $styleFont); - $xmlWriter->startElement('w:t'); - $xmlWriter->writeAttribute('xml:space', 'preserve'); - $xmlWriter->writeRaw($text); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - } - } - - $xmlWriter->endElement(); // p - } - - /** - * Write text break element - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param \PhpOffice\PhpWord\Element\TextBreak $element - * @param boolean $withoutP - */ - protected function writeTextBreak(XMLWriter $xmlWriter, TextBreak $element = null, $withoutP = false) - { - if (!$withoutP) { - $hasStyle = false; - $styleFont = null; - $styleParagraph = null; - if (!is_null($element)) { - $styleFont = $element->getFontStyle(); - $styleParagraph = $element->getParagraphStyle(); - $hasStyle = !is_null($styleFont) || !is_null($styleParagraph); - } - if ($hasStyle) { - $xmlWriter->startElement('w:p'); - $this->writeInlineParagraphStyle($xmlWriter, $styleParagraph); - if (!is_null($styleFont)) { - $xmlWriter->startElement('w:pPr'); - $this->writeInlineFontStyle($xmlWriter, $styleFont); - $xmlWriter->endElement(); // w:pPr - } - $xmlWriter->endElement(); // w:p - } else { - $xmlWriter->writeElement('w:p'); - } - } else { - $xmlWriter->writeElement('w:br'); - } - } - - /** - * Write list item element - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param \PhpOffice\PhpWord\Element\ListItem $listItem - */ - protected function writeListItem(XMLWriter $xmlWriter, ListItem $listItem) - { - $textObject = $listItem->getTextObject(); - $depth = $listItem->getDepth(); - $numId = $listItem->getStyle()->getNumId(); - $styleParagraph = $textObject->getParagraphStyle(); - - $xmlWriter->startElement('w:p'); - $xmlWriter->startElement('w:pPr'); - $this->writeInlineParagraphStyle($xmlWriter, $styleParagraph, true); - $xmlWriter->startElement('w:numPr'); - $xmlWriter->startElement('w:ilvl'); - $xmlWriter->writeAttribute('w:val', $depth); - $xmlWriter->endElement(); // w:ilvl - $xmlWriter->startElement('w:numId'); - $xmlWriter->writeAttribute('w:val', $numId); - $xmlWriter->endElement(); // w:numId - $xmlWriter->endElement(); // w:numPr - $xmlWriter->endElement(); // w:pPr - $this->writeText($xmlWriter, $textObject, true); - $xmlWriter->endElement(); // w:p - } - - /** - * Write footnote reference element - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param \PhpOffice\PhpWord\Element\Table $table - */ - protected function writeTable(XMLWriter $xmlWriter, Table $table) - { - $rows = $table->getRows(); - $cRows = count($rows); - - if ($cRows > 0) { - $xmlWriter->startElement('w:tbl'); - - // Table grid - $cellWidths = array(); - for ($i = 0; $i < $cRows; $i++) { - $row = $rows[$i]; - $cells = $row->getCells(); - if (count($cells) <= count($cellWidths)) { - continue; - } - $cellWidths = array(); - foreach ($cells as $cell) { - $cellWidths[] = $cell->getWidth(); - } - } - $xmlWriter->startElement('w:tblGrid'); - foreach ($cellWidths as $width) { - $xmlWriter->startElement('w:gridCol'); - if (!is_null($width)) { - $xmlWriter->writeAttribute('w:w', $width); - $xmlWriter->writeAttribute('w:type', 'dxa'); - } - $xmlWriter->endElement(); - } - $xmlWriter->endElement(); // w:tblGrid - - // Table style - $tblStyle = $table->getStyle(); - $tblWidth = $table->getWidth(); - if ($tblStyle instanceof TableStyle) { - $this->writeTableStyle($xmlWriter, $tblStyle, false); - } else { - if (!empty($tblStyle)) { - $xmlWriter->startElement('w:tblPr'); - $xmlWriter->startElement('w:tblStyle'); - $xmlWriter->writeAttribute('w:val', $tblStyle); - $xmlWriter->endElement(); - if (!is_null($tblWidth)) { - $xmlWriter->startElement('w:tblW'); - $xmlWriter->writeAttribute('w:w', $tblWidth); - $xmlWriter->writeAttribute('w:type', 'pct'); - $xmlWriter->endElement(); - } - $xmlWriter->endElement(); - } - } - - // Table rows - for ($i = 0; $i < $cRows; $i++) { - $row = $rows[$i]; - $height = $row->getHeight(); - $rowStyle = $row->getStyle(); - $tblHeader = $rowStyle->getTblHeader(); - $cantSplit = $rowStyle->getCantSplit(); - $exactHeight = $rowStyle->getExactHeight(); - - $xmlWriter->startElement('w:tr'); - if (!is_null($height) || !is_null($tblHeader) || !is_null($cantSplit)) { - $xmlWriter->startElement('w:trPr'); - if (!is_null($height)) { - $xmlWriter->startElement('w:trHeight'); - $xmlWriter->writeAttribute('w:val', $height); - $xmlWriter->writeAttribute('w:hRule', ($exactHeight ? 'exact' : 'atLeast')); - $xmlWriter->endElement(); - } - if ($tblHeader) { - $xmlWriter->startElement('w:tblHeader'); - $xmlWriter->writeAttribute('w:val', '1'); - $xmlWriter->endElement(); - } - if ($cantSplit) { - $xmlWriter->startElement('w:cantSplit'); - $xmlWriter->writeAttribute('w:val', '1'); - $xmlWriter->endElement(); - } - $xmlWriter->endElement(); - } - foreach ($row->getCells() as $cell) { - $cellStyle = $cell->getStyle(); - $width = $cell->getWidth(); - $xmlWriter->startElement('w:tc'); - $xmlWriter->startElement('w:tcPr'); - $xmlWriter->startElement('w:tcW'); - $xmlWriter->writeAttribute('w:w', $width); - $xmlWriter->writeAttribute('w:type', 'dxa'); - $xmlWriter->endElement(); // w:tcW - if ($cellStyle instanceof Cell) { - $this->writeCellStyle($xmlWriter, $cellStyle); - } - $xmlWriter->endElement(); // w:tcPr - $this->writeContainerElements($xmlWriter, $cell); - $xmlWriter->endElement(); // w:tc - } - $xmlWriter->endElement(); // w:tr - } - $xmlWriter->endElement(); - } - } - - /** - * Write image element - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param \PhpOffice\PhpWord\Element\Image $image - * @param boolean $withoutP - */ - protected function writeImage(XMLWriter $xmlWriter, Image $image, $withoutP = false) - { - $rId = $image->getRelationId() + ($image->isInSection() ? 6 : 0); - - $style = $image->getStyle(); - $width = $style->getWidth(); - $height = $style->getHeight(); - $align = $style->getAlign(); - $marginTop = $style->getMarginTop(); - $marginLeft = $style->getMarginLeft(); - $wrappingStyle = $style->getWrappingStyle(); - $w10wrapType = null; - - if (!$withoutP) { - $xmlWriter->startElement('w:p'); - if (!is_null($align)) { - $xmlWriter->startElement('w:pPr'); - $xmlWriter->startElement('w:jc'); - $xmlWriter->writeAttribute('w:val', $align); - $xmlWriter->endElement(); // w:jc - $xmlWriter->endElement(); // w:pPr - } - } - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:pict'); - $xmlWriter->startElement('v:shape'); - $xmlWriter->writeAttribute('type', '#_x0000_t75'); - $imgStyle = ''; - if (null !== $width) { - $imgStyle .= 'width:' . $width . 'px;'; - } - if (null !== $height) { - $imgStyle .= 'height:' . $height . 'px;'; - } - if (null !== $marginTop) { - $imgStyle .= 'margin-top:' . $marginTop . 'in;'; - } - if (null !== $marginLeft) { - $imgStyle .= 'margin-left:' . $marginLeft . 'in;'; - } - switch ($wrappingStyle) { - case ImageStyle::WRAPPING_STYLE_BEHIND: - $imgStyle .= 'position:absolute;z-index:-251658752;'; - break; - case ImageStyle::WRAPPING_STYLE_INFRONT: - $imgStyle .= 'position:absolute;z-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;'; - break; - case ImageStyle::WRAPPING_STYLE_SQUARE: - $imgStyle .= 'position:absolute;z-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;'; - $w10wrapType = 'square'; - break; - case ImageStyle::WRAPPING_STYLE_TIGHT: - $imgStyle .= 'position:absolute;z-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;'; - $w10wrapType = 'tight'; - break; - } - $xmlWriter->writeAttribute('style', $imgStyle); - - $xmlWriter->startElement('v:imagedata'); - $xmlWriter->writeAttribute('r:id', 'rId' . $rId); - $xmlWriter->writeAttribute('o:title', ''); - $xmlWriter->endElement(); // v:imagedata - - if (!is_null($w10wrapType)) { - $xmlWriter->startElement('w10:wrap'); - $xmlWriter->writeAttribute('type', $w10wrapType); - $xmlWriter->endElement(); // w10:wrap - } - - $xmlWriter->endElement(); // v:shape - $xmlWriter->endElement(); // w:pict - $xmlWriter->endElement(); // w:r - - if (!$withoutP) { - $xmlWriter->endElement(); // w:p - } - } - - /** - * Write watermark element - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param \PhpOffice\PhpWord\Element\Image $image - */ - protected function writeWatermark(XMLWriter $xmlWriter, Image $image) - { - $rId = $image->getRelationId(); - - $style = $image->getStyle(); - $width = $style->getWidth(); - $height = $style->getHeight(); - $marginLeft = $style->getMarginLeft(); - $marginTop = $style->getMarginTop(); - - $xmlWriter->startElement('w:p'); - - $xmlWriter->startElement('w:r'); - - $xmlWriter->startElement('w:pict'); - - $xmlWriter->startElement('v:shape'); - $xmlWriter->writeAttribute('type', '#_x0000_t75'); - - $strStyle = 'position:absolute;'; - $strStyle .= ' width:' . $width . 'px;'; - $strStyle .= ' height:' . $height . 'px;'; - if (!is_null($marginTop)) { - $strStyle .= ' margin-top:' . $marginTop . 'px;'; - } - if (!is_null($marginLeft)) { - $strStyle .= ' margin-left:' . $marginLeft . 'px;'; - } - - $xmlWriter->writeAttribute('style', $strStyle); - - $xmlWriter->startElement('v:imagedata'); - $xmlWriter->writeAttribute('r:id', 'rId' . $rId); - $xmlWriter->writeAttribute('o:title', ''); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - - $xmlWriter->endElement(); - - $xmlWriter->endElement(); - - $xmlWriter->endElement(); - } - - /** - * Write object element - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param \PhpOffice\PhpWord\Element\Object $object - * @param boolean $withoutP - */ - protected function writeObject(XMLWriter $xmlWriter, Object $object, $withoutP = false) - { - $rIdObject = $object->getRelationId() + ($object->isInSection() ? 6 : 0); - $rIdImage = $object->getImageRelationId() + ($object->isInSection() ? 6 : 0); - $shapeId = md5($rIdObject . '_' . $rIdImage); - $objectId = $object->getRelationId() + 1325353440; - $style = $object->getStyle(); - $align = $style->getAlign(); - - if (!$withoutP) { - $xmlWriter->startElement('w:p'); - } - if (!is_null($align)) { - $xmlWriter->startElement('w:pPr'); - $xmlWriter->startElement('w:jc'); - $xmlWriter->writeAttribute('w:val', $align); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - } - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:object'); - $xmlWriter->writeAttribute('w:dxaOrig', '249'); - $xmlWriter->writeAttribute('w:dyaOrig', '160'); - $xmlWriter->startElement('v:shape'); - $xmlWriter->writeAttribute('id', $shapeId); - $xmlWriter->writeAttribute('type', '#_x0000_t75'); - $xmlWriter->writeAttribute('style', 'width:104px;height:67px'); - $xmlWriter->writeAttribute('o:ole', ''); - $xmlWriter->startElement('v:imagedata'); - $xmlWriter->writeAttribute('r:id', 'rId' . $rIdImage); - $xmlWriter->writeAttribute('o:title', ''); - $xmlWriter->endElement(); // v:imagedata - $xmlWriter->endElement(); // v:shape - $xmlWriter->startElement('o:OLEObject'); - $xmlWriter->writeAttribute('Type', 'Embed'); - $xmlWriter->writeAttribute('ProgID', 'Package'); - $xmlWriter->writeAttribute('ShapeID', $shapeId); - $xmlWriter->writeAttribute('DrawAspect', 'Icon'); - $xmlWriter->writeAttribute('ObjectID', '_' . $objectId); - $xmlWriter->writeAttribute('r:id', 'rId' . $rIdObject); - $xmlWriter->endElement(); // o:OLEObject - $xmlWriter->endElement(); // w:object - $xmlWriter->endElement(); // w:r - if (!$withoutP) { - $xmlWriter->endElement(); // w:p - } - } - - /** - * Write footnote element which links to the actual content in footnotes.xml - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param \PhpOffice\PhpWord\Element\Footnote $footnote - * @param boolean $withoutP - */ - protected function writeFootnote(XMLWriter $xmlWriter, Footnote $footnote, $withoutP = false) - { - if (!$withoutP) { - $xmlWriter->startElement('w:p'); - } - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:rPr'); - $xmlWriter->startElement('w:rStyle'); - $xmlWriter->writeAttribute('w:val', 'FootnoteReference'); - $xmlWriter->endElement(); // w:rStyle - $xmlWriter->endElement(); // w:rPr - $xmlWriter->startElement('w:footnoteReference'); - $xmlWriter->writeAttribute('w:id', $footnote->getRelationId()); - $xmlWriter->endElement(); // w:footnoteReference - $xmlWriter->endElement(); // w:r - if (!$withoutP) { - $xmlWriter->endElement(); // w:p - } - } - - /** - * Write endnote element which links to the actual content in endnotes.xml - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param \PhpOffice\PhpWord\Element\Endnote $endnote - * @param boolean $withoutP - */ - protected function writeEndnote(XMLWriter $xmlWriter, Endnote $endnote, $withoutP = false) - { - if (!$withoutP) { - $xmlWriter->startElement('w:p'); - } - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:rPr'); - $xmlWriter->startElement('w:rStyle'); - $xmlWriter->writeAttribute('w:val', 'EndnoteReference'); - $xmlWriter->endElement(); // w:rStyle - $xmlWriter->endElement(); // w:rPr - $xmlWriter->startElement('w:endnoteReference'); - $xmlWriter->writeAttribute('w:id', $endnote->getRelationId()); - $xmlWriter->endElement(); // w:endnoteReference - $xmlWriter->endElement(); // w:r - if (!$withoutP) { - $xmlWriter->endElement(); // w:p - } - } - - /** - * Write CheckBox - * - * @param boolean $withoutP - * @param boolean $checkState - */ - protected function writeCheckBox(XMLWriter $xmlWriter, CheckBox $checkbox, $withoutP = false, $checkState = false) - { - $name = htmlspecialchars($checkbox->getName()); - $name = String::controlCharacterPHP2OOXML($name); - $text = htmlspecialchars($checkbox->getText()); - $text = String::controlCharacterPHP2OOXML($text); - $styleFont = $checkbox->getFontStyle(); - $styleParagraph = $checkbox->getParagraphStyle(); - - if (!$withoutP) { - $xmlWriter->startElement('w:p'); - $this->writeInlineParagraphStyle($xmlWriter, $styleParagraph); - } - - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:fldChar'); - $xmlWriter->writeAttribute('w:fldCharType', 'begin'); - $xmlWriter->startElement('w:ffData'); - $xmlWriter->startElement('w:name'); - $xmlWriter->writeAttribute('w:val', $name); - $xmlWriter->endElement(); //w:name - $xmlWriter->writeAttribute('w:enabled', ''); - $xmlWriter->startElement('w:calcOnExit'); - $xmlWriter->writeAttribute('w:val', '0'); - $xmlWriter->endElement(); //w:calcOnExit - $xmlWriter->startElement('w:checkBox'); - $xmlWriter->writeAttribute('w:sizeAuto', ''); - $xmlWriter->startElement('w:default'); - $xmlWriter->writeAttribute('w:val', ($checkState ? '1' : '0')); - $xmlWriter->endElement(); //w:default - $xmlWriter->endElement(); //w:checkBox - $xmlWriter->endElement(); // w:ffData - $xmlWriter->endElement(); // w:fldChar - $xmlWriter->endElement(); // w:r - - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:instrText'); - $xmlWriter->writeAttribute('xml:space', 'preserve'); - $xmlWriter->writeRaw(' FORMCHECKBOX '); - $xmlWriter->endElement();// w:instrText - $xmlWriter->endElement(); // w:r - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:fldChar'); - $xmlWriter->writeAttribute('w:fldCharType', 'seperate'); - $xmlWriter->endElement();// w:fldChar - $xmlWriter->endElement(); // w:r - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:fldChar'); - $xmlWriter->writeAttribute('w:fldCharType', 'end'); - $xmlWriter->endElement();// w:fldChar - $xmlWriter->endElement(); // w:r - - $xmlWriter->startElement('w:r'); - $this->writeInlineFontStyle($xmlWriter, $styleFont); - $xmlWriter->startElement('w:t'); - $xmlWriter->writeAttribute('xml:space', 'preserve'); - $xmlWriter->writeRaw($text); - $xmlWriter->endElement(); // w:t - $xmlWriter->endElement(); // w:r - - if (!$withoutP) { - $xmlWriter->endElement(); // w:p - } - } - /** * Write paragraph style * @@ -731,7 +34,7 @@ class Base extends AbstractWriterPart * @param \PhpOffice\PhpWord\Style\Paragraph $style * @param bool $withoutPPR */ - protected function writeParagraphStyle(XMLWriter $xmlWriter, Paragraph $style, $withoutPPR = false) + public function writeParagraphStyle(XMLWriter $xmlWriter, Paragraph $style, $withoutPPR = false) { $align = $style->getAlign(); @@ -840,7 +143,7 @@ class Base extends AbstractWriterPart * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param \PhpOffice\PhpWord\Style\Font $style */ - protected function writeFontStyle(XMLWriter $xmlWriter, Font $style) + public function writeFontStyle(XMLWriter $xmlWriter, Font $style) { $font = $style->getName(); $bold = $style->getBold(); @@ -945,7 +248,7 @@ class Base extends AbstractWriterPart * @param \PhpOffice\PhpWord\Style\Table $style * @param boolean $isFullStyle */ - protected function writeTableStyle(XMLWriter $xmlWriter, TableStyle $style, $isFullStyle = true) + public function writeTableStyle(XMLWriter $xmlWriter, TableStyle $style, $isFullStyle = true) { $bgColor = $style->getBgColor(); $brdCol = $style->getBorderColor(); @@ -1008,7 +311,7 @@ class Base extends AbstractWriterPart * @param string $type * @param \PhpOffice\PhpWord\Style\Table $style */ - protected function writeRowStyle(XMLWriter $xmlWriter, $type, TableStyle $style) + public function writeRowStyle(XMLWriter $xmlWriter, $type, TableStyle $style) { $bgColor = $style->getBgColor(); @@ -1049,7 +352,7 @@ class Base extends AbstractWriterPart * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param \PhpOffice\PhpWord\Style\Cell $style */ - protected function writeCellStyle(XMLWriter $xmlWriter, Cell $style) + public function writeCellStyle(XMLWriter $xmlWriter, Cell $style) { $bgColor = $style->getBgColor(); $valign = $style->getVAlign(); @@ -1117,7 +420,7 @@ class Base extends AbstractWriterPart * @param \PhpOffice\PhpWord\Style\Paragraph|string $styleParagraph * @param boolean $withoutPPR */ - protected function writeInlineParagraphStyle(XMLWriter $xmlWriter, $styleParagraph = null, $withoutPPR = false) + public function writeInlineParagraphStyle(XMLWriter $xmlWriter, $styleParagraph = null, $withoutPPR = false) { if ($styleParagraph instanceof Paragraph) { $this->writeParagraphStyle($xmlWriter, $styleParagraph, $withoutPPR); @@ -1142,7 +445,7 @@ class Base extends AbstractWriterPart * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param \PhpOffice\PhpWord\Style\Font|string $styleFont */ - protected function writeInlineFontStyle(XMLWriter $xmlWriter, $styleFont = null) + public function writeInlineFontStyle(XMLWriter $xmlWriter, $styleFont = null) { if ($styleFont instanceof Font) { $this->writeFontStyle($xmlWriter, $styleFont); @@ -1163,7 +466,7 @@ class Base extends AbstractWriterPart * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param \PhpOffice\PhpWord\Element\AbstractElement $container */ - protected function writeContainerElements(XMLWriter $xmlWriter, AbstractElement $container) + public function writeContainerElements(XMLWriter $xmlWriter, AbstractElement $container) { // Check allowed elements $elmCommon = array('Text', 'Link', 'TextBreak', 'Image', 'Object'); @@ -1179,40 +482,24 @@ class Base extends AbstractWriterPart ); $containerName = get_class($container); $containerName = substr($containerName, strrpos($containerName, '\\') + 1); - if (array_key_exists($containerName, $allowedElements)) { - $containerElements = $allowedElements[$containerName]; - } else { + if (!array_key_exists($containerName, $allowedElements)) { throw new Exception('Invalid container.'); } // Loop through elements $elements = $container->getElements(); + $withoutP = in_array($containerName, array('TextRun', 'Footnote', 'Endnote')) ? true : false; if (count($elements) > 0) { foreach ($elements as $element) { - $elmName = get_class($element); - $elmName = substr($elmName, strrpos($elmName, '\\') + 1); - if (in_array($elmName, $containerElements)) { - $method = "write{$elmName}"; - // Image on Header could be watermark - if ($containerName == 'Header' && $elmName == 'Image') { - if ($element->getIsWatermark()) { - $method = "writeWatermark"; - } - } - switch ($containerName) { - case 'TextRun': - case 'Footnote': - case 'Endnote': - $this->$method($xmlWriter, $element, true); - break; - default: - $this->$method($xmlWriter, $element); - } + if ($element instanceof AbstractElement) { + $elementWriter = new ElementWriter($xmlWriter, $this, $element, $withoutP); + $elementWriter->write(); } } } else { if ($containerName == 'Cell') { - $this->writeTextBreak($xmlWriter); + $elementWriter = new ElementWriter($xmlWriter, $this, new TextBreak(), $withoutP); + $elementWriter->write(); } } } diff --git a/src/PhpWord/Writer/Word2007/Document.php b/src/PhpWord/Writer/Word2007/Document.php index 645e5cf2..86b7fd59 100644 --- a/src/PhpWord/Writer/Word2007/Document.php +++ b/src/PhpWord/Writer/Word2007/Document.php @@ -10,12 +10,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007; use PhpOffice\PhpWord\PhpWord; -use PhpOffice\PhpWord\TOC; -use PhpOffice\PhpWord\Element\PageBreak; use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\Shared\XMLWriter; -use PhpOffice\PhpWord\Style\Font; /** * Word2007 document part writer @@ -202,154 +199,4 @@ class Document extends Base $xmlWriter->endElement(); } - - /** - * Write page break element - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param \PhpOffice\PhpWord\Element\PageBreak $pagebreak - */ - protected function writePageBreak(XMLWriter $xmlWriter, PageBreak $pagebreak) - { - $xmlWriter->startElement('w:p'); - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:br'); - $xmlWriter->writeAttribute('w:type', 'page'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - } - - /** - * Write TOC element - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param \PhpOffice\PhpWord\TOC $toc - */ - protected function writeTOC(XMLWriter $xmlWriter, TOC $toc) - { - $titles = $toc->getTitles(); - $styleFont = $toc->getStyleFont(); - - $styleTOC = $toc->getStyleTOC(); - $fIndent = $styleTOC->getIndent(); - $tabLeader = $styleTOC->getTabLeader(); - $tabPos = $styleTOC->getTabPos(); - - $maxDepth = $toc->getMaxDepth(); - $minDepth = $toc->getMinDepth(); - - $isObject = ($styleFont instanceof Font) ? true : false; - - for ($i = 0; $i < count($titles); $i++) { - $title = $titles[$i]; - $indent = ($title['depth'] - 1) * $fIndent; - - $xmlWriter->startElement('w:p'); - - $xmlWriter->startElement('w:pPr'); - - if ($isObject && !is_null($styleFont->getParagraphStyle())) { - $this->writeParagraphStyle($xmlWriter, $styleFont->getParagraphStyle()); - } - - if ($indent > 0) { - $xmlWriter->startElement('w:ind'); - $xmlWriter->writeAttribute('w:left', $indent); - $xmlWriter->endElement(); - } - - if (!empty($styleFont) && !$isObject) { - $xmlWriter->startElement('w:pPr'); - $xmlWriter->startElement('w:pStyle'); - $xmlWriter->writeAttribute('w:val', $styleFont); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - } - - $xmlWriter->startElement('w:tabs'); - $xmlWriter->startElement('w:tab'); - $xmlWriter->writeAttribute('w:val', 'right'); - if (!empty($tabLeader)) { - $xmlWriter->writeAttribute('w:leader', $tabLeader); - } - $xmlWriter->writeAttribute('w:pos', $tabPos); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - - $xmlWriter->endElement(); // w:pPr - - - if ($i == 0) { - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:fldChar'); - $xmlWriter->writeAttribute('w:fldCharType', 'begin'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:instrText'); - $xmlWriter->writeAttribute('xml:space', 'preserve'); - $xmlWriter->writeRaw('TOC \o "' . $minDepth . '-' . $maxDepth . '" \h \z \u'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:fldChar'); - $xmlWriter->writeAttribute('w:fldCharType', 'separate'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - } - - $xmlWriter->startElement('w:hyperlink'); - $xmlWriter->writeAttribute('w:anchor', $title['anchor']); - $xmlWriter->writeAttribute('w:history', '1'); - - $xmlWriter->startElement('w:r'); - - if ($isObject) { - $this->writeFontStyle($xmlWriter, $styleFont); - } - - $xmlWriter->startElement('w:t'); - $xmlWriter->writeRaw($title['text']); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - - $xmlWriter->startElement('w:r'); - $xmlWriter->writeElement('w:tab', null); - $xmlWriter->endElement(); - - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:fldChar'); - $xmlWriter->writeAttribute('w:fldCharType', 'begin'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:instrText'); - $xmlWriter->writeAttribute('xml:space', 'preserve'); - $xmlWriter->writeRaw('PAGEREF ' . $title['anchor'] . ' \h'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:fldChar'); - $xmlWriter->writeAttribute('w:fldCharType', 'end'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - - $xmlWriter->endElement(); // w:hyperlink - - $xmlWriter->endElement(); // w:p - } - - $xmlWriter->startElement('w:p'); - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:fldChar'); - $xmlWriter->writeAttribute('w:fldCharType', 'end'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - } } diff --git a/src/PhpWord/Writer/Word2007/Element/CheckBox.php b/src/PhpWord/Writer/Word2007/Element/CheckBox.php new file mode 100644 index 00000000..af5ca349 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/CheckBox.php @@ -0,0 +1,88 @@ +element->getName()); + $name = String::controlCharacterPHP2OOXML($name); + $text = htmlspecialchars($this->element->getText()); + $text = String::controlCharacterPHP2OOXML($text); + $fStyle = $this->element->getFontStyle(); + $pStyle = $this->element->getParagraphStyle(); + + if (!$this->withoutP) { + $this->xmlWriter->startElement('w:p'); + $this->parentWriter->writeInlineParagraphStyle($this->xmlWriter, $pStyle); + } + + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:fldChar'); + $this->xmlWriter->writeAttribute('w:fldCharType', 'begin'); + $this->xmlWriter->startElement('w:ffData'); + $this->xmlWriter->startElement('w:name'); + $this->xmlWriter->writeAttribute('w:val', $name); + $this->xmlWriter->endElement(); //w:name + $this->xmlWriter->writeAttribute('w:enabled', ''); + $this->xmlWriter->startElement('w:calcOnExit'); + $this->xmlWriter->writeAttribute('w:val', '0'); + $this->xmlWriter->endElement(); //w:calcOnExit + $this->xmlWriter->startElement('w:checkBox'); + $this->xmlWriter->writeAttribute('w:sizeAuto', ''); + $this->xmlWriter->startElement('w:default'); + $this->xmlWriter->writeAttribute('w:val', 0); + $this->xmlWriter->endElement(); //w:default + $this->xmlWriter->endElement(); //w:checkBox + $this->xmlWriter->endElement(); // w:ffData + $this->xmlWriter->endElement(); // w:fldChar + $this->xmlWriter->endElement(); // w:r + + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:instrText'); + $this->xmlWriter->writeAttribute('xml:space', 'preserve'); + $this->xmlWriter->writeRaw(' FORMCHECKBOX '); + $this->xmlWriter->endElement();// w:instrText + $this->xmlWriter->endElement(); // w:r + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:fldChar'); + $this->xmlWriter->writeAttribute('w:fldCharType', 'seperate'); + $this->xmlWriter->endElement();// w:fldChar + $this->xmlWriter->endElement(); // w:r + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:fldChar'); + $this->xmlWriter->writeAttribute('w:fldCharType', 'end'); + $this->xmlWriter->endElement();// w:fldChar + $this->xmlWriter->endElement(); // w:r + + $this->xmlWriter->startElement('w:r'); + $this->parentWriter->writeInlineFontStyle($this->xmlWriter, $fStyle); + $this->xmlWriter->startElement('w:t'); + $this->xmlWriter->writeAttribute('xml:space', 'preserve'); + $this->xmlWriter->writeRaw($text); + $this->xmlWriter->endElement(); // w:t + $this->xmlWriter->endElement(); // w:r + + if (!$this->withoutP) { + $this->xmlWriter->endElement(); // w:p + } + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/Element.php b/src/PhpWord/Writer/Word2007/Element/Element.php new file mode 100644 index 00000000..f456a106 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/Element.php @@ -0,0 +1,78 @@ +xmlWriter = $xmlWriter; + $this->parentWriter = $parentWriter; + $this->element = $element; + $this->withoutP = $withoutP; + } + + /** + * Write element + * + * @return string + */ + public function write() + { + $elmName = str_replace('PhpOffice\\PhpWord\\Element\\', '', get_class($this->element)); + $elmWriterClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $elmName; + if (class_exists($elmWriterClass) === true) { + $elmWriter = new $elmWriterClass($this->xmlWriter, $this->parentWriter, $this->element, $this->withoutP); + $elmWriter->write(); + } + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/Endnote.php b/src/PhpWord/Writer/Word2007/Element/Endnote.php new file mode 100644 index 00000000..5ddf1f3a --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/Endnote.php @@ -0,0 +1,26 @@ +element->getIsWatermark()) { + $this->writeWatermark(); + } else { + $this->writeImage(); + } + } + + /** + * Write image element + */ + private function writeImage() + { + $rId = $this->element->getRelationId() + ($this->element->isInSection() ? 6 : 0); + + $style = $this->element->getStyle(); + $width = $style->getWidth(); + $height = $style->getHeight(); + $align = $style->getAlign(); + $marginTop = $style->getMarginTop(); + $marginLeft = $style->getMarginLeft(); + $wrappingStyle = $style->getWrappingStyle(); + $w10wrapType = null; + $imgStyle = ''; + if (null !== $width) { + $imgStyle .= 'width:' . $width . 'px;'; + } + if (null !== $height) { + $imgStyle .= 'height:' . $height . 'px;'; + } + if (null !== $marginTop) { + $imgStyle .= 'margin-top:' . $marginTop . 'in;'; + } + if (null !== $marginLeft) { + $imgStyle .= 'margin-left:' . $marginLeft . 'in;'; + } + switch ($wrappingStyle) { + case ImageStyle::WRAPPING_STYLE_BEHIND: + $imgStyle .= 'position:absolute;z-index:-251658752;'; + break; + case ImageStyle::WRAPPING_STYLE_INFRONT: + $imgStyle .= 'position:absolute;z-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;'; + break; + case ImageStyle::WRAPPING_STYLE_SQUARE: + $imgStyle .= 'position:absolute;z-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;'; + $w10wrapType = 'square'; + break; + case ImageStyle::WRAPPING_STYLE_TIGHT: + $imgStyle .= 'position:absolute;z-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;'; + $w10wrapType = 'tight'; + break; + } + + if (!$this->withoutP) { + $this->xmlWriter->startElement('w:p'); + if (!is_null($align)) { + $this->xmlWriter->startElement('w:pPr'); + $this->xmlWriter->startElement('w:jc'); + $this->xmlWriter->writeAttribute('w:val', $align); + $this->xmlWriter->endElement(); // w:jc + $this->xmlWriter->endElement(); // w:pPr + } + } + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:pict'); + $this->xmlWriter->startElement('v:shape'); + $this->xmlWriter->writeAttribute('type', '#_x0000_t75'); + $this->xmlWriter->writeAttribute('style', $imgStyle); + $this->xmlWriter->startElement('v:imagedata'); + $this->xmlWriter->writeAttribute('r:id', 'rId' . $rId); + $this->xmlWriter->writeAttribute('o:title', ''); + $this->xmlWriter->endElement(); // v:imagedata + if (!is_null($w10wrapType)) { + $this->xmlWriter->startElement('w10:wrap'); + $this->xmlWriter->writeAttribute('type', $w10wrapType); + $this->xmlWriter->endElement(); // w10:wrap + } + $this->xmlWriter->endElement(); // v:shape + $this->xmlWriter->endElement(); // w:pict + $this->xmlWriter->endElement(); // w:r + + if (!$this->withoutP) { + $this->xmlWriter->endElement(); // w:p + } + } + /** + * Write watermark element + */ + private function writeWatermark() + { + $rId = $this->element->getRelationId(); + + $style = $this->element->getStyle(); + $width = $style->getWidth(); + $height = $style->getHeight(); + $marginLeft = $style->getMarginLeft(); + $marginTop = $style->getMarginTop(); + $strStyle = 'position:absolute;'; + $strStyle .= ' width:' . $width . 'px;'; + $strStyle .= ' height:' . $height . 'px;'; + if (!is_null($marginTop)) { + $strStyle .= ' margin-top:' . $marginTop . 'px;'; + } + if (!is_null($marginLeft)) { + $strStyle .= ' margin-left:' . $marginLeft . 'px;'; + } + + $this->xmlWriter->startElement('w:p'); + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:pict'); + $this->xmlWriter->startElement('v:shape'); + $this->xmlWriter->writeAttribute('type', '#_x0000_t75'); + $this->xmlWriter->writeAttribute('style', $strStyle); + $this->xmlWriter->startElement('v:imagedata'); + $this->xmlWriter->writeAttribute('r:id', 'rId' . $rId); + $this->xmlWriter->writeAttribute('o:title', ''); + $this->xmlWriter->endElement(); // v:imagedata + $this->xmlWriter->endElement(); // v:shape + $this->xmlWriter->endElement(); // w:pict + $this->xmlWriter->endElement(); // w:r + $this->xmlWriter->endElement(); // w:p + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/Link.php b/src/PhpWord/Writer/Word2007/Element/Link.php new file mode 100644 index 00000000..d1114dd0 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/Link.php @@ -0,0 +1,51 @@ +element->getRelationId() + ($this->element->isInSection() ? 6 : 0); + $linkName = $this->element->getLinkName(); + if (is_null($linkName)) { + $linkName = $this->element->getLinkSrc(); + } + $fStyle = $this->element->getFontStyle(); + $pStyle = $this->element->getParagraphStyle(); + + if (!$this->withoutP) { + $this->xmlWriter->startElement('w:p'); + $this->parentWriter->writeInlineParagraphStyle($this->xmlWriter, $pStyle); + } + $this->xmlWriter->startElement('w:hyperlink'); + $this->xmlWriter->writeAttribute('r:id', 'rId' . $rId); + $this->xmlWriter->writeAttribute('w:history', '1'); + $this->xmlWriter->startElement('w:r'); + $this->parentWriter->writeInlineFontStyle($this->xmlWriter, $fStyle); + $this->xmlWriter->startElement('w:t'); + $this->xmlWriter->writeAttribute('xml:space', 'preserve'); + $this->xmlWriter->writeRaw($linkName); + $this->xmlWriter->endElement(); // w:t + $this->xmlWriter->endElement(); // w:r + $this->xmlWriter->endElement(); // w:hyperlink + if (!$this->withoutP) { + $this->xmlWriter->endElement(); // w:p + } + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/ListItem.php b/src/PhpWord/Writer/Word2007/Element/ListItem.php new file mode 100644 index 00000000..91cad693 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/ListItem.php @@ -0,0 +1,50 @@ +element->getTextObject(); + $depth = $this->element->getDepth(); + $numId = $this->element->getStyle()->getNumId(); + $pStyle = $textObject->getParagraphStyle(); + + $this->xmlWriter->startElement('w:p'); + + $this->xmlWriter->startElement('w:pPr'); + $this->parentWriter->writeInlineParagraphStyle($this->xmlWriter, $pStyle, true); + $this->xmlWriter->startElement('w:numPr'); + $this->xmlWriter->startElement('w:ilvl'); + $this->xmlWriter->writeAttribute('w:val', $depth); + $this->xmlWriter->endElement(); // w:ilvl + $this->xmlWriter->startElement('w:numId'); + $this->xmlWriter->writeAttribute('w:val', $numId); + $this->xmlWriter->endElement(); // w:numId + $this->xmlWriter->endElement(); // w:numPr + $this->xmlWriter->endElement(); // w:pPr + + $elementWriter = new ElementWriter($this->xmlWriter, $this->parentWriter, $textObject, true); + $elementWriter->write(); + + $this->xmlWriter->endElement(); // w:p + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/Note.php b/src/PhpWord/Writer/Word2007/Element/Note.php new file mode 100644 index 00000000..9c93dd86 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/Note.php @@ -0,0 +1,43 @@ +withoutP) { + $this->xmlWriter->startElement('w:p'); + } + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:rPr'); + $this->xmlWriter->startElement('w:rStyle'); + $this->xmlWriter->writeAttribute('w:val', ucfirst($referenceType)); + $this->xmlWriter->endElement(); // w:rStyle + $this->xmlWriter->endElement(); // w:rPr + $this->xmlWriter->startElement("w:{$referenceType}"); + $this->xmlWriter->writeAttribute('w:id', $this->element->getRelationId()); + $this->xmlWriter->endElement(); // w:$referenceType + $this->xmlWriter->endElement(); // w:r + if (!$this->withoutP) { + $this->xmlWriter->endElement(); // w:p + } + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/Object.php b/src/PhpWord/Writer/Word2007/Element/Object.php new file mode 100644 index 00000000..1a2dfa4a --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/Object.php @@ -0,0 +1,69 @@ +element->getRelationId() + ($this->element->isInSection() ? 6 : 0); + $rIdImage = $this->element->getImageRelationId() + ($this->element->isInSection() ? 6 : 0); + $shapeId = md5($rIdObject . '_' . $rIdImage); + $objectId = $this->element->getRelationId() + 1325353440; + $style = $this->element->getStyle(); + $align = $style->getAlign(); + + if (!$this->withoutP) { + $this->xmlWriter->startElement('w:p'); + } + if (!is_null($align)) { + $this->xmlWriter->startElement('w:pPr'); + $this->xmlWriter->startElement('w:jc'); + $this->xmlWriter->writeAttribute('w:val', $align); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + } + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:object'); + $this->xmlWriter->writeAttribute('w:dxaOrig', '249'); + $this->xmlWriter->writeAttribute('w:dyaOrig', '160'); + $this->xmlWriter->startElement('v:shape'); + $this->xmlWriter->writeAttribute('id', $shapeId); + $this->xmlWriter->writeAttribute('type', '#_x0000_t75'); + $this->xmlWriter->writeAttribute('style', 'width:104px;height:67px'); + $this->xmlWriter->writeAttribute('o:ole', ''); + $this->xmlWriter->startElement('v:imagedata'); + $this->xmlWriter->writeAttribute('r:id', 'rId' . $rIdImage); + $this->xmlWriter->writeAttribute('o:title', ''); + $this->xmlWriter->endElement(); // v:imagedata + $this->xmlWriter->endElement(); // v:shape + $this->xmlWriter->startElement('o:OLEObject'); + $this->xmlWriter->writeAttribute('Type', 'Embed'); + $this->xmlWriter->writeAttribute('ProgID', 'Package'); + $this->xmlWriter->writeAttribute('ShapeID', $shapeId); + $this->xmlWriter->writeAttribute('DrawAspect', 'Icon'); + $this->xmlWriter->writeAttribute('ObjectID', '_' . $objectId); + $this->xmlWriter->writeAttribute('r:id', 'rId' . $rIdObject); + $this->xmlWriter->endElement(); // o:OLEObject + $this->xmlWriter->endElement(); // w:object + $this->xmlWriter->endElement(); // w:r + if (!$this->withoutP) { + $this->xmlWriter->endElement(); // w:p + } + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/PageBreak.php b/src/PhpWord/Writer/Word2007/Element/PageBreak.php new file mode 100644 index 00000000..a6cdd27f --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/PageBreak.php @@ -0,0 +1,32 @@ +xmlWriter->startElement('w:p'); + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:br'); + $this->xmlWriter->writeAttribute('w:type', 'page'); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/PreserveText.php b/src/PhpWord/Writer/Word2007/Element/PreserveText.php new file mode 100644 index 00000000..53e1fee9 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/PreserveText.php @@ -0,0 +1,80 @@ +element->getFontStyle(); + $pStyle = $this->element->getParagraphStyle(); + $texts = $this->element->getText(); + if (!is_array($texts)) { + $texts = array($texts); + } + + $this->xmlWriter->startElement('w:p'); + $this->parentWriter->writeInlineParagraphStyle($this->xmlWriter, $pStyle); + foreach ($texts as $text) { + if (substr($text, 0, 1) == '{') { + $text = substr($text, 1, -1); + + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:fldChar'); + $this->xmlWriter->writeAttribute('w:fldCharType', 'begin'); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + + $this->xmlWriter->startElement('w:r'); + $this->parentWriter->writeInlineFontStyle($this->xmlWriter, $fStyle); + $this->xmlWriter->startElement('w:instrText'); + $this->xmlWriter->writeAttribute('xml:space', 'preserve'); + $this->xmlWriter->writeRaw($text); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:fldChar'); + $this->xmlWriter->writeAttribute('w:fldCharType', 'separate'); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:fldChar'); + $this->xmlWriter->writeAttribute('w:fldCharType', 'end'); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + } else { + $text = htmlspecialchars($text); + $text = String::controlCharacterPHP2OOXML($text); + + $this->xmlWriter->startElement('w:r'); + $this->parentWriter->writeInlineFontStyle($this->xmlWriter, $fStyle); + $this->xmlWriter->startElement('w:t'); + $this->xmlWriter->writeAttribute('xml:space', 'preserve'); + $this->xmlWriter->writeRaw($text); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + } + } + + $this->xmlWriter->endElement(); // p + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/TOC.php b/src/PhpWord/Writer/Word2007/Element/TOC.php new file mode 100644 index 00000000..97ae408b --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/TOC.php @@ -0,0 +1,150 @@ +element->getTitles(); + $styleFont = $this->element->getStyleFont(); + + $styleTOC = $this->element->getStyleTOC(); + $fIndent = $styleTOC->getIndent(); + $tabLeader = $styleTOC->getTabLeader(); + $tabPos = $styleTOC->getTabPos(); + + $maxDepth = $this->element->getMaxDepth(); + $minDepth = $this->element->getMinDepth(); + + $isObject = ($styleFont instanceof Font) ? true : false; + + for ($i = 0; $i < count($titles); $i++) { + $title = $titles[$i]; + $indent = ($title['depth'] - 1) * $fIndent; + + $this->xmlWriter->startElement('w:p'); + + $this->xmlWriter->startElement('w:pPr'); + + if ($isObject && !is_null($styleFont->getParagraphStyle())) { + $this->parentWriter->writeParagraphStyle($this->xmlWriter, $styleFont->getParagraphStyle()); + } + + if ($indent > 0) { + $this->xmlWriter->startElement('w:ind'); + $this->xmlWriter->writeAttribute('w:left', $indent); + $this->xmlWriter->endElement(); + } + + if (!empty($styleFont) && !$isObject) { + $this->xmlWriter->startElement('w:pPr'); + $this->xmlWriter->startElement('w:pStyle'); + $this->xmlWriter->writeAttribute('w:val', $styleFont); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + } + + $this->xmlWriter->startElement('w:tabs'); + $this->xmlWriter->startElement('w:tab'); + $this->xmlWriter->writeAttribute('w:val', 'right'); + if (!empty($tabLeader)) { + $this->xmlWriter->writeAttribute('w:leader', $tabLeader); + } + $this->xmlWriter->writeAttribute('w:pos', $tabPos); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + + $this->xmlWriter->endElement(); // w:pPr + + + if ($i == 0) { + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:fldChar'); + $this->xmlWriter->writeAttribute('w:fldCharType', 'begin'); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:instrText'); + $this->xmlWriter->writeAttribute('xml:space', 'preserve'); + $this->xmlWriter->writeRaw('TOC \o "' . $minDepth . '-' . $maxDepth . '" \h \z \u'); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:fldChar'); + $this->xmlWriter->writeAttribute('w:fldCharType', 'separate'); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + } + + $this->xmlWriter->startElement('w:hyperlink'); + $this->xmlWriter->writeAttribute('w:anchor', $title['anchor']); + $this->xmlWriter->writeAttribute('w:history', '1'); + + $this->xmlWriter->startElement('w:r'); + + if ($isObject) { + $this->parentWriter->writeFontStyle($this->xmlWriter, $styleFont); + } + + $this->xmlWriter->startElement('w:t'); + $this->xmlWriter->writeRaw($title['text']); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->writeElement('w:tab', null); + $this->xmlWriter->endElement(); + + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:fldChar'); + $this->xmlWriter->writeAttribute('w:fldCharType', 'begin'); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:instrText'); + $this->xmlWriter->writeAttribute('xml:space', 'preserve'); + $this->xmlWriter->writeRaw('PAGEREF ' . $title['anchor'] . ' \h'); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:fldChar'); + $this->xmlWriter->writeAttribute('w:fldCharType', 'end'); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + + $this->xmlWriter->endElement(); // w:hyperlink + + $this->xmlWriter->endElement(); // w:p + } + + $this->xmlWriter->startElement('w:p'); + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:fldChar'); + $this->xmlWriter->writeAttribute('w:fldCharType', 'end'); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/Table.php b/src/PhpWord/Writer/Word2007/Element/Table.php new file mode 100644 index 00000000..bcaae2ad --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/Table.php @@ -0,0 +1,129 @@ +element->getRows(); + $rowCount = count($rows); + + if ($rowCount > 0) { + $this->xmlWriter->startElement('w:tbl'); + + // Table grid + $cellWidths = array(); + for ($i = 0; $i < $rowCount; $i++) { + $row = $rows[$i]; + $cells = $row->getCells(); + if (count($cells) <= count($cellWidths)) { + continue; + } + $cellWidths = array(); + foreach ($cells as $cell) { + $cellWidths[] = $cell->getWidth(); + } + } + $this->xmlWriter->startElement('w:tblGrid'); + foreach ($cellWidths as $width) { + $this->xmlWriter->startElement('w:gridCol'); + if (!is_null($width)) { + $this->xmlWriter->writeAttribute('w:w', $width); + $this->xmlWriter->writeAttribute('w:type', 'dxa'); + } + $this->xmlWriter->endElement(); + } + $this->xmlWriter->endElement(); // w:tblGrid + + // Table style + $tblStyle = $this->element->getStyle(); + $tblWidth = $this->element->getWidth(); + if ($tblStyle instanceof TableStyle) { + $this->parentWriter->writeTableStyle($this->xmlWriter, $tblStyle, false); + } else { + if (!empty($tblStyle)) { + $this->xmlWriter->startElement('w:tblPr'); + $this->xmlWriter->startElement('w:tblStyle'); + $this->xmlWriter->writeAttribute('w:val', $tblStyle); + $this->xmlWriter->endElement(); + if (!is_null($tblWidth)) { + $this->xmlWriter->startElement('w:tblW'); + $this->xmlWriter->writeAttribute('w:w', $tblWidth); + $this->xmlWriter->writeAttribute('w:type', 'pct'); + $this->xmlWriter->endElement(); + } + $this->xmlWriter->endElement(); + } + } + + // Table rows + for ($i = 0; $i < $rowCount; $i++) { + $row = $rows[$i]; + $height = $row->getHeight(); + $rowStyle = $row->getStyle(); + $tblHeader = $rowStyle->getTblHeader(); + $cantSplit = $rowStyle->getCantSplit(); + $exactHeight = $rowStyle->getExactHeight(); + + $this->xmlWriter->startElement('w:tr'); + if (!is_null($height) || !is_null($tblHeader) || !is_null($cantSplit)) { + $this->xmlWriter->startElement('w:trPr'); + if (!is_null($height)) { + $this->xmlWriter->startElement('w:trHeight'); + $this->xmlWriter->writeAttribute('w:val', $height); + $this->xmlWriter->writeAttribute('w:hRule', ($exactHeight ? 'exact' : 'atLeast')); + $this->xmlWriter->endElement(); + } + if ($tblHeader) { + $this->xmlWriter->startElement('w:tblHeader'); + $this->xmlWriter->writeAttribute('w:val', '1'); + $this->xmlWriter->endElement(); + } + if ($cantSplit) { + $this->xmlWriter->startElement('w:cantSplit'); + $this->xmlWriter->writeAttribute('w:val', '1'); + $this->xmlWriter->endElement(); + } + $this->xmlWriter->endElement(); + } + foreach ($row->getCells() as $cell) { + $cellStyle = $cell->getStyle(); + $width = $cell->getWidth(); + $this->xmlWriter->startElement('w:tc'); + $this->xmlWriter->startElement('w:tcPr'); + $this->xmlWriter->startElement('w:tcW'); + $this->xmlWriter->writeAttribute('w:w', $width); + $this->xmlWriter->writeAttribute('w:type', 'dxa'); + $this->xmlWriter->endElement(); // w:tcW + if ($cellStyle instanceof Cell) { + $this->parentWriter->writeCellStyle($this->xmlWriter, $cellStyle); + } + $this->xmlWriter->endElement(); // w:tcPr + $this->parentWriter->writeContainerElements($this->xmlWriter, $cell); + $this->xmlWriter->endElement(); // w:tc + } + $this->xmlWriter->endElement(); // w:tr + } + $this->xmlWriter->endElement(); + } + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/Text.php b/src/PhpWord/Writer/Word2007/Element/Text.php new file mode 100644 index 00000000..ee7d8157 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/Text.php @@ -0,0 +1,49 @@ +element->getFontStyle(); + $pStyle = $this->element->getParagraphStyle(); + $text = htmlspecialchars($this->element->getText()); + $text = String::controlCharacterPHP2OOXML($text); + + if (!$this->withoutP) { + $this->xmlWriter->startElement('w:p'); + $this->parentWriter->writeInlineParagraphStyle($this->xmlWriter, $pStyle); + } + $this->xmlWriter->startElement('w:r'); + $this->parentWriter->writeInlineFontStyle($this->xmlWriter, $fStyle); + $this->xmlWriter->startElement('w:t'); + $this->xmlWriter->writeAttribute('xml:space', 'preserve'); + $this->xmlWriter->writeRaw($text); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); // w:r + if (!$this->withoutP) { + $this->xmlWriter->endElement(); // w:p + } + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/TextBreak.php b/src/PhpWord/Writer/Word2007/Element/TextBreak.php new file mode 100644 index 00000000..5c2d6476 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/TextBreak.php @@ -0,0 +1,49 @@ +withoutP) { + $hasStyle = false; + $fStyle = null; + $pStyle = null; + if (!is_null($this->element)) { + $fStyle = $this->element->getFontStyle(); + $pStyle = $this->element->getParagraphStyle(); + $hasStyle = !is_null($fStyle) || !is_null($pStyle); + } + if ($hasStyle) { + $this->xmlWriter->startElement('w:p'); + $this->parentWriter->writeInlineParagraphStyle($this->xmlWriter, $pStyle); + if (!is_null($fStyle)) { + $this->xmlWriter->startElement('w:pPr'); + $this->parentWriter->writeInlineFontStyle($this->xmlWriter, $fStyle); + $this->xmlWriter->endElement(); // w:pPr + } + $this->xmlWriter->endElement(); // w:p + } else { + $this->xmlWriter->writeElement('w:p'); + } + } else { + $this->xmlWriter->writeElement('w:br'); + } + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/TextRun.php b/src/PhpWord/Writer/Word2007/Element/TextRun.php new file mode 100644 index 00000000..8663e0fc --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/TextRun.php @@ -0,0 +1,33 @@ +element->getParagraphStyle(); + $this->xmlWriter->startElement('w:p'); + $this->parentWriter->writeInlineParagraphStyle($this->xmlWriter, $pStyle); + $this->parentWriter->writeContainerElements($this->xmlWriter, $this->element); + $this->xmlWriter->endElement(); // w:p + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/Title.php b/src/PhpWord/Writer/Word2007/Element/Title.php new file mode 100644 index 00000000..5570921f --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/Title.php @@ -0,0 +1,65 @@ +element->getAnchor(); + $bookmarkId = $this->element->getBookmarkId(); + $style = $this->element->getStyle(); + $text = htmlspecialchars($this->element->getText()); + $text = String::controlCharacterPHP2OOXML($text); + + $this->xmlWriter->startElement('w:p'); + + if (!empty($style)) { + $this->xmlWriter->startElement('w:pPr'); + $this->xmlWriter->startElement('w:pStyle'); + $this->xmlWriter->writeAttribute('w:val', $style); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + } + + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:fldChar'); + $this->xmlWriter->writeAttribute('w:fldCharType', 'end'); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + + $this->xmlWriter->startElement('w:bookmarkStart'); + $this->xmlWriter->writeAttribute('w:id', $bookmarkId); + $this->xmlWriter->writeAttribute('w:name', $anchor); + $this->xmlWriter->endElement(); + + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->startElement('w:t'); + $this->xmlWriter->writeRaw($text); + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + + $this->xmlWriter->startElement('w:bookmarkEnd'); + $this->xmlWriter->writeAttribute('w:id', $bookmarkId); + $this->xmlWriter->endElement(); + + $this->xmlWriter->endElement(); + } +} diff --git a/tests/PhpWord/Tests/Element/SectionTest.php b/tests/PhpWord/Tests/Element/SectionTest.php index d41a1e1f..415e43ad 100644 --- a/tests/PhpWord/Tests/Element/SectionTest.php +++ b/tests/PhpWord/Tests/Element/SectionTest.php @@ -95,13 +95,12 @@ class SectionTest extends \PHPUnit_Framework_TestCase $elementCollection = $section->getElements(); $elementTypes = array('Text', 'Link', 'TextBreak', 'PageBreak', 'Table', 'ListItem', 'Object', 'Image', - 'Title', 'TextRun', 'Footnote', 'CheckBox'); + 'Title', 'TextRun', 'Footnote', 'CheckBox', 'TOC'); $i = 0; foreach ($elementTypes as $elementType) { $this->assertInstanceOf("PhpOffice\\PhpWord\\Element\\{$elementType}", $elementCollection[$i]); $i++; } - $this->assertInstanceOf("PhpOffice\\PhpWord\\TOC", $elementCollection[$i]); } /** diff --git a/tests/PhpWord/Tests/Element/TOCTest.php b/tests/PhpWord/Tests/Element/TOCTest.php new file mode 100644 index 00000000..207f6969 --- /dev/null +++ b/tests/PhpWord/Tests/Element/TOCTest.php @@ -0,0 +1,80 @@ + 9062, + 'tabLeader' => \PhpOffice\PhpWord\Style\TOC::TABLEADER_DOT, + 'indent' => 200, + ); + $object = new TOC(array('_size' => 11), array('_tabPos' => $expected['tabPos'])); + $tocStyle = $object->getStyleTOC(); + + $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\TOC', $tocStyle); + $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Font', $object->getStyleFont()); + + foreach ($expected as $key => $value) { + $method = "get{$key}"; + $this->assertEquals($value, $tocStyle->$method()); + } + } + + /** + * Construct with named font style + */ + public function testConstructWithStyleName() + { + $object = new TOC('Font Style'); + $tocStyle = $object->getStyleTOC(); + + $this->assertEquals('Font Style', $object->getStyleFont()); + } + + /** + * Set/get minDepth and maxDepth + */ + public function testSetGetMinMaxDepth() + { + $toc = new TOC(); + $titles = array( + 'Heading 1' => 1, + 'Heading 2' => 2, + 'Heading 3' => 3, + 'Heading 4' => 4, + ); + foreach ($titles as $text => $depth) { + \PhpOffice\PhpWord\TOC::addTitle($text, $depth); + } + + $this->assertEquals(1, $toc->getMinDepth()); + $this->assertEquals(9, $toc->getMaxDepth()); + + $toc->setMinDepth(2); + $toc->setMaxDepth(3); + $toc->getTitles(); + + $this->assertEquals(2, $toc->getMinDepth()); + $this->assertEquals(3, $toc->getMaxDepth()); + } +} diff --git a/tests/PhpWord/Tests/TOCTest.php b/tests/PhpWord/Tests/TOCTest.php index 5417bb44..d0b73352 100644 --- a/tests/PhpWord/Tests/TOCTest.php +++ b/tests/PhpWord/Tests/TOCTest.php @@ -18,39 +18,6 @@ use PhpOffice\PhpWord\TOC; */ class TOCTest extends \PHPUnit_Framework_TestCase { - /** - * Construct with font and TOC style in array format - */ - public function testConstructWithStyleArray() - { - $expected = array( - 'tabPos' => 9062, - 'tabLeader' => \PhpOffice\PhpWord\Style\TOC::TABLEADER_DOT, - 'indent' => 200, - ); - $object = new TOC(array('_size' => 11), array('_tabPos' => $expected['tabPos'])); - $tocStyle = $object->getStyleTOC(); - - $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\TOC', $tocStyle); - $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Font', $object->getStyleFont()); - - foreach ($expected as $key => $value) { - $method = "get{$key}"; - $this->assertEquals($value, $tocStyle->$method()); - } - } - - /** - * Construct with named font style - */ - public function testConstructWithStyleName() - { - $object = new TOC('Font Style'); - $tocStyle = $object->getStyleTOC(); - - $this->assertEquals('Font Style', $object->getStyleFont()); - } - /** * Add and get title */ @@ -82,33 +49,5 @@ class TOCTest extends \PHPUnit_Framework_TestCase TOC::resetTitles(); $this->assertEquals(0, count($toc->getTitles())); - - } - - /** - * Set/get minDepth and maxDepth - */ - public function testSetGetMinMaxDepth() - { - $toc = new TOC(); - $titles = array( - 'Heading 1' => 1, - 'Heading 2' => 2, - 'Heading 3' => 3, - 'Heading 4' => 4, - ); - foreach ($titles as $text => $depth) { - $toc->addTitle($text, $depth); - } - - $this->assertEquals(1, $toc->getMinDepth()); - $this->assertEquals(9, $toc->getMaxDepth()); - - $toc->setMinDepth(2); - $toc->setMaxDepth(3); - $toc->getTitles(); - - $this->assertEquals(2, $toc->getMinDepth()); - $this->assertEquals(3, $toc->getMaxDepth()); } } diff --git a/tests/PhpWord/Tests/Writer/HTMLTest.php b/tests/PhpWord/Tests/Writer/HTMLTest.php index 354da0e6..265c4f6b 100644 --- a/tests/PhpWord/Tests/Writer/HTMLTest.php +++ b/tests/PhpWord/Tests/Writer/HTMLTest.php @@ -61,7 +61,7 @@ class HTMLTest extends \PHPUnit_Framework_TestCase $section = $phpWord->addSection(); $section->addText('Test 1', 'Font', 'Paragraph'); $section->addTextBreak(); - $section->addText('Test 2', array('name' => 'Tahoma', 'bold' => true, 'italic' => true)); + $section->addText('Test 2', array('name' => 'Tahoma', 'bold' => true, 'italic' => true, 'subscript' => true)); $section->addLink('http://test.com'); $section->addTitle('Test', 1); $section->addPageBreak();