From 2be4cbf131d57d610d5731e0bc9d25baa69f6755 Mon Sep 17 00:00:00 2001 From: Ivan Lanin Date: Fri, 25 Apr 2014 18:01:17 +0700 Subject: [PATCH] Refactor: Apply composite design pattern to RTF writer --- src/PhpWord/Writer/RTF.php | 317 +++++-------------- src/PhpWord/Writer/RTF/Element/Element.php | 72 +++++ src/PhpWord/Writer/RTF/Element/Text.php | 112 +++++++ src/PhpWord/Writer/RTF/Element/TextBreak.php | 30 ++ src/PhpWord/Writer/RTF/Element/TextRun.php | 45 +++ src/PhpWord/Writer/RTF/Element/Title.php | 33 ++ 6 files changed, 379 insertions(+), 230 deletions(-) create mode 100644 src/PhpWord/Writer/RTF/Element/Element.php create mode 100644 src/PhpWord/Writer/RTF/Element/Text.php create mode 100644 src/PhpWord/Writer/RTF/Element/TextBreak.php create mode 100644 src/PhpWord/Writer/RTF/Element/TextRun.php create mode 100644 src/PhpWord/Writer/RTF/Element/Title.php diff --git a/src/PhpWord/Writer/RTF.php b/src/PhpWord/Writer/RTF.php index ef965ea5..5d75555c 100755 --- a/src/PhpWord/Writer/RTF.php +++ b/src/PhpWord/Writer/RTF.php @@ -10,21 +10,11 @@ namespace PhpOffice\PhpWord\Writer; use PhpOffice\PhpWord\PhpWord; -use PhpOffice\PhpWord\TOC; -use PhpOffice\PhpWord\Element\Image; -use PhpOffice\PhpWord\Element\Link; -use PhpOffice\PhpWord\Element\ListItem; -use PhpOffice\PhpWord\Element\Object; -use PhpOffice\PhpWord\Element\PageBreak; -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\Shared\Drawing; use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Style\Font; +use PhpOffice\PhpWord\Writer\RTF\Element\Element as ElementWriter; /** * RTF writer @@ -77,7 +67,7 @@ class RTF extends AbstractWriter implements WriterInterface $hFile = fopen($pFilename, 'w'); if ($hFile !== false) { - fwrite($hFile, $this->getData()); + fwrite($hFile, $this->writeDocument()); fclose($hFile); } else { throw new Exception("Can't open file"); @@ -88,31 +78,70 @@ class RTF extends AbstractWriter implements WriterInterface } } + /** + * Get color table + * + * @param mixed $value + */ + public function getColorTable() + { + return $this->colorTable; + } + + /** + * Get font table + * + * @param mixed $value + */ + public function getFontTable() + { + return $this->fontTable; + } + + /** + * Set last paragraph style + * + * @param mixed $value + */ + public function setLastParagraphStyle($value = '') + { + $this->lastParagraphStyle = $value; + } + + /** + * Get last paragraph style + * + * @param mixed $value + */ + public function getLastParagraphStyle() + { + return $this->lastParagraphStyle; + } + /** * Get all data * * @return string */ - private function getData() + private function writeDocument() { - // PhpWord object : $this->phpWord $this->fontTable = $this->getDataFont(); $this->colorTable = $this->getDataColor(); - $sRTFContent = '{\rtf1'; // Set the default character set - $sRTFContent .= '\ansi\ansicpg1252'; - // Set the default font (the first one) - $sRTFContent .= '\deff0'; - // Set the default tab size (720 twips) + $sRTFContent = '{\rtf1'; + $sRTFContent .= '\ansi\ansicpg1252'; // Set the default font (the first one) + $sRTFContent .= '\deff0'; // Set the default tab size (720 twips) $sRTFContent .= '\deftab720'; $sRTFContent .= PHP_EOL; + // Set the font tbl group $sRTFContent .= '{\fonttbl'; foreach ($this->fontTable as $idx => $font) { $sRTFContent .= '{\f' . $idx . '\fnil\fcharset0 ' . $font . ';}'; } $sRTFContent .= '}' . PHP_EOL; + // Set the color tbl group $sRTFContent .= '{\colortbl '; foreach ($this->colorTable as $idx => $color) { @@ -120,32 +149,52 @@ class RTF extends AbstractWriter implements WriterInterface $sRTFContent .= ';\red' . $arrColor[0] . '\green' . $arrColor[1] . '\blue' . $arrColor[2] . ''; } $sRTFContent .= ';}' . PHP_EOL; - // Set the generator - $sRTFContent .= '{\*\generator PhpWord;}' . PHP_EOL; - // Set the view mode of the document - $sRTFContent .= '\viewkind4'; - // Set the numberof bytes that follows a unicode character - $sRTFContent .= '\uc1'; - // Resets to default paragraph properties. - $sRTFContent .= '\pard'; - // No widow/orphan control - $sRTFContent .= '\nowidctlpar'; - // Applies a language to a text run (1036 : French (France)) - $sRTFContent .= '\lang1036'; - // Point size (in half-points) above which to kern character pairs - $sRTFContent .= '\kerning1'; - // Set the font size in half-points - $sRTFContent .= '\fs' . (PhpWord::DEFAULT_FONT_SIZE * 2); - $sRTFContent .= PHP_EOL; - // Body - $sRTFContent .= $this->getDataContent(); + $sRTFContent .= '{\*\generator PhpWord;}' . PHP_EOL; // Set the generator + $sRTFContent .= '\viewkind4'; // Set the view mode of the document + $sRTFContent .= '\uc1'; // Set the numberof bytes that follows a unicode character + $sRTFContent .= '\pard'; // Resets to default paragraph properties. + $sRTFContent .= '\nowidctlpar'; // No widow/orphan control + $sRTFContent .= '\lang1036'; // Applies a language to a text run (1036 : French (France)) + $sRTFContent .= '\kerning1'; // Point size (in half-points) above which to kern character pairs + $sRTFContent .= '\fs' . (PhpWord::DEFAULT_FONT_SIZE * 2); // Set the font size in half-points + $sRTFContent .= PHP_EOL; + + // Body + $sRTFContent .= $this->writeContent(); $sRTFContent .= '}'; return $sRTFContent; } + /** + * Get content data + * + * @return string + */ + private function writeContent() + { + $phpWord = $this->phpWord; + $sRTFBody = ''; + + $sections = $phpWord->getSections(); + $countSections = count($sections); + $pSection = 0; + + if ($countSections > 0) { + foreach ($sections as $section) { + $pSection++; + $elements = $section->getElements(); + foreach ($elements as $element) { + $elementWriter = new ElementWriter($this, $element); + $sRTFBody .= $elementWriter->write(); + } + } + } + return $sRTFBody; + } + /** * Get all fonts * @@ -259,196 +308,4 @@ class RTF extends AbstractWriter implements WriterInterface return $arrColors; } - - /** - * Get content data - * - * @return string - */ - private function getDataContent() - { - $phpWord = $this->phpWord; - $sRTFBody = ''; - - $sections = $phpWord->getSections(); - $countSections = count($sections); - $pSection = 0; - - if ($countSections > 0) { - foreach ($sections as $section) { - $pSection++; - $elements = $section->getElements(); - foreach ($elements as $element) { - if ($element instanceof Text) { - $sRTFBody .= $this->getDataContentText($element); - } elseif ($element instanceof TextBreak) { - $sRTFBody .= $this->getDataContentTextBreak(); - } elseif ($element instanceof TextRun) { - $sRTFBody .= $this->getDataContentTextRun($element); - } elseif ($element instanceof Link) { - $sRTFBody .= $this->getDataContentUnsupportedElement('Link'); - } elseif ($element instanceof Title) { - $sRTFBody .= $this->getDataContentUnsupportedElement('Title'); - } elseif ($element instanceof PageBreak) { - $sRTFBody .= $this->getDataContentUnsupportedElement('Page Break'); - } elseif ($element instanceof Table) { - $sRTFBody .= $this->getDataContentUnsupportedElement('Table'); - } elseif ($element instanceof ListItem) { - $sRTFBody .= $this->getDataContentUnsupportedElement('List Item'); - } elseif ($element instanceof Image) { - $sRTFBody .= $this->getDataContentUnsupportedElement('Image'); - } elseif ($element instanceof Object) { - $sRTFBody .= $this->getDataContentUnsupportedElement('Object'); - } elseif ($element instanceof TOC) { - $sRTFBody .= $this->getDataContentUnsupportedElement('TOC'); - } else { - $sRTFBody .= $this->getDataContentUnsupportedElement('Other'); - } - } - } - } - return $sRTFBody; - } - - /** - * Get text element content - * - * @param boolean $withoutP - * @return string - */ - private function getDataContentText(Text $text, $withoutP = false) - { - $sRTFText = ''; - - $styleFont = $text->getFontStyle(); - if (is_string($styleFont)) { - $styleFont = Style::getStyle($styleFont); - } - - $styleParagraph = $text->getParagraphStyle(); - if (is_string($styleParagraph)) { - $styleParagraph = Style::getStyle($styleParagraph); - } - - if ($styleParagraph && !$withoutP) { - if ($this->lastParagraphStyle != $text->getParagraphStyle()) { - $sRTFText .= '\pard\nowidctlpar'; - if ($styleParagraph->getSpaceAfter() != null) { - $sRTFText .= '\sa' . $styleParagraph->getSpaceAfter(); - } - if ($styleParagraph->getAlign() != null) { - if ($styleParagraph->getAlign() == 'center') { - $sRTFText .= '\qc'; - } - } - $this->lastParagraphStyle = $text->getParagraphStyle(); - } else { - $this->lastParagraphStyle = ''; - } - } else { - $this->lastParagraphStyle = ''; - } - - if ($styleFont instanceof Font) { - if ($styleFont->getColor() != null) { - $idxColor = array_search($styleFont->getColor(), $this->colorTable); - if ($idxColor !== false) { - $sRTFText .= '\cf' . ($idxColor + 1); - } - } else { - $sRTFText .= '\cf0'; - } - if ($styleFont->getName() != null) { - $idxFont = array_search($styleFont->getName(), $this->fontTable); - if ($idxFont !== false) { - $sRTFText .= '\f' . $idxFont; - } - } else { - $sRTFText .= '\f0'; - } - if ($styleFont->getBold()) { - $sRTFText .= '\b'; - } - if ($styleFont->getItalic()) { - $sRTFText .= '\i'; - } - if ($styleFont->getSize()) { - $sRTFText .= '\fs' . ($styleFont->getSize() * 2); - } - } - if ($this->lastParagraphStyle != '' || $styleFont) { - $sRTFText .= ' '; - } - $sRTFText .= $text->getText(); - - if ($styleFont instanceof Font) { - $sRTFText .= '\cf0'; - $sRTFText .= '\f0'; - - if ($styleFont->getBold()) { - $sRTFText .= '\b0'; - } - if ($styleFont->getItalic()) { - $sRTFText .= '\i0'; - } - if ($styleFont->getSize()) { - $sRTFText .= '\fs' . (PhpWord::DEFAULT_FONT_SIZE * 2); - } - } - - if (!$withoutP) { - $sRTFText .= '\par' . PHP_EOL; - } - return $sRTFText; - } - - /** - * Get textrun content - * - * @return string - */ - private function getDataContentTextRun(TextRun $textrun) - { - $sRTFText = ''; - $elements = $textrun->getElements(); - if (count($elements) > 0) { - $sRTFText .= '\pard\nowidctlpar' . PHP_EOL; - foreach ($elements as $element) { - if ($element instanceof Text) { - $sRTFText .= '{'; - $sRTFText .= $this->getDataContentText($element, true); - $sRTFText .= '}' . PHP_EOL; - } - } - $sRTFText .= '\par' . PHP_EOL; - } - return $sRTFText; - } - - /** - * Get text break content - * - * @return string - */ - private function getDataContentTextBreak() - { - $this->lastParagraphStyle = ''; - - return '\par' . PHP_EOL; - } - - /** - * Get unsupported element content - * - * @param string $element - */ - private function getDataContentUnsupportedElement($element) - { - $sRTFText = ''; - $sRTFText .= '\pard\nowidctlpar' . PHP_EOL; - $sRTFText .= "{$element}"; - $sRTFText .= '\par' . PHP_EOL; - - return $sRTFText; - } } diff --git a/src/PhpWord/Writer/RTF/Element/Element.php b/src/PhpWord/Writer/RTF/Element/Element.php new file mode 100644 index 00000000..9bb3b5d9 --- /dev/null +++ b/src/PhpWord/Writer/RTF/Element/Element.php @@ -0,0 +1,72 @@ +parentWriter = $parentWriter; + $this->element = $element; + $this->withoutP = $withoutP; + } + + /** + * Write element + * + * @return string + */ + public function write() + { + $rtfText = ''; + $elmName = str_replace('PhpOffice\\PhpWord\\Element\\', '', get_class($this->element)); + $elmWriterClass = 'PhpOffice\\PhpWord\\Writer\\RTF\\Element\\' . $elmName; + if (class_exists($elmWriterClass) === true) { + $elmWriter = new $elmWriterClass($this->parentWriter, $this->element, $this->withoutP); + $rtfText = $elmWriter->write(); + } + + return $rtfText; + } +} diff --git a/src/PhpWord/Writer/RTF/Element/Text.php b/src/PhpWord/Writer/RTF/Element/Text.php new file mode 100644 index 00000000..8041b680 --- /dev/null +++ b/src/PhpWord/Writer/RTF/Element/Text.php @@ -0,0 +1,112 @@ +element->getFontStyle(); + if (is_string($styleFont)) { + $styleFont = Style::getStyle($styleFont); + } + + $styleParagraph = $this->element->getParagraphStyle(); + if (is_string($styleParagraph)) { + $styleParagraph = Style::getStyle($styleParagraph); + } + + if ($styleParagraph && !$this->withoutP) { + if ($this->parentWriter->getLastParagraphStyle() != $this->element->getParagraphStyle()) { + $rtfText .= '\pard\nowidctlpar'; + if ($styleParagraph->getSpaceAfter() != null) { + $rtfText .= '\sa' . $styleParagraph->getSpaceAfter(); + } + if ($styleParagraph->getAlign() != null) { + if ($styleParagraph->getAlign() == 'center') { + $rtfText .= '\qc'; + } + } + $this->parentWriter->setLastParagraphStyle($this->element->getParagraphStyle()); + } else { + $this->parentWriter->setLastParagraphStyle(); + } + } else { + $this->parentWriter->setLastParagraphStyle(); + } + + if ($styleFont instanceof Font) { + if ($styleFont->getColor() != null) { + $idxColor = array_search($styleFont->getColor(), $this->parentWriter->getColorTable()); + if ($idxColor !== false) { + $rtfText .= '\cf' . ($idxColor + 1); + } + } else { + $rtfText .= '\cf0'; + } + if ($styleFont->getName() != null) { + $idxFont = array_search($styleFont->getName(), $this->parentWriter->getFontTable()); + if ($idxFont !== false) { + $rtfText .= '\f' . $idxFont; + } + } else { + $rtfText .= '\f0'; + } + if ($styleFont->getBold()) { + $rtfText .= '\b'; + } + if ($styleFont->getItalic()) { + $rtfText .= '\i'; + } + if ($styleFont->getSize()) { + $rtfText .= '\fs' . ($styleFont->getSize() * 2); + } + } + if ($this->parentWriter->getLastParagraphStyle() != '' || $styleFont) { + $rtfText .= ' '; + } + $rtfText .= $this->element->getText(); + + if ($styleFont instanceof Font) { + $rtfText .= '\cf0'; + $rtfText .= '\f0'; + + if ($styleFont->getBold()) { + $rtfText .= '\b0'; + } + if ($styleFont->getItalic()) { + $rtfText .= '\i0'; + } + if ($styleFont->getSize()) { + $rtfText .= '\fs' . (PhpWord::DEFAULT_FONT_SIZE * 2); + } + } + + if (!$this->withoutP) { + $rtfText .= '\par' . PHP_EOL; + } + return $rtfText; + } +} diff --git a/src/PhpWord/Writer/RTF/Element/TextBreak.php b/src/PhpWord/Writer/RTF/Element/TextBreak.php new file mode 100644 index 00000000..91ae706d --- /dev/null +++ b/src/PhpWord/Writer/RTF/Element/TextBreak.php @@ -0,0 +1,30 @@ +parentWriter->setLastParagraphStyle(); + + return '\par' . PHP_EOL; + } +} diff --git a/src/PhpWord/Writer/RTF/Element/TextRun.php b/src/PhpWord/Writer/RTF/Element/TextRun.php new file mode 100644 index 00000000..86c30f4b --- /dev/null +++ b/src/PhpWord/Writer/RTF/Element/TextRun.php @@ -0,0 +1,45 @@ +element->getElements(); + if (count($elements) > 0) { + $rtfText .= '\pard\nowidctlpar' . PHP_EOL; + foreach ($elements as $element) { + if ($element instanceof TextElement) { + $elementWriter = new Element($this->parentWriter, $element, true); + $rtfText .= '{'; + $rtfText .= $elementWriter->write(); + $rtfText .= '}' . PHP_EOL; + } + } + $rtfText .= '\par' . PHP_EOL; + } + + return $rtfText; + } +} diff --git a/src/PhpWord/Writer/RTF/Element/Title.php b/src/PhpWord/Writer/RTF/Element/Title.php new file mode 100644 index 00000000..61a40032 --- /dev/null +++ b/src/PhpWord/Writer/RTF/Element/Title.php @@ -0,0 +1,33 @@ +element->getText(); + $rtfText .= '\par' . PHP_EOL; + + return $rtfText; + } +}