From b91e3209fa62d3d5b72cb8df75acdbf64403868b Mon Sep 17 00:00:00 2001 From: Ivan Lanin Date: Sun, 18 May 2014 11:13:38 +0700 Subject: [PATCH] Refactor ODT writer to give enable some additional features --- .scrutinizer.yml | 5 +- CHANGELOG.md | 2 + phpunit.xml.dist | 1 - samples/resources/Sample_11_ReadWord2007.docx | Bin 69796 -> 70869 bytes src/PhpWord/PhpWord.php | 61 +++--- src/PhpWord/Reader/Word2007/AbstractPart.php | 8 +- src/PhpWord/Style.php | 76 ++++--- src/PhpWord/Style/AbstractStyle.php | 37 +++- src/PhpWord/Writer/HTML/Element/Table.php | 5 +- src/PhpWord/Writer/ODText.php | 1 + src/PhpWord/Writer/ODText/Element/Table.php | 1 + src/PhpWord/Writer/ODText/Element/Title.php | 42 ++++ src/PhpWord/Writer/ODText/Part/Content.php | 193 ++++++++++-------- src/PhpWord/Writer/ODText/Part/Styles.php | 134 ++---------- .../Writer/ODText/Style/DefaultStyle.php | 72 +++++++ src/PhpWord/Writer/ODText/Style/Font.php | 36 ++-- .../Writer/ODText/Style/MasterStyle.php | 43 ++++ .../Writer/ODText/Style/NamedStyle.php | 50 +++++ .../Writer/ODText/Style/PageLayoutStyle.php | 78 +++++++ src/PhpWord/Writer/ODText/Style/Paragraph.php | 19 +- .../Writer/Word2007/Part/AbstractPart.php | 10 +- .../Tests/Writer/ODText/ElementTest.php | 2 +- 22 files changed, 576 insertions(+), 300 deletions(-) create mode 100644 src/PhpWord/Writer/ODText/Element/Title.php create mode 100644 src/PhpWord/Writer/ODText/Style/DefaultStyle.php create mode 100644 src/PhpWord/Writer/ODText/Style/MasterStyle.php create mode 100644 src/PhpWord/Writer/ODText/Style/NamedStyle.php create mode 100644 src/PhpWord/Writer/ODText/Style/PageLayoutStyle.php diff --git a/.scrutinizer.yml b/.scrutinizer.yml index a35530a9..6f982d8e 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -16,8 +16,9 @@ tools: external_code_coverage: enabled: true timeout: 900 - php_sim: - min_mass: 40 + php_cpd: true + # php_sim: # Temporarily disabled to allow focus on things other than duplicates + # min_mass: 40 php_pdepend: true php_analyzer: true sensiolabs_security_checker: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f687b9d..30551204 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3; new r - RTF: Ability to add links and page breaks in RTF - @ivanlanin GH-196 - ListItemRun: Remove fontStyle parameter because ListItemRun is inherited from TextRun and TextRun doesn't have fontStyle - @ivanlanin - Config: Ability to use a config file to store various common settings - @ivanlanin GH-200 +- ODT: Enable inline font style in TextRun - @ivanlanin +- ODT: Enable underline, strike/doublestrike, smallcaps/allcaps, superscript/subscript font style - @ivanlanin ### Bugfixes diff --git a/phpunit.xml.dist b/phpunit.xml.dist index fb511bd2..015dd2ed 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -18,7 +18,6 @@ ./src ./src/PhpWord/Shared/PCLZip - ./src/PhpWord/Shared/Spyc diff --git a/samples/resources/Sample_11_ReadWord2007.docx b/samples/resources/Sample_11_ReadWord2007.docx index aefe9f485ea617defd77ba8129edd70dd2fbb789..a457c7a68c8972a1020df0f8c457218bbcb571fa 100644 GIT binary patch delta 18248 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

R%r)mo;{!sXNO3~le#Cy-5aG?H;4U+-VT-_op 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 H4-5MXGRNxr delta 17145 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 diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index a3abb869..c54faa36 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -240,10 +240,11 @@ class PhpWord * Set default paragraph style definition to styles.xml * * @param array $styles Paragraph style definition + * @return \PhpOffice\PhpWord\Style\Paragraph */ public function setDefaultParagraphStyle($styles) { - Style::setDefaultParagraphStyle($styles); + return Style::setDefaultParagraphStyle($styles); } /** @@ -251,10 +252,11 @@ class PhpWord * * @param string $styleName * @param array $styles + * @return \PhpOffice\PhpWord\Style\Paragraph */ public function addParagraphStyle($styleName, $styles) { - Style::addParagraphStyle($styleName, $styles); + return Style::addParagraphStyle($styleName, $styles); } /** @@ -263,10 +265,11 @@ class PhpWord * @param string $styleName * @param mixed $fontStyle * @param mixed $paragraphStyle + * @return \PhpOffice\PhpWord\Style\Font */ public function addFontStyle($styleName, $fontStyle, $paragraphStyle = null) { - Style::addFontStyle($styleName, $fontStyle, $paragraphStyle); + return Style::addFontStyle($styleName, $fontStyle, $paragraphStyle); } /** @@ -275,10 +278,35 @@ class PhpWord * @param string $styleName * @param mixed $styleTable * @param mixed $styleFirstRow + * @return \PhpOffice\PhpWord\Style\Table */ public function addTableStyle($styleName, $styleTable, $styleFirstRow = null) { - Style::addTableStyle($styleName, $styleTable, $styleFirstRow); + return Style::addTableStyle($styleName, $styleTable, $styleFirstRow); + } + + /** + * Adds a numbering style + * + * @param string $styleName + * @param mixed $styles + * @return \PhpOffice\PhpWord\Style\Numbering + */ + public function addNumberingStyle($styleName, $styles) + { + return Style::addNumberingStyle($styleName, $styles); + } + + /** + * Adds a hyperlink style to styles.xml + * + * @param string $styleName + * @param mixed $styles + * @return \PhpOffice\PhpWord\Style\Font + */ + public function addLinkStyle($styleName, $styles) + { + return Style::addLinkStyle($styleName, $styles); } /** @@ -287,32 +315,11 @@ class PhpWord * @param int $depth * @param mixed $fontStyle * @param mixed $paragraphStyle + * @return \PhpOffice\PhpWord\Style\Font */ public function addTitleStyle($depth, $fontStyle, $paragraphStyle = null) { - Style::addTitleStyle($depth, $fontStyle, $paragraphStyle); - } - - /** - * Adds a hyperlink style to styles.xml - * - * @param string $styleName - * @param mixed $styles - */ - public function addLinkStyle($styleName, $styles) - { - Style::addLinkStyle($styleName, $styles); - } - - /** - * Adds a numbering style - * - * @param string $styleName - * @param mixed $styles - */ - public function addNumberingStyle($styleName, $styles) - { - Style::addNumberingStyle($styleName, $styles); + return Style::addTitleStyle($depth, $fontStyle, $paragraphStyle); } /** diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 34088b17..b4b5d829 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -222,10 +222,11 @@ abstract class AbstractPart $style = array(); $mapping = array( 'w:rStyle' => 'styleName', - 'w:b' => 'bold', 'w:i' => 'italic', 'w:color' => 'color', - 'w:strike' => 'strikethrough', 'w:u' => 'underline', + 'w:b' => 'bold', 'w:i' => 'italic', 'w:color' => 'color', 'w:u' => 'underline', + 'w:strike' => 'strikethrough', 'w:dstrike' => 'doubleStrikethrough', 'w:highlight' => 'fgColor', 'w:sz' => 'size', 'w:rFonts' => 'name', 'w:vertAlign' => 'superScript', + 'w:smallCaps' => 'smallCaps', 'w:caps' => 'allCaps', ); $nodes = $xmlReader->getElements('w:rPr/*', $domNode); @@ -244,6 +245,9 @@ abstract class AbstractPart case 'w:b': case 'w:i': case 'w:strike': + case 'w:dstrike': + case 'w:smallCaps': + case 'w:caps': $style[$property] = true; break; diff --git a/src/PhpWord/Style.php b/src/PhpWord/Style.php index ef3310d7..d56c73fe 100644 --- a/src/PhpWord/Style.php +++ b/src/PhpWord/Style.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWord; +use PhpOffice\PhpWord\Style\AbstractStyle; use PhpOffice\PhpWord\Style\Font; use PhpOffice\PhpWord\Style\Numbering; use PhpOffice\PhpWord\Style\Paragraph; @@ -39,10 +40,11 @@ class Style * * @param string $styleName * @param array $styles + * @return \PhpOffice\PhpWord\Style\Paragraph */ public static function addParagraphStyle($styleName, $styles) { - self::setStyleValues($styleName, new Paragraph(), $styles); + return self::setStyleValues($styleName, new Paragraph(), $styles); } /** @@ -51,10 +53,11 @@ class Style * @param string $styleName * @param array $fontStyle * @param array $paragraphStyle + * @return \PhpOffice\PhpWord\Style\Font */ public static function addFontStyle($styleName, $fontStyle, $paragraphStyle = null) { - self::setStyleValues($styleName, new Font('text', $paragraphStyle), $fontStyle); + return self::setStyleValues($styleName, new Font('text', $paragraphStyle), $fontStyle); } /** @@ -62,22 +65,24 @@ class Style * * @param string $styleName * @param array $styles + * @return \PhpOffice\PhpWord\Style\Font */ public static function addLinkStyle($styleName, $styles) { - self::setStyleValues($styleName, new Font('link'), $styles); + return self::setStyleValues($styleName, new Font('link'), $styles); } /** - * Add table style + * Add numbering style * * @param string $styleName - * @param array $styleTable - * @param array|null $styleFirstRow + * @param array $styleValues + * @return \PhpOffice\PhpWord\Style\Numbering + * @since 0.10.0 */ - public static function addTableStyle($styleName, $styleTable, $styleFirstRow = null) + public static function addNumberingStyle($styleName, $styleValues) { - self::setStyleValues($styleName, new Table($styleTable, $styleFirstRow), null); + return self::setStyleValues($styleName, new Numbering(), $styleValues); } /** @@ -86,29 +91,30 @@ class Style * @param int $depth * @param array $fontStyle * @param array $paragraphStyle + * @return \PhpOffice\PhpWord\Style\Font */ public static function addTitleStyle($depth, $fontStyle, $paragraphStyle = null) { - self::setStyleValues("Heading_{$depth}", new Font('title', $paragraphStyle), $fontStyle); + return self::setStyleValues("Heading_{$depth}", new Font('title', $paragraphStyle), $fontStyle); } /** - * Add numbering style + * Add table style * * @param string $styleName - * @param array $styleValues - * @return Numbering - * @since 0.10.0 + * @param array $styleTable + * @param array|null $styleFirstRow + * @return \PhpOffice\PhpWord\Style\Table */ - public static function addNumberingStyle($styleName, $styleValues) + public static function addTableStyle($styleName, $styleTable, $styleFirstRow = null) { - self::setStyleValues($styleName, new Numbering(), $styleValues); + return self::setStyleValues($styleName, new Table($styleTable, $styleFirstRow), null); } /** * Count styles * - * @return integer + * @return int * @since 0.10.0 */ public static function countStyles() @@ -129,16 +135,17 @@ class Style * Set default paragraph style * * @param array $styles Paragraph style definition + * @return \PhpOffice\PhpWord\Style\Paragraph */ public static function setDefaultParagraphStyle($styles) { - self::addParagraphStyle('Normal', $styles); + return self::addParagraphStyle('Normal', $styles); } /** * Get all styles * - * @return array + * @return \PhpOffice\PhpWord\Style\AbstractStyle[] */ public static function getStyles() { @@ -149,7 +156,7 @@ class Style * Get style by name * * @param string $styleName - * @return Paragraph|Font|Table|Numbering|null + * @return \PhpOffice\PhpWord\Style\AbstractStyle Paragraph|Font|Table|Numbering */ public static function getStyle($styleName) { @@ -163,21 +170,30 @@ class Style /** * Set style values and put it to static style collection * - * @param string $styleName - * @param Paragraph|Font|Table|Numbering $styleObject - * @param array|null $styleValues + * The $styleValues could be an array or object + * + * @param string $name + * @param \PhpOffice\PhpWord\Style\AbstractStyle $style + * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $value + * @return \PhpOffice\PhpWord\Style\AbstractStyle */ - private static function setStyleValues($styleName, $styleObject, $styleValues = null) + private static function setStyleValues($name, $style, $value = null) { - if (!array_key_exists($styleName, self::$styles)) { - if (!is_null($styleValues) && is_array($styleValues)) { - foreach ($styleValues as $key => $value) { - $styleObject->setStyleValue($key, $value); + if (!array_key_exists($name, self::$styles)) { + if ($value !== null) { + if (is_array($value)) { + $style->setStyleByArray($value); + } elseif ($value instanceof AbstractStyle) { + if (get_class($style) == get_class($value)) { + $style = $value; + } } } - $styleObject->setStyleName($styleName); - $styleObject->setIndex(self::countStyles() + 1); // One based index - self::$styles[$styleName] = $styleObject; + $style->setStyleName($name); + $style->setIndex(self::countStyles() + 1); // One based index + self::$styles[$name] = $style; } + + return self::getStyle($name); } } diff --git a/src/PhpWord/Style/AbstractStyle.php b/src/PhpWord/Style/AbstractStyle.php index 0ac71ab2..c9e26887 100644 --- a/src/PhpWord/Style/AbstractStyle.php +++ b/src/PhpWord/Style/AbstractStyle.php @@ -49,6 +49,14 @@ abstract class AbstractStyle */ protected $aliases = array(); + /** + * Is this an automatic style? (Used primarily in OpenDocument driver) + * + * @var bool + * @since 0.11.0 + */ + private $isAuto = false; + /** * Get style name * @@ -95,6 +103,29 @@ abstract class AbstractStyle return $this; } + /** + * Get is automatic style flag + * + * @return bool + */ + public function isAuto() + { + return $this->isAuto; + } + + /** + * Set is automatic style flag + * + * @param bool $value + * @return self + */ + public function setAuto($value = true) + { + $this->isAuto = $this->setBoolVal($value, $this->isAuto); + + return $this; + } + /** * Set style value template method * @@ -123,12 +154,12 @@ abstract class AbstractStyle /** * Set style by using associative array * - * @param array $styles + * @param array $values * @return self */ - public function setStyleByArray($styles = array()) + public function setStyleByArray($values = array()) { - foreach ($styles as $key => $value) { + foreach ($values as $key => $value) { $this->setStyleValue($key, $value); } diff --git a/src/PhpWord/Writer/HTML/Element/Table.php b/src/PhpWord/Writer/HTML/Element/Table.php index fc5f0d30..c8813a67 100644 --- a/src/PhpWord/Writer/HTML/Element/Table.php +++ b/src/PhpWord/Writer/HTML/Element/Table.php @@ -41,9 +41,10 @@ class Table extends AbstractElement if ($rowCount > 0) { $content .= '' . PHP_EOL; foreach ($rows as $row) { - // $height = $row->getHeight(); + /** @var $row \PhpOffice\PhpWord\Element\Row Type hint */ $rowStyle = $row->getStyle(); - $tblHeader = $rowStyle->getTblHeader(); + // $height = $row->getHeight(); + $tblHeader = $rowStyle->isTblHeader(); $content .= '' . PHP_EOL; foreach ($row->getCells() as $cell) { $writer = new Container($this->parentWriter, $cell); diff --git a/src/PhpWord/Writer/ODText.php b/src/PhpWord/Writer/ODText.php index dc2c5d2c..fbe51c5d 100644 --- a/src/PhpWord/Writer/ODText.php +++ b/src/PhpWord/Writer/ODText.php @@ -49,6 +49,7 @@ class ODText extends AbstractWriter implements WriterInterface foreach (array_keys($this->parts) as $partName) { $partClass = get_class($this) . '\\Part\\' . $partName; if (class_exists($partClass)) { + /** @var $partObject \PhpOffice\PhpWord\Writer\ODText\Part\AbstractPart Type hint */ $partObject = new $partClass(); $partObject->setParentWriter($this); $this->writerParts[strtolower($partName)] = $partObject; diff --git a/src/PhpWord/Writer/ODText/Element/Table.php b/src/PhpWord/Writer/ODText/Element/Table.php index 19e5b408..f26960b8 100644 --- a/src/PhpWord/Writer/ODText/Element/Table.php +++ b/src/PhpWord/Writer/ODText/Element/Table.php @@ -49,6 +49,7 @@ class Table extends AbstractElement foreach ($rows as $row) { $xmlWriter->startElement('table:table-row'); + /** @var $row \PhpOffice\PhpWord\Element\Row Type hint */ foreach ($row->getCells() as $cell) { $xmlWriter->startElement('table:table-cell'); $xmlWriter->writeAttribute('office:value-type', 'string'); diff --git a/src/PhpWord/Writer/ODText/Element/Title.php b/src/PhpWord/Writer/ODText/Element/Title.php new file mode 100644 index 00000000..9d062a7f --- /dev/null +++ b/src/PhpWord/Writer/ODText/Element/Title.php @@ -0,0 +1,42 @@ +getXmlWriter(); + $element = $this->getElement(); + if (!$element instanceof \PhpOffice\PhpWord\Element\Title) { + return; + } + + $xmlWriter->startElement('text:p'); + $xmlWriter->writeRaw($element->getText()); + $xmlWriter->endElement(); // text:p + } +} diff --git a/src/PhpWord/Writer/ODText/Part/Content.php b/src/PhpWord/Writer/ODText/Part/Content.php index f5ae1883..f63deba6 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -19,12 +19,13 @@ namespace PhpOffice\PhpWord\Writer\ODText\Part; use PhpOffice\PhpWord\Element\Table; use PhpOffice\PhpWord\Element\Text; +use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\Media; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Shared\XMLWriter; +use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Style\Font; use PhpOffice\PhpWord\Style\Paragraph; -use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Writer\ODText\Element\Container; /** @@ -39,8 +40,10 @@ class Content extends AbstractPart */ public function write() { - $phpWord = $this->getParentWriter()->getPhpWord(); $xmlWriter = $this->getXmlWriter(); + $phpWord = $this->getParentWriter()->getPhpWord(); + + $this->getAutoStyles($phpWord); $xmlWriter->startDocument('1.0', 'UTF-8'); $xmlWriter->startElement('office:document-content'); @@ -51,14 +54,20 @@ class Content extends AbstractPart $xmlWriter->writeAttribute('xmlns:field', 'urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0'); $xmlWriter->writeAttribute('xmlns:formx', 'urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0'); - $this->getAutomaticStyles($phpWord); $this->writeFontFaces($xmlWriter); // office:font-face-decls - $this->writeAutomaticStyles($xmlWriter, $phpWord); // office:automatic-styles + // Automatic styles + $xmlWriter->startElement('office:automatic-styles'); + $this->writeTextAutoStyles($xmlWriter); + $this->writeImageAutoStyles($xmlWriter); + $this->writeTableAutoStyles($xmlWriter, $phpWord); + $xmlWriter->endElement(); // office:automatic-styles + + // Body $xmlWriter->startElement('office:body'); $xmlWriter->startElement('office:text'); - // text:sequence-decls + // Sequence declarations $sequences = array('Illustration', 'Table', 'Text', 'Drawing'); $xmlWriter->startElement('text:sequence-decls'); foreach ($sequences as $sequence) { @@ -69,18 +78,18 @@ class Content extends AbstractPart } $xmlWriter->endElement(); // text:sequence-decl + // Sections $sections = $phpWord->getSections(); - $sectionCount = count($sections); - if ($sectionCount > 0) { - foreach ($sections as $section) { - // $xmlWriter->startElement('text:section'); - $containerWriter = new Container($xmlWriter, $section); - $containerWriter->write(); - // $xmlWriter->endElement(); // text:section - } + foreach ($sections as $section) { + // $xmlWriter->startElement('text:section'); + $containerWriter = new Container($xmlWriter, $section); + $containerWriter->write(); + // $xmlWriter->endElement(); // text:section } + $xmlWriter->endElement(); // office:text $xmlWriter->endElement(); // office:body + $xmlWriter->endElement(); // office:document-content return $xmlWriter->getData(); @@ -89,22 +98,16 @@ class Content extends AbstractPart /** * Write automatic styles */ - private function writeAutomaticStyles(XMLWriter $xmlWriter, PhpWord $phpWord) + private function writeTextAutoStyles(XMLWriter $xmlWriter) { - $xmlWriter->startElement('office:automatic-styles'); - - // Font and paragraph $styles = Style::getStyles(); $paragraphStyleCount = 0; if (count($styles) > 0) { - foreach ($styles as $styleName => $style) { - if (preg_match('#^T[0-9]+$#', $styleName) != 0 - || preg_match('#^P[0-9]+$#', $styleName) != 0 - ) { + foreach ($styles as $style) { + if ($style->isAuto() === true) { $styleClass = str_replace('\\Style\\', '\\Writer\\ODText\\Style\\', get_class($style)); if (class_exists($styleClass)) { $styleWriter = new $styleClass($xmlWriter, $style); - $styleWriter->setIsAuto(true); $styleWriter->write(); } if ($style instanceof Paragraph) { @@ -115,13 +118,18 @@ class Content extends AbstractPart if ($paragraphStyleCount == 0) { $style = new Paragraph(); $style->setStyleName('P1'); + $style->setAuto(); $styleWriter = new \PhpOffice\PhpWord\Writer\ODText\Style\Paragraph($xmlWriter, $style); - $styleWriter->setIsAuto(true); $styleWriter->write(); } } + } - // Images + /** + * Write image automatic styles + */ + private function writeImageAutoStyles(XMLWriter $xmlWriter) + { $images = Media::getElements('section'); foreach ($images as $image) { if ($image['type'] == 'image') { @@ -132,75 +140,94 @@ class Content extends AbstractPart $xmlWriter->startElement('style:graphic-properties'); $xmlWriter->writeAttribute('style:vertical-pos', 'top'); $xmlWriter->writeAttribute('style:vertical-rel', 'baseline'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); + $xmlWriter->endElement(); // style:graphic-properties + $xmlWriter->endElement(); // style:style } } - - // Tables - $sections = $phpWord->getSections(); - $sectionCount = count($sections); - if ($sectionCount > 0) { - $sectionId = 0; - foreach ($sections as $section) { - $sectionId++; - $elements = $section->getElements(); - foreach ($elements as $element) { - if ($elements instanceof Table) { - $xmlWriter->startElement('style:style'); - $xmlWriter->writeAttribute('style:name', $element->getElementId()); - $xmlWriter->writeAttribute('style:family', 'table'); - $xmlWriter->startElement('style:table-properties'); - //$xmlWriter->writeAttribute('style:width', 'table'); - $xmlWriter->writeAttribute('style:rel-width', 100); - $xmlWriter->writeAttribute('table:align', 'center'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - } - } - } - } - - $xmlWriter->endElement(); // office:automatic-styles } /** - * Set automatic styles + * Write table automatic styles */ - private function getAutomaticStyles(PhpWord $phpWord) + private function writeTableAutoStyles(XMLWriter $xmlWriter, PhpWord $phpWord) { $sections = $phpWord->getSections(); - $sectionCount = count($sections); - if ($sectionCount > 0) { - $paragraphStyleCount = 0; - $fontStyleCount = 0; - foreach ($sections as $section) { - $elements = $section->getElements(); - foreach ($elements as $element) { - if ($element instanceof Text) { - $fontStyle = $element->getFontStyle(); - $paragraphStyle = $element->getParagraphStyle(); - - // Font - if ($fontStyle instanceof Font) { - $fontStyleCount++; - $arrStyle = array( - 'color' => $fontStyle->getColor(), - 'name' => $fontStyle->getName() - ); - $phpWord->addFontStyle('T' . $fontStyleCount, $arrStyle); - $element->setFontStyle('T' . $fontStyleCount); - - // Paragraph - } elseif ($paragraphStyle instanceof Paragraph) { - $paragraphStyleCount++; - - $phpWord->addParagraphStyle('P' . $paragraphStyleCount, array()); - $element->setParagraphStyle('P' . $paragraphStyleCount); - } - } + foreach ($sections as $section) { + $elements = $section->getElements(); + foreach ($elements as $element) { + if ($elements instanceof Table) { + $xmlWriter->startElement('style:style'); + $xmlWriter->writeAttribute('style:name', $element->getElementId()); + $xmlWriter->writeAttribute('style:family', 'table'); + $xmlWriter->startElement('style:table-properties'); + //$xmlWriter->writeAttribute('style:width', 'table'); + $xmlWriter->writeAttribute('style:rel-width', 100); + $xmlWriter->writeAttribute('table:align', 'center'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); } } } } + + /** + * Get automatic styles + */ + private function getAutoStyles(PhpWord $phpWord) + { + $sections = $phpWord->getSections(); + $paragraphStyleCount = 0; + $fontStyleCount = 0; + foreach ($sections as $section) { + $this->getContainerStyle($section, $paragraphStyleCount, $fontStyleCount); + } + } + + /** + * Get all styles of each elements in container recursively + * + * @param \PhpOffice\PhpWord\Element\AbstractContainer $container + * @param int $paragraphStyleCount + * @param int $fontStyleCount + */ + private function getContainerStyle($container, &$paragraphStyleCount, &$fontStyleCount) + { + $elements = $container->getElements(); + foreach ($elements as $element) { + if ($element instanceof TextRun) { + $this->getContainerStyle($element, $paragraphStyleCount, $fontStyleCount); + } elseif ($element instanceof Text) { + $this->getElementStyle($element, $paragraphStyleCount, $fontStyleCount); + } + } + } + + /** + * Get style of individual element + * + * @param \PhpOffice\PhpWord\Element\Text $element + * @param int $paragraphStyleCount + * @param int $fontStyleCount + */ + private function getElementStyle(&$element, &$paragraphStyleCount, &$fontStyleCount) + { + $fontStyle = $element->getFontStyle(); + $paragraphStyle = $element->getParagraphStyle(); + $phpWord = $this->getParentWriter()->getPhpWord(); + + // Font + if ($fontStyle instanceof Font) { + $fontStyleCount++; + $style = $phpWord->addFontStyle("T{$fontStyleCount}", $fontStyle); + $style->setAuto(); + $element->setFontStyle("T{$fontStyleCount}"); + + // Paragraph + } elseif ($paragraphStyle instanceof Paragraph) { + $paragraphStyleCount++; + $style = $phpWord->addParagraphStyle("P{$paragraphStyleCount}", array()); + $style->setAuto(); + $element->setParagraphStyle("P{$paragraphStyleCount}"); + } + } } diff --git a/src/PhpWord/Writer/ODText/Part/Styles.php b/src/PhpWord/Writer/ODText/Part/Styles.php index 0c39607c..a226f7ff 100644 --- a/src/PhpWord/Writer/ODText/Part/Styles.php +++ b/src/PhpWord/Writer/ODText/Part/Styles.php @@ -17,8 +17,7 @@ namespace PhpOffice\PhpWord\Writer\ODText\Part; -use PhpOffice\PhpWord\Settings; -use PhpOffice\PhpWord\Style; +use PhpOffice\PhpWord\Shared\XMLWriter; /** * ODText styloes part writer: styles.xml @@ -36,128 +35,39 @@ class Styles extends AbstractPart // XML header $xmlWriter->startDocument('1.0', 'UTF-8'); - - // Styles:Styles $xmlWriter->startElement('office:document-styles'); $this->writeCommonRootAttributes($xmlWriter); - // office:font-face-decls + // Font declarations $this->writeFontFaces($xmlWriter); - // office:styles + // Office styles $xmlWriter->startElement('office:styles'); - - // style:default-style - $xmlWriter->startElement('style:default-style'); - $xmlWriter->writeAttribute('style:family', 'paragraph'); - - // style:paragraph-properties - $xmlWriter->startElement('style:paragraph-properties'); - $xmlWriter->writeAttribute('fo:hyphenation-ladder-count', 'no-limit'); - $xmlWriter->writeAttribute('style:text-autospace', 'ideograph-alpha'); - $xmlWriter->writeAttribute('style:punctuation-wrap', 'hanging'); - $xmlWriter->writeAttribute('style:line-break', 'strict'); - $xmlWriter->writeAttribute('style:tab-stop-distance', '1.249cm'); - $xmlWriter->writeAttribute('style:writing-mode', 'page'); + $this->writePart($xmlWriter, 'Default'); + $this->writePart($xmlWriter, 'Named'); $xmlWriter->endElement(); - // style:text-properties - $xmlWriter->startElement('style:text-properties'); - $xmlWriter->writeAttribute('style:use-window-font-color', 'true'); - $xmlWriter->writeAttribute('style:font-name', Settings::getDefaultFontName()); - $xmlWriter->writeAttribute('fo:font-size', Settings::getDefaultFontSize() . 'pt'); - $xmlWriter->writeAttribute('fo:language', 'fr'); - $xmlWriter->writeAttribute('fo:country', 'FR'); - $xmlWriter->writeAttribute('style:letter-kerning', 'true'); - $xmlWriter->writeAttribute('style:font-name-asian', Settings::getDefaultFontName() . '2'); - $xmlWriter->writeAttribute('style:font-size-asian', Settings::getDefaultFontSize() . 'pt'); - $xmlWriter->writeAttribute('style:language-asian', 'zh'); - $xmlWriter->writeAttribute('style:country-asian', 'CN'); - $xmlWriter->writeAttribute('style:font-name-complex', Settings::getDefaultFontName() . '2'); - $xmlWriter->writeAttribute('style:font-size-complex', Settings::getDefaultFontSize() . 'pt'); - $xmlWriter->writeAttribute('style:language-complex', 'hi'); - $xmlWriter->writeAttribute('style:country-complex', 'IN'); - $xmlWriter->writeAttribute('fo:hyphenate', 'false'); - $xmlWriter->writeAttribute('fo:hyphenation-remain-char-count', '2'); - $xmlWriter->writeAttribute('fo:hyphenation-push-char-count', '2'); - $xmlWriter->endElement(); - - $xmlWriter->endElement(); - - // Write Style Definitions - $styles = Style::getStyles(); - if (count($styles) > 0) { - foreach ($styles as $styleName => $style) { - if (preg_match('#^T[0-9]+$#', $styleName) == 0 - && preg_match('#^P[0-9]+$#', $styleName) == 0 - ) { - $styleClass = str_replace('\\Style\\', '\\Writer\\ODText\\Style\\', get_class($style)); - if (class_exists($styleClass)) { - $styleWriter = new $styleClass($xmlWriter, $style); - $styleWriter->write(); - } - } - } - } - $xmlWriter->endElement(); - - // office:automatic-styles + // Automatic styles $xmlWriter->startElement('office:automatic-styles'); - // style:page-layout - $xmlWriter->startElement('style:page-layout'); - $xmlWriter->writeAttribute('style:name', 'Mpm1'); - // style:page-layout-properties - $xmlWriter->startElement('style:page-layout-properties'); - $xmlWriter->writeAttribute('fo:page-width', "21.001cm"); - $xmlWriter->writeAttribute('fo:page-height', '29.7cm'); - $xmlWriter->writeAttribute('style:num-format', '1'); - $xmlWriter->writeAttribute('style:print-orientation', 'portrait'); - $xmlWriter->writeAttribute('fo:margin-top', '2.501cm'); - $xmlWriter->writeAttribute('fo:margin-bottom', '2cm'); - $xmlWriter->writeAttribute('fo:margin-left', '2.501cm'); - $xmlWriter->writeAttribute('fo:margin-right', '2.501cm'); - $xmlWriter->writeAttribute('style:writing-mode', 'lr-tb'); - $xmlWriter->writeAttribute('style:layout-grid-color', '#c0c0c0'); - $xmlWriter->writeAttribute('style:layout-grid-lines', '25199'); - $xmlWriter->writeAttribute('style:layout-grid-base-height', '0.423cm'); - $xmlWriter->writeAttribute('style:layout-grid-ruby-height', '0cm'); - $xmlWriter->writeAttribute('style:layout-grid-mode', 'none'); - $xmlWriter->writeAttribute('style:layout-grid-ruby-below', 'false'); - $xmlWriter->writeAttribute('style:layout-grid-print', 'false'); - $xmlWriter->writeAttribute('style:layout-grid-display', 'false'); - $xmlWriter->writeAttribute('style:layout-grid-base-width', '0.37cm'); - $xmlWriter->writeAttribute('style:layout-grid-snap-to', 'true'); - $xmlWriter->writeAttribute('style:footnote-max-height', '0cm'); - //style:footnote-sep - $xmlWriter->startElement('style:footnote-sep'); - $xmlWriter->writeAttribute('style:width', '0.018cm'); - $xmlWriter->writeAttribute('style:line-style', 'solid'); - $xmlWriter->writeAttribute('style:adjustment', 'left'); - $xmlWriter->writeAttribute('style:rel-width', '25%'); - $xmlWriter->writeAttribute('style:color', '#000000'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - // style:header-style - $xmlWriter->startElement('style:header-style'); - $xmlWriter->endElement(); - // style:footer-style - $xmlWriter->startElement('style:footer-style'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); + $this->writePart($xmlWriter, 'PageLayout'); + $this->writePart($xmlWriter, 'Master'); $xmlWriter->endElement(); - // office:master-styles - $xmlWriter->startElement('office:master-styles'); - // style:master-page - $xmlWriter->startElement('style:master-page'); - $xmlWriter->writeAttribute('style:name', 'Standard'); - $xmlWriter->writeAttribute('style:page-layout-name', 'Mpm1'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); + $xmlWriter->endElement(); // office:document-styles - $xmlWriter->endElement(); - - // Return return $xmlWriter->getData(); } + + /** + * Write style part + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param string $subStyle + */ + private function writePart(XMLWriter $xmlWriter, $subStyle) + { + $writerClass = "PhpOffice\\PhpWord\\Writer\\ODText\\Style\\{$subStyle}Style"; + $styleWriter = new $writerClass($xmlWriter); + $styleWriter->write(); + } } diff --git a/src/PhpWord/Writer/ODText/Style/DefaultStyle.php b/src/PhpWord/Writer/ODText/Style/DefaultStyle.php new file mode 100644 index 00000000..d77157fa --- /dev/null +++ b/src/PhpWord/Writer/ODText/Style/DefaultStyle.php @@ -0,0 +1,72 @@ +getXmlWriter(); + + $xmlWriter->startElement('style:default-style'); + $xmlWriter->writeAttribute('style:family', 'paragraph'); + + // Paragraph + $xmlWriter->startElement('style:paragraph-properties'); + $xmlWriter->writeAttribute('fo:hyphenation-ladder-count', 'no-limit'); + $xmlWriter->writeAttribute('style:text-autospace', 'ideograph-alpha'); + $xmlWriter->writeAttribute('style:punctuation-wrap', 'hanging'); + $xmlWriter->writeAttribute('style:line-break', 'strict'); + $xmlWriter->writeAttribute('style:tab-stop-distance', '1.249cm'); + $xmlWriter->writeAttribute('style:writing-mode', 'page'); + $xmlWriter->endElement(); // style:paragraph-properties + + // Font + $xmlWriter->startElement('style:text-properties'); + $xmlWriter->writeAttribute('style:use-window-font-color', 'true'); + $xmlWriter->writeAttribute('style:font-name', Settings::getDefaultFontName()); + $xmlWriter->writeAttribute('fo:font-size', Settings::getDefaultFontSize() . 'pt'); + $xmlWriter->writeAttribute('fo:language', 'fr'); + $xmlWriter->writeAttribute('fo:country', 'FR'); + $xmlWriter->writeAttribute('style:letter-kerning', 'true'); + $xmlWriter->writeAttribute('style:font-name-asian', Settings::getDefaultFontName() . '2'); + $xmlWriter->writeAttribute('style:font-size-asian', Settings::getDefaultFontSize() . 'pt'); + $xmlWriter->writeAttribute('style:language-asian', 'zh'); + $xmlWriter->writeAttribute('style:country-asian', 'CN'); + $xmlWriter->writeAttribute('style:font-name-complex', Settings::getDefaultFontName() . '2'); + $xmlWriter->writeAttribute('style:font-size-complex', Settings::getDefaultFontSize() . 'pt'); + $xmlWriter->writeAttribute('style:language-complex', 'hi'); + $xmlWriter->writeAttribute('style:country-complex', 'IN'); + $xmlWriter->writeAttribute('fo:hyphenate', 'false'); + $xmlWriter->writeAttribute('fo:hyphenation-remain-char-count', '2'); + $xmlWriter->writeAttribute('fo:hyphenation-push-char-count', '2'); + $xmlWriter->endElement(); // style:text-properties + + $xmlWriter->endElement(); // style:default-style + } +} diff --git a/src/PhpWord/Writer/ODText/Style/Font.php b/src/PhpWord/Writer/ODText/Style/Font.php index 148c8dbc..acab0ee5 100644 --- a/src/PhpWord/Writer/ODText/Style/Font.php +++ b/src/PhpWord/Writer/ODText/Style/Font.php @@ -24,11 +24,6 @@ namespace PhpOffice\PhpWord\Writer\ODText\Style; */ class Font extends AbstractStyle { - /** - * Is automatic style - */ - private $isAuto = false; - /** * Write style */ @@ -67,17 +62,28 @@ class Font extends AbstractStyle $xmlWriter->writeAttributeIf($style->isItalic(), 'style:font-style-asian', 'italic'); $xmlWriter->writeAttributeIf($style->isItalic(), 'style:font-style-complex', 'italic'); + // Underline + // @todo Various mode of underline + $underline = $style->getUnderline(); + $xmlWriter->writeAttributeIf($underline != 'none', 'style:text-underline-style', 'solid'); + + // Strikethrough, double strikethrough + $xmlWriter->writeAttributeIf($style->isStrikethrough(), 'style:text-line-through-type', 'single'); + $xmlWriter->writeAttributeIf($style->isDoubleStrikethrough(), 'style:text-line-through-type', 'double'); + + // Small caps, all caps + $xmlWriter->writeAttributeIf($style->isSmallCaps(), 'fo:font-variant', 'small-caps'); + $xmlWriter->writeAttributeIf($style->isAllCaps(), 'fo:text-transform', 'uppercase'); + + // Superscript/subscript + $xmlWriter->writeAttributeIf($style->isSuperScript(), 'style:text-position', 'super'); + $xmlWriter->writeAttributeIf($style->isSubScript(), 'style:text-position', 'sub'); + + // @todo Foreground-Color + + // @todo Background color + $xmlWriter->endElement(); // style:text-properties $xmlWriter->endElement(); // style:style } - - /** - * Set is automatic style - * - * @param bool $value - */ - public function setIsAuto($value) - { - $this->isAuto = $value; - } } diff --git a/src/PhpWord/Writer/ODText/Style/MasterStyle.php b/src/PhpWord/Writer/ODText/Style/MasterStyle.php new file mode 100644 index 00000000..97d91a6a --- /dev/null +++ b/src/PhpWord/Writer/ODText/Style/MasterStyle.php @@ -0,0 +1,43 @@ +getXmlWriter(); + + $xmlWriter->startElement('office:master-styles'); + + $xmlWriter->startElement('style:master-page'); + $xmlWriter->writeAttribute('style:name', 'Standard'); + $xmlWriter->writeAttribute('style:page-layout-name', 'Mpm1'); + $xmlWriter->endElement(); // style:master-page + + $xmlWriter->endElement(); // office:master-styles + } +} diff --git a/src/PhpWord/Writer/ODText/Style/NamedStyle.php b/src/PhpWord/Writer/ODText/Style/NamedStyle.php new file mode 100644 index 00000000..e2b63162 --- /dev/null +++ b/src/PhpWord/Writer/ODText/Style/NamedStyle.php @@ -0,0 +1,50 @@ +getXmlWriter(); + + $styles = Style::getStyles(); + if (count($styles) > 0) { + foreach ($styles as $style) { + if ($style->isAuto() === false) { + $styleClass = str_replace('\\Style\\', '\\Writer\\ODText\\Style\\', get_class($style)); + if (class_exists($styleClass)) { + /** @var $styleWriter \PhpOffice\PhpWord\Writer\ODText\Style\AbstractStyle Type hint */ + $styleWriter = new $styleClass($xmlWriter, $style); + $styleWriter->write(); + } + } + } + } + } +} diff --git a/src/PhpWord/Writer/ODText/Style/PageLayoutStyle.php b/src/PhpWord/Writer/ODText/Style/PageLayoutStyle.php new file mode 100644 index 00000000..cfcb6c3b --- /dev/null +++ b/src/PhpWord/Writer/ODText/Style/PageLayoutStyle.php @@ -0,0 +1,78 @@ +getXmlWriter(); + + $xmlWriter->startElement('style:page-layout'); + $xmlWriter->writeAttribute('style:name', 'Mpm1'); + + $xmlWriter->startElement('style:page-layout-properties'); + $xmlWriter->writeAttribute('fo:page-width', "21.001cm"); + $xmlWriter->writeAttribute('fo:page-height', '29.7cm'); + $xmlWriter->writeAttribute('style:num-format', '1'); + $xmlWriter->writeAttribute('style:print-orientation', 'portrait'); + $xmlWriter->writeAttribute('fo:margin-top', '2.501cm'); + $xmlWriter->writeAttribute('fo:margin-bottom', '2cm'); + $xmlWriter->writeAttribute('fo:margin-left', '2.501cm'); + $xmlWriter->writeAttribute('fo:margin-right', '2.501cm'); + $xmlWriter->writeAttribute('style:writing-mode', 'lr-tb'); + $xmlWriter->writeAttribute('style:layout-grid-color', '#c0c0c0'); + $xmlWriter->writeAttribute('style:layout-grid-lines', '25199'); + $xmlWriter->writeAttribute('style:layout-grid-base-height', '0.423cm'); + $xmlWriter->writeAttribute('style:layout-grid-ruby-height', '0cm'); + $xmlWriter->writeAttribute('style:layout-grid-mode', 'none'); + $xmlWriter->writeAttribute('style:layout-grid-ruby-below', 'false'); + $xmlWriter->writeAttribute('style:layout-grid-print', 'false'); + $xmlWriter->writeAttribute('style:layout-grid-display', 'false'); + $xmlWriter->writeAttribute('style:layout-grid-base-width', '0.37cm'); + $xmlWriter->writeAttribute('style:layout-grid-snap-to', 'true'); + $xmlWriter->writeAttribute('style:footnote-max-height', '0cm'); + + $xmlWriter->startElement('style:footnote-sep'); + $xmlWriter->writeAttribute('style:width', '0.018cm'); + $xmlWriter->writeAttribute('style:line-style', 'solid'); + $xmlWriter->writeAttribute('style:adjustment', 'left'); + $xmlWriter->writeAttribute('style:rel-width', '25%'); + $xmlWriter->writeAttribute('style:color', '#000000'); + $xmlWriter->endElement(); //style:footnote-sep + + $xmlWriter->endElement(); // style:page-layout-properties + + + $xmlWriter->startElement('style:header-style'); + $xmlWriter->endElement(); // style:header-style + + $xmlWriter->startElement('style:footer-style'); + $xmlWriter->endElement(); // style:footer-style + + $xmlWriter->endElement(); // style:page-layout + } +} diff --git a/src/PhpWord/Writer/ODText/Style/Paragraph.php b/src/PhpWord/Writer/ODText/Style/Paragraph.php index e5f52cfe..133b8cdf 100644 --- a/src/PhpWord/Writer/ODText/Style/Paragraph.php +++ b/src/PhpWord/Writer/ODText/Style/Paragraph.php @@ -24,11 +24,6 @@ namespace PhpOffice\PhpWord\Writer\ODText\Style; */ class Paragraph extends AbstractStyle { - /** - * Is automatic style - */ - private $isAuto = false; - /** * Write style */ @@ -46,13 +41,13 @@ class Paragraph extends AbstractStyle $xmlWriter->startElement('style:style'); $xmlWriter->writeAttribute('style:name', $style->getStyleName()); $xmlWriter->writeAttribute('style:family', 'paragraph'); - if ($this->isAuto) { + if ($style->isAuto()) { $xmlWriter->writeAttribute('style:parent-style-name', 'Standard'); $xmlWriter->writeAttribute('style:master-page-name', 'Standard'); } $xmlWriter->startElement('style:paragraph-properties'); - if ($this->isAuto) { + if ($style->isAuto()) { $xmlWriter->writeAttribute('style:page-number', 'auto'); } else { $xmlWriter->writeAttribute('fo:margin-top', $marginTop . 'cm'); @@ -63,14 +58,4 @@ class Paragraph extends AbstractStyle $xmlWriter->endElement(); //style:style } - - /** - * Set is automatic style - * - * @param bool $value - */ - public function setIsAuto($value) - { - $this->isAuto = $value; - } } diff --git a/src/PhpWord/Writer/Word2007/Part/AbstractPart.php b/src/PhpWord/Writer/Word2007/Part/AbstractPart.php index b0454956..04444155 100644 --- a/src/PhpWord/Writer/Word2007/Part/AbstractPart.php +++ b/src/PhpWord/Writer/Word2007/Part/AbstractPart.php @@ -19,7 +19,7 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Part; use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\Shared\XMLWriter; -use PhpOffice\PhpWord\Writer\WriterInterface; +use PhpOffice\PhpWord\Writer\AbstractWriter; /** * Word2007 writer part abstract class @@ -29,16 +29,16 @@ abstract class AbstractPart /** * Parent writer * - * @var \PhpOffice\PhpWord\Writer\WriterInterface + * @var \PhpOffice\PhpWord\Writer\AbstractWriter */ protected $parentWriter; /** * Set parent writer * - * @param \PhpOffice\PhpWord\Writer\WriterInterface $writer + * @param \PhpOffice\PhpWord\Writer\AbstractWriter $writer */ - public function setParentWriter(WriterInterface $writer = null) + public function setParentWriter(AbstractWriter $writer = null) { $this->parentWriter = $writer; } @@ -46,7 +46,7 @@ abstract class AbstractPart /** * Get parent writer * - * @return \PhpOffice\PhpWord\Writer\WriterInterface + * @return \PhpOffice\PhpWord\Writer\AbstractWriter * @throws \PhpOffice\PhpWord\Exception\Exception */ public function getParentWriter() diff --git a/tests/PhpWord/Tests/Writer/ODText/ElementTest.php b/tests/PhpWord/Tests/Writer/ODText/ElementTest.php index c5fdfb41..fa9532d1 100644 --- a/tests/PhpWord/Tests/Writer/ODText/ElementTest.php +++ b/tests/PhpWord/Tests/Writer/ODText/ElementTest.php @@ -28,7 +28,7 @@ class ElementTest extends \PHPUnit_Framework_TestCase */ public function testUnmatchedElements() { - $elements = array('Image', 'Link', 'Table', 'Text'); + $elements = array('Image', 'Link', 'Table', 'Text', 'Title'); foreach ($elements as $element) { $objectClass = 'PhpOffice\\PhpWord\\Writer\\ODText\\Element\\' . $element; $xmlWriter = new XMLWriter();