diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index 16d16a47d0..2d7755d143 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -15,6 +15,22 @@ - Word2007 Reader/Writer: Permit book-fold printing by [@potofcoffee](https://github.com/potofcoffee) in [#2225](https://github.com/PHPOffice/PHPWord/pull/2225) & [#2470](https://github.com/PHPOffice/PHPWord/pull/2470) - Word2007 Writer : Add PageNumber to TOC by [@jet-desk](https://github.com/jet-desk) in [#1652](https://github.com/PHPOffice/PHPWord/pull/1652) & [#2471](https://github.com/PHPOffice/PHPWord/pull/2471) - Word2007 Reader/Writer + ODText Reader/Writer : Add Element Formula in by [@Progi1984](https://github.com/Progi1984) in [#2477](https://github.com/PHPOffice/PHPWord/pull/2477) +- Add Support for Various Missing Features in HTML Writer by [@oleibman](https://github.com/oleibman) in [#2475](https://github.com/PHPOffice/PHPWord/pull/2475) + - Fixed addHTML (text-align:right in html is not handled correctly) in [#2467](https://github.com/PHPOffice/PHPWord/pull/2467) + - HTML Writer : Added ability to specify generic fallback font + - HTML Writer : Added ability to specify handling of whitespace + - HTML Writer : Added support for Table Border style, color, and size + - HTML Writer : Added support for empty paragraphs (Word writer permits, browsers generally suppress) + - HTML Writer : Paragraph style should support indentation, line-height, page-break-before + - HTML Writer : Removed margin-top/bottom when spacing is null in Paragraph style + - HTML Writer : Added default paragraph style to all paragraphs, as well as class Normal + - HTML Writer : Use css @page and page declarations for sections + - HTML Writer : Wrap sections in div, with page break before each (except first) + - PDF Writer : Added support for PageBreak + - PDF Writer : Added callback for modifying the HTML + ### Bug fixes @@ -41,4 +57,8 @@ - Bump phpunit/phpunit from 9.6.11 to 9.6.13 by [@dependabot](https://github.com/dependabot) in [#2481](https://github.com/PHPOffice/PHPWord/pull/2481) - Bump tecnickcom/tcpdf from 6.6.2 to 6.6.5 by [@dependabot](https://github.com/dependabot) in [#2482](https://github.com/PHPOffice/PHPWord/pull/2482) - Bump phpmd/phpmd from 2.13.0 to 2.14.1 by [@dependabot](https://github.com/dependabot) in [#2483](https://github.com/PHPOffice/PHPWord/pull/2483) -- Bump phpstan/phpstan-phpunit from 1.3.14 to 1.3.15 by [@dependabot](https://github.com/dependabot) in [#2494](https://github.com/PHPOffice/PHPWord/pull/2494) \ No newline at end of file +- Bump phpstan/phpstan-phpunit from 1.3.14 to 1.3.15 by [@dependabot](https://github.com/dependabot) in [#2494](https://github.com/PHPOffice/PHPWord/pull/2494) + + +### BC Breaks +- Removed dependency `laminas/laminas-escaper` \ No newline at end of file diff --git a/docs/usage/styles/font.md b/docs/usage/styles/font.md index 94b59b6500..921dc7fd85 100644 --- a/docs/usage/styles/font.md +++ b/docs/usage/styles/font.md @@ -24,5 +24,5 @@ Available Font style options: See ``\PhpOffice\PhpWord\Style\Language`` class for some language codes. - ``position``. The text position, raised or lowered, in half points - ``hidden``. Hidden text, *true* or *false*. -`htmlWhiteSpace``. How white space is handled when generating html/pdf. Possible values are *pre-wrap* and *normal* (other css values for white space are accepted, but are not expected to be useful). -- ``htmlGenericFont``. Fallback generic font for html/pdf. Possible values are *sans-serif*, *serif*, and *monospace* (other css values for generic fonts are accepted). +- ``whiteSpace``. How white space is handled when generating html/pdf. Possible values are *pre-wrap* and *normal* (other css values for white space are accepted, but are not expected to be useful). +- ``fallbackFont``. Fallback generic font for html/pdf. Possible values are *sans-serif*, *serif*, and *monospace* (other css values for generic fonts are accepted). diff --git a/docs/usage/writers.md b/docs/usage/writers.md index f68008bf87..81fb2b99b4 100644 --- a/docs/usage/writers.md +++ b/docs/usage/writers.md @@ -11,12 +11,13 @@ $writer->save(__DIR__ . '/sample.html'); ``` -When generating html/pdf, you can alter the default handling of white space (normal), -and/or supply a fallback generic font as follows: +When generating html/pdf, you can alter the default handling of white space (normal), and/or supply a fallback generic font as follows: ```php - $phpWord->setDefaultHtmlGenericFont('serif'); - $phpWord->setDefaultHtmlWhiteSpace('pre-wrap'); +$writer = IOFactory::createWriter($oPhpWord, 'HTML'); +$writer->setDefaultGenericFont('serif'); +$writer->setDefaultWhiteSpace('pre-wrap'); +$writer->save(__DIR__ . '/sample.html'); ``` ## ODText @@ -39,6 +40,33 @@ $writer = IOFactory::createWriter($oPhpWord, 'PDF'); $writer->save(__DIR__ . '/sample.pdf'); ``` +To generate a PDF, the PhpWord object passes through HTML before generating the PDF. +This HTML can be modified using a callback. + +``` php +setEditCallback('cbEditHTML'); +$writer->save(__DIR__ . '/sample.pdf'); + +/** + * Add a meta tag generator + */ +function cbEditHTML(string $inputHTML): string +{ + $beforeBody = ''; + $needle = ''; + + $pos = strpos($inputHTML, $needle); + if ($pos !== false) { + $inputHTML = (string) substr_replace($inputHTML, "$beforeBody\n$needle", $pos, strlen($needle)); + } + + return $inputHTML; +} +``` + ### Options You can define options like : diff --git a/src/PhpWord/Metadata/Settings.php b/src/PhpWord/Metadata/Settings.php index 5aeac09f8c..2de9ef8959 100644 --- a/src/PhpWord/Metadata/Settings.php +++ b/src/PhpWord/Metadata/Settings.php @@ -114,7 +114,7 @@ class Settings /** * Theme Font Languages. * - * @var Language + * @var ?Language */ private $themeFontLang; @@ -369,22 +369,20 @@ public function setMirrorMargins($mirrorMargins): void /** * Returns the Language. - * - * @return Language */ - public function getThemeFontLang() + public function getThemeFontLang(): ?Language { return $this->themeFontLang; } /** - * sets the Language for this document. - * - * @param Language $themeFontLang + * Sets the Language for this document. */ - public function setThemeFontLang($themeFontLang): void + public function setThemeFontLang(Language $themeFontLang): self { $this->themeFontLang = $themeFontLang; + + return $this; } /** diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index 489119052b..da57f38d29 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -256,68 +256,6 @@ public function setDefaultFontName($fontName): void Settings::setDefaultFontName($fontName); } - /** - * Default generic name for default font for html. - * - * @var string - */ - private $defaultHtmlGenericFont = ''; - - /** - * Get generic name for default font for html. - * - * @return string - */ - public function getDefaultHtmlGenericFont() - { - return $this->defaultHtmlGenericFont; - } - - /** - * Set generic name for default font for html. - * - * @param string $value - * - * @return bool - */ - public function setDefaultHtmlGenericFont($value) - { - $this->defaultHtmlGenericFont = \PhpOffice\PhpWord\Style\Font::validateGenericFont($value); - - return '' !== $this->defaultHtmlGenericFont; - } - - /** - * Default white space style for html. - * - * @var string - */ - private $defaultHtmlWhiteSpace = ''; - - /** - * Get default white space style for html. - * - * @return string - */ - public function getDefaultHtmlWhiteSpace() - { - return $this->defaultHtmlWhiteSpace; - } - - /** - * Set default white space style for html. - * - * @param string $value - * - * @return bool - */ - public function setDefaultHtmlWhiteSpace($value) - { - $this->defaultHtmlWhiteSpace = \PhpOffice\PhpWord\Style\Font::validateWhiteSpace($value); - - return '' !== $this->defaultHtmlWhiteSpace; - } - /** * Get default font size. * @@ -387,4 +325,52 @@ public function save($filename, $format = 'Word2007', $download = false) return true; } + + /** + * Create new section. + * + * @deprecated 0.10.0 + * + * @param array $settings + * + * @return \PhpOffice\PhpWord\Element\Section + * + * @codeCoverageIgnore + */ + public function createSection($settings = null) + { + return $this->addSection($settings); + } + + /** + * Get document properties object. + * + * @deprecated 0.12.0 + * + * @return \PhpOffice\PhpWord\Metadata\DocInfo + * + * @codeCoverageIgnore + */ + public function getDocumentProperties() + { + return $this->getDocInfo(); + } + + /** + * Set document properties object. + * + * @deprecated 0.12.0 + * + * @param \PhpOffice\PhpWord\Metadata\DocInfo $documentProperties + * + * @return self + * + * @codeCoverageIgnore + */ + public function setDocumentProperties($documentProperties) + { + $this->metadata['Document'] = $documentProperties; + + return $this; + } } diff --git a/src/PhpWord/Shared/Handler.php b/src/PhpWord/Shared/Handler.php deleted file mode 100644 index 72232cc9e6..0000000000 --- a/src/PhpWord/Shared/Handler.php +++ /dev/null @@ -1,46 +0,0 @@ - $this->getStyleName(), 'basic' => [ 'name' => $this->getName(), @@ -323,11 +336,9 @@ public function getStyleValues() 'rtl' => $this->isRTL(), 'shading' => $this->getShading(), 'lang' => $this->getLang(), - $hws => $this->getHtmlWhiteSpace(), - $hgf => $this->getHtmlGenericFont(), + 'whiteSpace' => $this->getWhiteSpace(), + 'fallbackFont' => $this->getFallbackFont(), ]; - - return $styles; } /** @@ -953,46 +964,16 @@ public function setPosition($value = null) return $this; } - /** - * Preservation of white space in html. - * - * @var string Value used for css white-space - */ - private $htmlWhiteSpace = ''; - - /** - * Validate html css white-space value. It is expected that only pre-wrap and normal (default) are useful. - * - * @param string $value Should be one of pre-wrap, normal, nowrap, pre, pre-line, initial, inherit - * - * @return string value if valid, null string if not - */ - public static function validateWhiteSpace($value) - { - switch ($value) { - case 'pre-wrap': - case 'normal': - case 'nowrap': - case 'pre': - case 'pre-line': - case 'initial': - case 'inherit': - return $value; - default: - return ''; - } - } - /** * Set html css white-space value. It is expected that only pre-wrap and normal (default) are useful. * - * @param string $value Should be one of pre-wrap, normal, nowrap, pre, pre-line, initial, inherit + * @param string|null $value Should be one of pre-wrap, normal, nowrap, pre, pre-line, initial, inherit * * @return self */ - public function setHtmlWhiteSpace($value) + public function setWhiteSpace(?string $value): self { - $this->htmlWhiteSpace = self::validateWhiteSpace($value); + $this->whiteSpace = Validate::validateCSSWhiteSpace($value); return $this; } @@ -1002,41 +983,9 @@ public function setHtmlWhiteSpace($value) * * @return string */ - public function getHtmlWhiteSpace() + public function getWhiteSpace(): string { - return $this->htmlWhiteSpace; - } - - /** - * Generic font as fallback for html. - * - * @var string generic font name - */ - private $htmlGenericFont = ''; - - /** - * Validate generic font for fallback for html. - * - * @param string $value generic font name - * - * @return string value if legitimate, null string if not - */ - public static function validateGenericFont($value) - { - switch ($value) { - case 'serif': - case 'sans-serif': - case 'monospace': - case 'cursive': - case 'fantasy': - case 'system-ui': - case 'math': - case 'emoji': - case 'fangsong': - return $value; - default: - return ''; - } + return $this->whiteSpace; } /** @@ -1046,9 +995,9 @@ public static function validateGenericFont($value) * * @return self */ - public function setHtmlGenericFont($value) + public function setFallbackFont(?string $value): self { - $this->htmlGenericFont = self::validateGenericFont($value); + $this->fallbackFont = Validate::validateCSSGenericFont($value); return $this; } @@ -1058,8 +1007,8 @@ public function setHtmlGenericFont($value) * * @return string */ - public function getHtmlGenericFont() + public function getFallbackFont(): string { - return $this->htmlGenericFont; + return $this->fallbackFont; } } diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 5624c93560..f740212a2c 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -138,13 +138,15 @@ public function __construct($documentTemplate) public function __destruct() { - if ($this->zipClass !== null) { + // ZipClass + if ($this->zipClass) { try { $this->zipClass->close(); } catch (Throwable $e) { // Nothing to do here. } } + // Temporary file if ($this->tempDocumentFilename && file_exists($this->tempDocumentFilename)) { unlink($this->tempDocumentFilename); } @@ -279,7 +281,7 @@ protected static function ensureMacroCompleted($macro) */ protected static function ensureUtf8Encoded($subject) { - return (null !== $subject) ? Text::toUTF8($subject) : ''; + return $subject ? Text::toUTF8($subject) : ''; } /** @@ -454,7 +456,7 @@ private function chooseImageDimension($baseValue, $inlineValue, $defaultValue) if (null === $value && isset($inlineValue)) { $value = $inlineValue; } - if (!preg_match('/^([0-9]*(cm|mm|in|pt|pc|px|%|em|ex|)|auto)$/i', $value ?? '')) { + if (!preg_match('/^([0-9\.]*(cm|mm|in|pt|pc|px|%|em|ex|)|auto)$/i', $value ?? '')) { $value = null; } if (null === $value) { diff --git a/src/PhpWord/Writer/HTML.php b/src/PhpWord/Writer/HTML.php index ca9784a83b..33db6a0500 100644 --- a/src/PhpWord/Writer/HTML.php +++ b/src/PhpWord/Writer/HTML.php @@ -18,6 +18,9 @@ namespace PhpOffice\PhpWord\Writer; use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Settings; +use PhpOffice\PhpWord\Shared\Validate; +use PhpOffice\PhpWord\Style\Font; /** * HTML writer. @@ -35,13 +38,6 @@ class HTML extends AbstractWriter implements WriterInterface */ protected $isPdf = false; - /** - * Is the current writer creating TCPDF? - * - * @var bool - */ - protected $isTcpdf = false; - /** * Footnotes and endnotes collection. * @@ -54,7 +50,21 @@ class HTML extends AbstractWriter implements WriterInterface * * @var null|callable */ - private $editHtmlCallback; + private $editCallback; + + /** + * Default generic name for default font for html. + * + * @var string + */ + private $defaultGenericFont = ''; + + /** + * Default white space style for html. + * + * @var string + */ + private $defaultWhiteSpace = ''; /** * Create new instance. @@ -99,7 +109,7 @@ public function getContent() $langtext = ''; $phpWord = $this->getPhpWord(); $lang = $phpWord->getSettings()->getThemeFontLang(); - if (!empty($lang)) { // @phpstan-ignore-line + if (!empty($lang)) { $lang2 = $lang->getLatin(); if (!$lang2) { $lang2 = $lang->getEastAsia(); @@ -115,7 +125,9 @@ public function getContent() $content .= $this->getWriterPart('Head')->write(); $content .= $this->getWriterPart('Body')->write(); $content .= '' . PHP_EOL; - $callback = $this->editHtmlCallback; + + // Trigger a callback for editing the entire HTML + $callback = $this->editCallback; if ($callback !== null) { $content = $callback($content); } @@ -123,15 +135,25 @@ public function getContent() return $content; } + /** + * Return the callback to edit the entire HTML. + */ + public function getEditCallback(): ?callable + { + return $this->editCallback; + } + /** * Set a callback to edit the entire HTML. * * The callback must accept the HTML as string as first parameter, * and it must return the edited HTML as string. */ - public function setEditHtmlCallback(?callable $callback): void + public function setEditCallback(?callable $callback): self { - $this->editHtmlCallback = $callback; + $this->editCallback = $callback; + + return $this; } /** @@ -144,16 +166,6 @@ public function isPdf() return $this->isPdf; } - /** - * Get is TCPDF. - * - * @return bool - */ - public function isTcpdf() - { - return $this->isTcpdf; - } - /** * Get notes. * @@ -175,14 +187,62 @@ public function addNote($noteId, $noteMark): void $this->notes[$noteId] = $noteMark; } + /** + * Get generic name for default font for html. + * + * @return string + */ + public function getDefaultGenericFont(): string + { + return $this->defaultGenericFont; + } + + /** + * Set generic name for default font for html. + * + * @param string $value + * + * @return self + */ + public function setDefaultGenericFont(string $value): self + { + $this->defaultGenericFont = Validate::validateCSSGenericFont($value); + + return $this; + } + + /** + * Get default white space style for html. + * + * @return string + */ + public function getDefaultWhiteSpace(): string + { + return $this->defaultWhiteSpace; + } + + /** + * Set default white space style for html. + * + * @param string $value + * + * @return self + */ + public function setDefaultWhiteSpace(string $value): self + { + $this->defaultWhiteSpace = Validate::validateCSSWhiteSpace($value); + + return $this; + } + /** * Escape string or not depending on setting. * * @param string $txt */ - public static function escapeOrNot($txt): string + public function escapeHTML(string $txt): string { - if (\PhpOffice\PhpWord\Settings::isOutputEscapingEnabled()) { + if (Settings::isOutputEscapingEnabled()) { return htmlspecialchars($txt, ENT_QUOTES | (defined('ENT_SUBSTITUTE') ? ENT_SUBSTITUTE : 0), 'UTF-8'); } diff --git a/src/PhpWord/Writer/HTML/Element/Link.php b/src/PhpWord/Writer/HTML/Element/Link.php index 5ff7030118..ac48c865bd 100644 --- a/src/PhpWord/Writer/HTML/Element/Link.php +++ b/src/PhpWord/Writer/HTML/Element/Link.php @@ -40,9 +40,9 @@ public function write() $prefix = $this->element->isInternal() ? '#' : ''; $content = $this->writeOpening(); $content .= "element->getSource()) + . $this->parentWriter->escapeHTML($this->element->getSource()) . '">' - . HTML::escapeOrNot($this->element->getText()) + . $this->parentWriter->escapeHTML($this->element->getText()) . ''; $content .= $this->writeClosing(); diff --git a/src/PhpWord/Writer/HTML/Element/ListItem.php b/src/PhpWord/Writer/HTML/Element/ListItem.php index 4dd61ff321..ddc3ecf0fd 100644 --- a/src/PhpWord/Writer/HTML/Element/ListItem.php +++ b/src/PhpWord/Writer/HTML/Element/ListItem.php @@ -37,7 +37,7 @@ public function write() return ''; } - $content = '

' . HTML::escapeOrNot($this->element->getTextObject()->getText()) . '

' . PHP_EOL; + $content = '

' . $this->parentWriter->escapeHTML($this->element->getTextObject()->getText()) . '

' . PHP_EOL; return $content; } diff --git a/src/PhpWord/Writer/HTML/Element/PageBreak.php b/src/PhpWord/Writer/HTML/Element/PageBreak.php index 8e3971781c..e5c48cc789 100644 --- a/src/PhpWord/Writer/HTML/Element/PageBreak.php +++ b/src/PhpWord/Writer/HTML/Element/PageBreak.php @@ -17,6 +17,8 @@ namespace PhpOffice\PhpWord\Writer\HTML\Element; +use PhpOffice\PhpWord\Writer\PDF\TCPDF; + /** * PageBreak element HTML writer. * @@ -35,7 +37,7 @@ public function write() { /** @var \PhpOffice\PhpWord\Writer\HTML $parentWriter Type hint */ $parentWriter = $this->parentWriter; - if ($parentWriter->isTcpdf()) { + if ($parentWriter instanceof TCPDF) { return '
'; } if ($parentWriter->isPdf()) { diff --git a/src/PhpWord/Writer/HTML/Element/Table.php b/src/PhpWord/Writer/HTML/Element/Table.php index 43320ea8fb..620a0c02eb 100644 --- a/src/PhpWord/Writer/HTML/Element/Table.php +++ b/src/PhpWord/Writer/HTML/Element/Table.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWord\Writer\HTML\Element; +use PhpOffice\PhpWord\Writer\HTML\Style\Table as TableStyleWriter; /** * Table element HTML writer. * @@ -39,7 +40,7 @@ public function write() $rows = $this->element->getRows(); $rowCount = count($rows); if ($rowCount > 0) { - $content .= 'element->getStyle()) . '>' . PHP_EOL; + $content .= 'getTableStyle($this->element->getStyle()) . '>' . PHP_EOL; for ($i = 0; $i < $rowCount; ++$i) { /** @var \PhpOffice\PhpWord\Element\Row $row Type hint */ @@ -51,7 +52,7 @@ public function write() $rowCellCount = count($rowCells); for ($j = 0; $j < $rowCellCount; ++$j) { $cellStyle = $rowCells[$j]->getStyle(); - $cellStyleCss = self::getTableStyle($cellStyle); + $cellStyleCss = $this->getTableStyle($cellStyle); $cellBgColor = $cellStyle->getBgColor(); $cellFgColor = null; if ($cellBgColor && $cellBgColor !== 'auto') { @@ -114,7 +115,7 @@ public function write() * * @return string */ - private static function getTableStyle($tableStyle = null) + private function getTableStyle($tableStyle = null): string { if ($tableStyle == null) { return ''; @@ -125,67 +126,12 @@ private static function getTableStyle($tableStyle = null) return $style . '"'; } - $style = self::getTableStyleString($tableStyle); + $styleWriter = new TableStyleWriter($tableStyle); + $style = $styleWriter->write(); if ($style === '') { return ''; } return ' style="' . $style . '"'; } - - /** - * Translates Table style in CSS equivalent. - * - * @param \PhpOffice\PhpWord\Style\Cell|\PhpOffice\PhpWord\Style\Table|string $tableStyle - * - * @return string - */ - public static function getTableStyleString($tableStyle) - { - $style = ''; - if (is_object($tableStyle) && method_exists($tableStyle, 'getLayout')) { - if ($tableStyle->getLayout() == \PhpOffice\PhpWord\Style\Table::LAYOUT_FIXED) { - $style .= 'table-layout: fixed;'; - } elseif ($tableStyle->getLayout() == \PhpOffice\PhpWord\Style\Table::LAYOUT_AUTO) { - $style .= 'table-layout: auto;'; - } - } - if (is_object($tableStyle) && method_exists($tableStyle, 'isBidiVisual')) { - if ($tableStyle->isBidiVisual()) { - $style .= ' direction: rtl;'; - } - } - - $dirs = ['Top', 'Left', 'Bottom', 'Right']; - $testmethprefix = 'getBorder'; - foreach ($dirs as $dir) { - $testmeth = $testmethprefix . $dir . 'Style'; - if (method_exists($tableStyle, $testmeth)) { - $outval = $tableStyle->{$testmeth}(); - if ($outval === 'single') { - $outval = 'solid'; - } - if (is_string($outval) && 1 == preg_match('/^[a-z]+$/', $outval)) { - $style .= ' border-' . lcfirst($dir) . '-style: ' . $outval . ';'; - } - } - $testmeth = $testmethprefix . $dir . 'Color'; - if (method_exists($tableStyle, $testmeth)) { - $outval = $tableStyle->{$testmeth}(); - if (is_string($outval) && 1 == preg_match('/^[a-z]+$/', $outval)) { - $style .= ' border-' . lcfirst($dir) . '-color: ' . $outval . ';'; - } - } - $testmeth = $testmethprefix . $dir . 'Size'; - if (method_exists($tableStyle, $testmeth)) { - $outval = $tableStyle->{$testmeth}(); - if (is_numeric($outval)) { - // size is in twips - divide by 20 to get points - $style .= ' border-' . lcfirst($dir) . '-width: ' . ((string) ($outval / 20)) . 'pt;'; - } - } - } - - return $style; - } } diff --git a/src/PhpWord/Writer/HTML/Element/Text.php b/src/PhpWord/Writer/HTML/Element/Text.php index 35aa00d2d8..d4392226bb 100644 --- a/src/PhpWord/Writer/HTML/Element/Text.php +++ b/src/PhpWord/Writer/HTML/Element/Text.php @@ -67,19 +67,21 @@ class Text extends AbstractElement */ public function write() { + $this->processFontStyle(); + /** @var \PhpOffice\PhpWord\Element\Text $element Type hint */ $element = $this->element; - $this->getFontStyle(); + + $text = $this->parentWriter->escapeHTML($element->getText()); + if (!$this->withoutP && !trim($text)) { + $text = ' '; + } $content = ''; $content .= $this->writeOpening(); $content .= $this->openingText; $content .= $this->openingTags; - $contenx = HTML::escapeOrNot($element->getText()); - if (!$this->withoutP && !trim(/** @scrutinizer ignore-type */ $contenx)) { - $contenx = ' '; - } - $content .= $contenx; + $content .= $text; $content .= $this->closingTags; $content .= $this->closingText; $content .= $this->writeClosing(); @@ -139,7 +141,7 @@ protected function writeClosing() $content .= $this->writeTrackChangeClosing(); if (!$this->withoutP) { - $content .= HTML::escapeOrNot($this->closingText); + $content .= $this->parentWriter->escapeHTML($this->closingText); $content .= '

' . PHP_EOL; } @@ -221,9 +223,7 @@ private function getParagraphStyle() $pStyleIsObject = ($paragraphStyle instanceof Paragraph); if ($pStyleIsObject) { $styleWriter = new ParagraphStyleWriter($paragraphStyle); - /** @var HTML */ - $temp = $this->parentWriter; - $styleWriter->setParentWriter($temp); + $styleWriter->setParentWriter($this->parentWriter); $style = $styleWriter->write(); } elseif (is_string($paragraphStyle)) { $style = $paragraphStyle; @@ -239,44 +239,50 @@ private function getParagraphStyle() /** * Get font style. */ - private function getFontStyle(): void + private function processFontStyle(): void { /** @var \PhpOffice\PhpWord\Element\Text $element Type hint */ $element = $this->element; - $style = ''; - $langtext = ''; + + $attributeStyle = $attributeLang = ''; $lang = null; + $fontStyle = $element->getFontStyle(); - $fStyleIsObject = ($fontStyle instanceof Font); - if ($fStyleIsObject) { + if ($fontStyle instanceof Font) { + // Attribute style $styleWriter = new FontStyleWriter($fontStyle); - $styl2 = $styleWriter->write(); - if ($styl2) { - $style = " style=\"$styl2\""; + $fontCSS = $styleWriter->write(); + if ($fontCSS) { + $attributeStyle = ' style="' . $fontCSS . '"'; } + // Attribute Lang $lang = $fontStyle->getLang(); } elseif (!empty($fontStyle)) { - $style = " class=\"$fontStyle\""; - /** @var \PhpOffice\PhpWord\Style\Font $styl3 Type hint */ - $styl3 = Style::getStyle($fontStyle); - if (!empty($styl3) && method_exists($styl3, 'getLang')) { // @phpstan-ignore-line - $lang = $styl3->getLang(); + // Attribute class + $attributeStyle = ' class="' . $fontStyle . '"'; + // Attribute Lang + /** @var Font $styl3 */ + $cssClassStyle = Style::getStyle($fontStyle); + if (!empty($cssClassStyle) && method_exists($cssClassStyle, 'getLang')) { + $lang = $cssClassStyle->getLang(); } } + if ($lang) { - $langtext = $lang->getLatin(); - if (!$langtext) { - $langtext = $lang->getEastAsia(); + $attributeLang = $lang->getLatin(); + if (!$attributeLang) { + $attributeLang = $lang->getEastAsia(); } - if (!$langtext) { - $langtext = $lang->getBidirectional(); + if (!$attributeLang) { + $attributeLang = $lang->getBidirectional(); } - if ($langtext) { - $langtext = " lang='$langtext'"; + if ($attributeLang) { + $attributeLang = " lang='$attributeLang'"; } } - if ($style || $langtext) { - $this->openingTags = ""; + + if ($attributeStyle || $attributeLang) { + $this->openingTags = ""; $this->closingTags = ''; } } diff --git a/src/PhpWord/Writer/HTML/Element/Title.php b/src/PhpWord/Writer/HTML/Element/Title.php index c46249f373..65e6cb090b 100644 --- a/src/PhpWord/Writer/HTML/Element/Title.php +++ b/src/PhpWord/Writer/HTML/Element/Title.php @@ -41,7 +41,7 @@ public function write() $text = $this->element->getText(); if (is_string($text)) { - $text = HTML::escapeOrNot($text); + $text = $this->parentWriter->escapeHTML($text); } else { $writer = new Container($this->parentWriter, $text); $text = $writer->write(); diff --git a/src/PhpWord/Writer/HTML/Part/Body.php b/src/PhpWord/Writer/HTML/Part/Body.php index fe25df5f90..e5e2a5b80f 100644 --- a/src/PhpWord/Writer/HTML/Part/Body.php +++ b/src/PhpWord/Writer/HTML/Part/Body.php @@ -19,6 +19,7 @@ use PhpOffice\PhpWord\Writer\HTML\Element\Container; use PhpOffice\PhpWord\Writer\HTML\Element\TextRun as TextRunWriter; +use PhpOffice\PhpWord\Writer\PDF\TCPDF; /** * RTF body part writer. @@ -41,10 +42,10 @@ public function write() $content .= '' . PHP_EOL; $sections = $phpWord->getSections(); $secno = 0; - $tcpdf = $this->getParentWriter()->isTcpdf(); + $isTCPDFWriter = $this->getParentWriter() instanceof TCPDF; foreach ($sections as $section) { ++$secno; - if ($tcpdf && $secno > 1) { + if ($isTCPDFWriter && $secno > 1) { $content .= "
" . PHP_EOL; } else { $content .= "
" . PHP_EOL; diff --git a/src/PhpWord/Writer/HTML/Part/Head.php b/src/PhpWord/Writer/HTML/Part/Head.php index b8daf4dab2..adda046db2 100644 --- a/src/PhpWord/Writer/HTML/Part/Head.php +++ b/src/PhpWord/Writer/HTML/Part/Head.php @@ -18,15 +18,16 @@ namespace PhpOffice\PhpWord\Writer\HTML\Part; use PhpOffice\PhpWord\Settings; +use PhpOffice\PhpWord\Shared\Converter; use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Style\Font; use PhpOffice\PhpWord\Style\Paragraph; use PhpOffice\PhpWord\Style\Table; use PhpOffice\PhpWord\Writer\HTML; -use PhpOffice\PhpWord\Writer\HTML\Element\Table as TableStyleWriter; use PhpOffice\PhpWord\Writer\HTML\Style\Font as FontStyleWriter; use PhpOffice\PhpWord\Writer\HTML\Style\Generic as GenericStyleWriter; use PhpOffice\PhpWord\Writer\HTML\Style\Paragraph as ParagraphStyleWriter; +use PhpOffice\PhpWord\Writer\HTML\Style\Table as TableStyleWriter; /** * RTF head part writer. @@ -67,7 +68,7 @@ public function write() if ($docProps->$method() != '') { $content .= '' . PHP_EOL; } @@ -83,22 +84,24 @@ public function write() * * @return string */ - private function writeStyles() + private function writeStyles(): string { $css = '' . PHP_EOL; return $css; } + + /** + * Set font and alternates for css font-family. + */ + private function getFontFamily(string $font, string $genericFont): string + { + if (empty($font)) { + return ''; + } + $fontfamily = "'" . htmlspecialchars($font, ENT_QUOTES, 'UTF-8') . "'"; + if (!empty($genericFont)) { + $fontfamily .= ", $genericFont"; + } + + return $fontfamily; + } } diff --git a/src/PhpWord/Writer/HTML/Style/Font.php b/src/PhpWord/Writer/HTML/Style/Font.php index 5aead50c07..eb59d02d1e 100644 --- a/src/PhpWord/Writer/HTML/Style/Font.php +++ b/src/PhpWord/Writer/HTML/Style/Font.php @@ -39,14 +39,14 @@ public function write() } $css = []; - $font = self::getFontFamily($style->getName(), $style->getHtmlGenericFont()); + $font = $this->getFontFamily($style->getName(), $style->getFallbackFont()); $size = $style->getSize(); $color = $style->getColor(); $fgColor = $style->getFgColor(); $underline = $style->getUnderline() != FontStyle::UNDERLINE_NONE; $lineThrough = $style->isStrikethrough() || $style->isDoubleStrikethrough(); - $css['font-family'] = $this->getValueIf(!empty($font), "{$font}"); + $css['font-family'] = $this->getValueIf(!empty($font), $font); $css['font-size'] = $this->getValueIf($size !== null, "{$size}pt"); $css['color'] = $this->getValueIf($color !== null, "#{$color}"); $css['background'] = $this->getValueIf($fgColor != '', $fgColor); @@ -61,7 +61,7 @@ public function write() $css['text-transform'] = $this->getValueIf($style->isAllCaps(), 'uppercase'); $css['font-variant'] = $this->getValueIf($style->isSmallCaps(), 'small-caps'); $css['display'] = $this->getValueIf($style->isHidden(), 'none'); - $whitespace = $style->getHtmlWhiteSpace(); + $whitespace = $style->getWhiteSpace(); if ($whitespace) { $css['white-space'] = $whitespace; } @@ -79,13 +79,8 @@ public function write() /** * Set font and alternates for css font-family. - * - * @param string $font - * @param string $genericFont - * - * @return string */ - public static function getFontFamily($font, $genericFont) + private function getFontFamily(?string $font, string $genericFont): string { if (empty($font)) { return ''; diff --git a/src/PhpWord/Writer/HTML/Style/Paragraph.php b/src/PhpWord/Writer/HTML/Style/Paragraph.php index 73286bda8b..9213673bb5 100644 --- a/src/PhpWord/Writer/HTML/Style/Paragraph.php +++ b/src/PhpWord/Writer/HTML/Style/Paragraph.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWord\Writer\HTML\Style; +use PhpOffice\PhpWord\Shared\Converter; use PhpOffice\PhpWord\SimpleType\Jc; /** @@ -46,31 +47,25 @@ public function write() switch ($style->getAlignment()) { case Jc::CENTER: $textAlign = 'center'; - break; case Jc::END: $textAlign = ($style->isBidi()) ? 'left' : 'right'; - break; case Jc::MEDIUM_KASHIDA: case Jc::HIGH_KASHIDA: case Jc::LOW_KASHIDA: - case /** @scrutinizer ignore-deprecated */ Jc::RIGHT: + case Jc::RIGHT: $textAlign = 'right'; - break; case Jc::BOTH: case Jc::DISTRIBUTE: case Jc::THAI_DISTRIBUTE: - case /** @scrutinizer ignore-deprecated */ Jc::JUSTIFY: + case Jc::JUSTIFY: $textAlign = 'justify'; - break; - case /** @scrutinizer ignore-deprecated */ Jc::LEFT: + case Jc::LEFT: $textAlign = 'left'; - break; - default: //all others, including Jc::START $textAlign = ($style->isBidi()) ? 'right' : 'left'; @@ -89,23 +84,28 @@ public function write() $css['margin-bottom'] = $this->getValueIf(null !== $after, ($after / 20) . 'pt'); } - $lht = $style->getLineHeight(); - if (!empty($lht)) { - $css['line-height'] = $lht; + // Line Height + $lineHeight = $style->getLineHeight(); + if (!empty($lineHeight)) { + $css['line-height'] = $lineHeight; } - $ind = $style->getIndentation(); - if ($ind != null) { - $tcpdf = $this->getParentWriter()->isTcpdf(); - $left = $ind->getLeft(); - $inches = $left * 1.0 / \PhpOffice\PhpWord\Shared\Converter::INCH_TO_TWIP; - $css[$tcpdf ? 'text-indent' : 'margin-left'] = ((string) $inches) . 'in'; - $left = $ind->getRight(); - $inches = $left * 1.0 / \PhpOffice\PhpWord\Shared\Converter::INCH_TO_TWIP; + + // Indentation (Margin) + $indentation = $style->getIndentation(); + if ($indentation) { + $inches = $indentation->getLeft() * 1.0 / Converter::INCH_TO_TWIP; + $css[$this->getParentWriter() instanceof TCPDF ? 'text-indent' : 'margin-left'] = ((string) $inches) . 'in'; + + $inches = $indentation->getRight() * 1.0 / Converter::INCH_TO_TWIP; $css['margin-right'] = ((string) $inches) . 'in'; } + + // Page Break Before if ($style->hasPageBreakBefore()) { $css['page-break-before'] = 'always'; } + + // Bidirectional if ($style->isBidi()) { $css['direction'] = 'rtl'; } diff --git a/src/PhpWord/Writer/HTML/Style/Table.php b/src/PhpWord/Writer/HTML/Style/Table.php new file mode 100644 index 0000000000..d2c318a69f --- /dev/null +++ b/src/PhpWord/Writer/HTML/Style/Table.php @@ -0,0 +1,82 @@ +getStyle(); + if (!$style instanceof StyleTable && !$style instanceof StyleCell) { + return ''; + } + + $css = []; + if (is_object($style) && method_exists($style, 'getLayout')) { + if ($style->getLayout() == StyleTable::LAYOUT_FIXED) { + $css['table-layout'] = 'fixed'; + } elseif ($style->getLayout() == StyleTable::LAYOUT_AUTO) { + $css['table-layout'] = 'auto'; + } + } + if (is_object($style) && method_exists($style, 'isBidiVisual')) { + if ($style->isBidiVisual()) { + $css['direction'] = 'rtl'; + } + } + + foreach (['Top', 'Left', 'Bottom', 'Right'] as $direction) { + $method = 'getBorder' . $direction . 'Style'; + if (method_exists($style, $method)) { + $outval = $style->{$method}(); + if ($outval === 'single') { + $outval = 'solid'; + } + if (is_string($outval) && 1 == preg_match('/^[a-z]+$/', $outval)) { + $css['border-' . lcfirst($direction) . '-style'] = $outval; + } + } + + $method = 'getBorder' . $direction . 'Color'; + if (method_exists($style, $method)) { + $outval = $style->{$method}(); + if (is_string($outval) && 1 == preg_match('/^[a-z]+$/', $outval)) { + $css['border-' . lcfirst($direction) . '-color'] = $outval; + } + } + + $method = 'getBorder' . $direction . 'Size'; + if (method_exists($style, $method)) { + $outval = $style->{$method}(); + if (is_numeric($outval)) { + // size is in twips - divide by 20 to get points + $css['border-' . lcfirst($direction) . '-width'] = ((string) ($outval / 20)) . 'pt'; + } + } + } + + return $this->assembleCss($css); + } +} diff --git a/src/PhpWord/Writer/PDF.php b/src/PhpWord/Writer/PDF.php index b24e66efb8..8cd52e6884 100644 --- a/src/PhpWord/Writer/PDF.php +++ b/src/PhpWord/Writer/PDF.php @@ -19,6 +19,7 @@ use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Writer\PDF\AbstractRenderer; use PhpOffice\PhpWord\Settings; /** @@ -71,11 +72,16 @@ public function __call($name, $arguments) // throw new Exception("PDF Rendering library has not been defined."); // } - return call_user_func_array([$this->renderer, $name], $arguments); + return call_user_func_array([$this->getRenderer(), $name], $arguments); } public function save(string $filename): void { - $this->renderer->save($filename); + $this->getRenderer()->save($filename); + } + + public function getRenderer(): AbstractRenderer + { + return $this->renderer; } } diff --git a/src/PhpWord/Writer/PDF/TCPDF.php b/src/PhpWord/Writer/PDF/TCPDF.php index 5ef92f451b..3a8206ce22 100644 --- a/src/PhpWord/Writer/PDF/TCPDF.php +++ b/src/PhpWord/Writer/PDF/TCPDF.php @@ -21,6 +21,7 @@ use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Writer\WriterInterface; +use TCPDF as TCPDFBase; /** * TCPDF writer. @@ -38,17 +39,6 @@ class TCPDF extends AbstractRenderer implements WriterInterface */ protected $includeFile = 'tcpdf.php'; - /** - * Overridden to set isTcpdf. - * - * @codeCoverageIgnore - */ - public function __construct(PhpWord $phpWord) - { - parent::__construct($phpWord); - $this->isTcpdf = true; - } - /** * Gets the implementation of external PDF library that should be used. * @@ -56,11 +46,11 @@ public function __construct(PhpWord $phpWord) * @param string $unit Unit measure * @param string $paperSize Paper size * - * @return \TCPDF implementation + * @return TCPDFBase implementation */ protected function createExternalWriterInstance($orientation, $unit, $paperSize) { - $instance = new \TCPDF($orientation, $unit, $paperSize); + $instance = new TCPDFBase($orientation, $unit, $paperSize); if ($this->getFont()) { $instance->setFont($this->getFont(), $instance->getFontStyle(), $instance->getFontSizePt()); @@ -77,7 +67,7 @@ protected function createExternalWriterInstance($orientation, $unit, $paperSize) * between paragaraphs when the user has * explicitly set those values to numeric in default style. */ - protected function prepareToWrite(\TCPDF $pdf): void + protected function prepareToWrite(TCPDFBase $pdf): void { $pdf->AddPage(); $customStyles = Style::getStyles(); diff --git a/src/PhpWord/Writer/RTF/Part/Document.php b/src/PhpWord/Writer/RTF/Part/Document.php index 1d55d43fa1..a0002583a9 100644 --- a/src/PhpWord/Writer/RTF/Part/Document.php +++ b/src/PhpWord/Writer/RTF/Part/Document.php @@ -203,8 +203,6 @@ private function writeSections() $elementWriter = new Container($this->getParentWriter(), $section); $content .= $elementWriter->write(); - - //$content .= '\sect' . PHP_EOL; } return $content; diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index 333975da03..e19d24bbad 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -35,9 +35,9 @@ class Paragraph extends AbstractStyle */ private $nestedLevel = 0; - private const LEFT = /** @scrutinizer ignore-deprecated */ Jc::LEFT; - private const RIGHT = /** @scrutinizer ignore-deprecated */ Jc::RIGHT; - private const JUSTIFY = /** @scrutinizer ignore-deprecated */ Jc::JUSTIFY; + private const LEFT = Jc::LEFT; + private const RIGHT = Jc::RIGHT; + private const JUSTIFY = Jc::JUSTIFY; /** * Write style. diff --git a/src/PhpWord/Writer/Word2007/Element/TOC.php b/src/PhpWord/Writer/Word2007/Element/TOC.php index f7d00c14c8..2cf76155e4 100644 --- a/src/PhpWord/Writer/Word2007/Element/TOC.php +++ b/src/PhpWord/Writer/Word2007/Element/TOC.php @@ -71,7 +71,7 @@ private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, Title $ti $fontStyle = $element->getStyleFont(); $isObject = ($fontStyle instanceof Font) ? true : false; $rId = $title->getRelationId(); - $indent = ($title->getDepth() - 1) * $tocStyle->getIndent(); + $indent = (int) (($title->getDepth() - 1) * $tocStyle->getIndent()); $xmlWriter->startElement('w:p'); @@ -93,8 +93,10 @@ private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, Title $ti $styleWriter->write(); } $xmlWriter->startElement('w:t'); + $titleText = $title->getText(); $this->writeText(is_string($titleText) ? $titleText : ''); + $xmlWriter->endElement(); // w:t $xmlWriter->endElement(); // w:r @@ -142,10 +144,8 @@ private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, Title $ti /** * Write style. - * - * @param float|int $indent */ - private function writeStyle(XMLWriter $xmlWriter, TOCElement $element, $indent): void + private function writeStyle(XMLWriter $xmlWriter, TOCElement $element, int $indent): void { $tocStyle = $element->getStyleTOC(); $fontStyle = $element->getStyleFont(); diff --git a/src/PhpWord/Writer/Word2007/Element/TOC.php.bak b/src/PhpWord/Writer/Word2007/Element/TOC.php.bak deleted file mode 100644 index a86199bf23..0000000000 --- a/src/PhpWord/Writer/Word2007/Element/TOC.php.bak +++ /dev/null @@ -1,202 +0,0 @@ -getXmlWriter(); - $element = $this->getElement(); - if (!$element instanceof TOCElement) { - return; - } - - $titles = $element->getTitles(); - $writeFieldMark = true; - - foreach ($titles as $title) { - $this->writeTitle($xmlWriter, $element, $title, $writeFieldMark); - if ($writeFieldMark) { - $writeFieldMark = false; - } - } - - $xmlWriter->startElement('w:p'); - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:fldChar'); - $xmlWriter->writeAttribute('w:fldCharType', 'end'); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - $xmlWriter->endElement(); - } - - /** - * Write title. - * - * @param \PhpOffice\PhpWord\Element\Title $title - * @param bool $writeFieldMark - */ - private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, $title, $writeFieldMark): void - {echo "here2\n"; - $tocStyle = $element->getStyleTOC(); - $fontStyle = $element->getStyleFont(); - $isObject = ($fontStyle instanceof Font) ? true : false; - $rId = $title->getRelationId(); - $indent = ($title->getDepth() - 1) * $tocStyle->getIndent(); - - $xmlWriter->startElement('w:p'); - - // Write style and field mark - $this->writeStyle($xmlWriter, $element, $indent); - if ($writeFieldMark) { - $this->writeFieldMark($xmlWriter, $element); - } - - // Hyperlink - $xmlWriter->startElement('w:hyperlink'); - $xmlWriter->writeAttribute('w:anchor', "_Toc{$rId}"); - $xmlWriter->writeAttribute('w:history', '1'); - - // Title text - $xmlWriter->startElement('w:r'); - if ($isObject) { - $styleWriter = new FontStyleWriter($xmlWriter, $fontStyle); - $styleWriter->write(); - } - $xmlWriter->startElement('w:t'); - $titleText = $title->getText(); - $this->writeText(is_string($titleText) ? $titleText : ''); - $xmlWriter->endElement(); // w:t - $xmlWriter->endElement(); // w:r - - $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->text("PAGEREF _Toc{$rId} \\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 - } - - /** - * Write style. - * - * @param float|int $indent - */ - private function writeStyle(XMLWriter $xmlWriter, TOCElement $element, $indent): void - {echo "here3\n"; - $tocStyle = $element->getStyleTOC(); - $fontStyle = $element->getStyleFont(); - $isObject = ($fontStyle instanceof Font) ? true : false; - - $xmlWriter->startElement('w:pPr'); - - // Paragraph - if ($isObject && null !== $fontStyle->getParagraph()) { - $styleWriter = new ParagraphStyleWriter($xmlWriter, $fontStyle->getParagraph()); - $styleWriter->write(); - } - - // Font - if (!empty($fontStyle) && !$isObject) { - $xmlWriter->startElement('w:rPr'); - $xmlWriter->startElement('w:rStyle'); - $xmlWriter->writeAttribute('w:val', $fontStyle); - $xmlWriter->endElement(); - $xmlWriter->endElement(); // w:rPr - } - - // Tab - $xmlWriter->startElement('w:tabs'); - $styleWriter = new TabStyleWriter($xmlWriter, $tocStyle); - $styleWriter->write(); - $xmlWriter->endElement(); - - // Indent - if ($indent > 0) { - $xmlWriter->startElement('w:ind'); - $xmlWriter->writeAttribute('w:left', $indent); - $xmlWriter->endElement(); - } - - $xmlWriter->endElement(); // w:pPr - } - - /** - * Write TOC Field. - */ - private function writeFieldMark(XMLWriter $xmlWriter, TOCElement $element): void - {echo "here4\n"; - $minDepth = $element->getMinDepth(); - $maxDepth = $element->getMaxDepth(); - - $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->text("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(); - } -} diff --git a/tests/PhpWordTests/Shared/HandlerTest.php b/tests/PhpWordTests/Shared/HandlerTest.php deleted file mode 100644 index 4aa051d3ce..0000000000 --- a/tests/PhpWordTests/Shared/HandlerTest.php +++ /dev/null @@ -1,79 +0,0 @@ -getMessage()); - } - } - } - - public function testNotice(): void - { - try { - Handler::notice('invalidtz'); - self::fail('Expected error/exception did not happen'); - } catch (Throwable $e) { - self::assertStringContainsString('Timezone', $e->getMessage()); - } - } - - public function testWarning(): void - { - try { - Handler::warning(); - self::fail('Expected error/exception did not happen'); - } catch (Throwable $e) { - self::assertStringContainsString('ailed to open stream', $e->getMessage()); - } - } - - public function testUserDeprecated(): void - { - try { - Handler::userDeprecated(); - self::fail('Expected error/exception did not happen'); - } catch (Throwable $e) { - self::assertStringContainsString('hello', $e->getMessage()); - } - } - - public function testUserNotice(): void - { - try { - Handler::userNotice(); - self::fail('Expected error/exception did not happen'); - } catch (Throwable $e) { - self::assertStringContainsString('userNotice', $e->getMessage()); - } - } - - public function testUserWarning(): void - { - try { - Handler::userWarning(); - self::fail('Expected error/exception did not happen'); - } catch (Throwable $e) { - self::assertStringContainsString('userWarning', $e->getMessage()); - } - } -} diff --git a/tests/PhpWordTests/Shared/ValidateTest.php b/tests/PhpWordTests/Shared/ValidateTest.php new file mode 100644 index 0000000000..b9d5549cec --- /dev/null +++ b/tests/PhpWordTests/Shared/ValidateTest.php @@ -0,0 +1,76 @@ +assertEquals($expected, Validate::validateCSSGenericFont($value)); + } + + public static function providerCSSGenericFont(): iterable + { + $data = []; + // Valid data + foreach(Validate::CSS_GENERICFONT as $value) { + $data[] = [ + $value, + $value, + ]; + } + // Invalid data + $data[] = ['invalidData', '']; + $data[] = ['', '']; + $data[] = [null, '']; + + return $data; + } + + /** + * @dataProvider providerCSSWhiteSpace + */ + public function testValidateCSSWhiteSpace(?string $value, string $expected): void + { + $this->assertEquals($expected, Validate::validateCSSWhiteSpace($value)); + } + + public static function providerCSSWhiteSpace(): iterable + { + $data = []; + // Valid data + foreach(Validate::CSS_WHITESPACE as $value) { + $data[] = [ + $value, + $value, + ]; + } + // Invalid data + $data[] = ['invalidData', '']; + $data[] = ['', '']; + $data[] = [null, '']; + + return $data; + } +} diff --git a/tests/PhpWordTests/Style/FontTest.php b/tests/PhpWordTests/Style/FontTest.php index e2d7d4f582..e11b8604ac 100644 --- a/tests/PhpWordTests/Style/FontTest.php +++ b/tests/PhpWordTests/Style/FontTest.php @@ -79,8 +79,8 @@ public function testSetStyleValueWithNullOrEmpty(): void 'kerning' => null, 'lang' => null, 'hidden' => false, - 'htmlWhiteSpace' => '', - 'htmlGenericFont' => '', + 'whiteSpace' => '', + 'fallbackFont' => '', ]; foreach ($attributes as $key => $default) { $get = is_bool($default) ? "is{$key}" : "get{$key}"; @@ -123,8 +123,8 @@ public function testSetStyleValueNormal(): void 'noProof' => true, 'lang' => new Language(Language::EN_US), 'hidden' => true, - 'htmlWhiteSpace' => 'pre-wrap', - 'htmlGenericFont' => 'serif', + 'whiteSpace' => 'pre-wrap', + 'fallbackFont' => 'serif', ]; $object->setStyleByArray($attributes); foreach ($attributes as $key => $value) { diff --git a/tests/PhpWordTests/Writer/HTML/Element/PageBreakTest.php b/tests/PhpWordTests/Writer/HTML/Element/PageBreakTest.php new file mode 100644 index 0000000000..1cf2208bd2 --- /dev/null +++ b/tests/PhpWordTests/Writer/HTML/Element/PageBreakTest.php @@ -0,0 +1,76 @@ + 
'. PHP_EOL, $object->write()); + } + + public function testMPDF(): void + { + $rendererName = Settings::PDF_RENDERER_MPDF; + $rendererLibraryPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/mpdf/mpdf'); + Settings::setPdfRenderer($rendererName, $rendererLibraryPath); + $writer = new PDF(new PhpWord()); + + $object = new PageBreak($writer->getRenderer(), new BasePageBreak()); + + self::assertEquals('', $object->write()); + } + + public function testDOMPDF(): void + { + $rendererName = Settings::PDF_RENDERER_DOMPDF; + $rendererLibraryPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/dompdf/dompdf'); + Settings::setPdfRenderer($rendererName, $rendererLibraryPath); + $writer = new PDF(new PhpWord()); + + $object = new PageBreak($writer->getRenderer(), new BasePageBreak()); + + self::assertEquals('', $object->write()); + } + + public function testTCPDF(): void + { + $rendererName = Settings::PDF_RENDERER_TCPDF; + $rendererLibraryPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/tecnickcom/tcpdf'); + Settings::setPdfRenderer($rendererName, $rendererLibraryPath); + $writer = new PDF(new PhpWord()); + + $object = new PageBreak($writer->getRenderer(), new BasePageBreak()); + + self::assertEquals('
', $object->write()); + } +} diff --git a/tests/PhpWordTests/Writer/HTML/Element/TableTest.php b/tests/PhpWordTests/Writer/HTML/Element/TableTest.php new file mode 100644 index 0000000000..23a1751b47 --- /dev/null +++ b/tests/PhpWordTests/Writer/HTML/Element/TableTest.php @@ -0,0 +1,167 @@ +addSection(); + + $bsnone = ['borderStyle' => 'none']; + $table1 = $section->addTable($bsnone); + $row1 = $table1->addRow(); + $row1->addCell(null, $bsnone)->addText('Row 1 Cell 1'); + $row1->addCell(null, $bsnone)->addText('Row 1 Cell 2'); + $row2 = $table1->addRow(); + $row2->addCell(null, $bsnone)->addText('Row 2 Cell 1'); + $row2->addCell(null, $bsnone)->addText('Row 2 Cell 2'); + + $table1 = $section->addTable(); + $row1 = $table1->addRow(); + $row1->addCell()->addText('Row 1 Cell 1'); + $row1->addCell()->addText('Row 1 Cell 2'); + $row2 = $table1->addRow(); + $row2->addCell()->addText('Row 2 Cell 1'); + $row2->addCell()->addText('Row 2 Cell 2'); + + $bstyle = ['borderStyle' => 'dashed', 'borderColor' => 'red']; + $table1 = $section->addTable($bstyle); + $row1 = $table1->addRow(); + $row1->addCell(null, $bstyle)->addText('Row 1 Cell 1'); + $row1->addCell(null, $bstyle)->addText('Row 1 Cell 2'); + $row2 = $table1->addRow(); + $row2->addCell(null, $bstyle)->addText('Row 2 Cell 1'); + $row2->addCell(null, $bstyle)->addText('Row 2 Cell 2'); + + $bstyle = [ + 'borderTopStyle' => 'dotted', + 'borderLeftStyle' => 'dashed', + 'borderRightStyle' => 'dashed', + 'borderBottomStyle' => 'dotted', + 'borderTopColor' => 'blue', + 'borderLeftColor' => 'green', + 'borderRightColor' => 'green', + 'borderBottomColor' => 'blue', + ]; + $table1 = $section->addTable($bstyle); + $row1 = $table1->addRow(); + $row1->addCell(null, $bstyle)->addText('Row 1 Cell 1'); + $row1->addCell(null, $bstyle)->addText('Row 1 Cell 2'); + $row2 = $table1->addRow(); + $row2->addCell(null, $bstyle)->addText('Row 2 Cell 1'); + $row2->addCell(null, $bstyle)->addText('Row 2 Cell 2'); + + $bstyle = ['borderStyle' => 'solid', 'borderSize' => 5]; + $table1 = $section->addTable($bstyle); + $row1 = $table1->addRow(); + $row1->addCell(null, $bstyle)->addText('Row 1 Cell 1'); + $row1->addCell(null, $bstyle)->addText('Row 1 Cell 2'); + $row2 = $table1->addRow(); + $row2->addCell(null, $bstyle)->addText('Row 2 Cell 1'); + $row2->addCell(null, $bstyle)->addText('Row 2 Cell 2'); + + $phpWord->addTableStyle('tstyle', ['borderStyle' => 'solid', 'borderSize' => 5]); + $table1 = $section->addTable('tstyle'); + $row1 = $table1->addRow(); + $row1->addCell(null, 'tstyle')->addText('Row 1 Cell 1'); + $row1->addCell(null, 'tstyle')->addText('Row 1 Cell 2'); + $row2 = $table1->addRow(); + $row2->addCell(null, 'tstyle')->addText('Row 2 Cell 1'); + $row2->addCell(null, 'tstyle')->addText('Row 2 Cell 2'); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + $cssnone = 'border-top-style: none;' + . ' border-left-style: none;' + . ' border-bottom-style: none;' + . ' border-right-style: none;'; + self::assertEquals("table-layout: auto; $cssnone", Helper::getTextContent($xpath, '/html/body/div/table[1]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[1]/tr[1]/td[1]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[1]/tr[1]/td[2]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[1]/tr[2]/td[1]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[1]/tr[2]/td[2]', 'style')); + + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/table[2]', 'style')); + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/table[2]/tr[1]/td[1]', 'style')); + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/table[2]/tr[1]/td[2]', 'style')); + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/table[2]/tr[2]/td[1]', 'style')); + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/table[2]/tr[2]/td[2]', 'style')); + + $cssnone = 'border-top-style: dashed;' + . ' border-top-color: red;' + . ' border-left-style: dashed;' + . ' border-left-color: red;' + . ' border-bottom-style: dashed;' + . ' border-bottom-color: red;' + . ' border-right-style: dashed;' + . ' border-right-color: red;'; + self::assertEquals("table-layout: auto; $cssnone", Helper::getTextContent($xpath, '/html/body/div/table[3]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[3]/tr[1]/td[1]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[3]/tr[1]/td[2]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[3]/tr[2]/td[1]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[3]/tr[2]/td[2]', 'style')); + + $cssnone = 'border-top-style: dotted;' + . ' border-top-color: blue;' + . ' border-left-style: dashed;' + . ' border-left-color: green;' + . ' border-bottom-style: dotted;' + . ' border-bottom-color: blue;' + . ' border-right-style: dashed;' + . ' border-right-color: green;'; + self::assertEquals("table-layout: auto; $cssnone", Helper::getTextContent($xpath, '/html/body/div/table[4]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[4]/tr[1]/td[1]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[4]/tr[1]/td[2]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[4]/tr[2]/td[1]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[4]/tr[2]/td[2]', 'style')); + + $cssnone = 'border-top-style: solid;' + . ' border-top-width: 0.25pt;' + . ' border-left-style: solid;' + . ' border-left-width: 0.25pt;' + . ' border-bottom-style: solid;' + . ' border-bottom-width: 0.25pt;' + . ' border-right-style: solid;' + . ' border-right-width: 0.25pt;'; + self::assertEquals("table-layout: auto; $cssnone", Helper::getTextContent($xpath, '/html/body/div/table[5]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[5]/tr[1]/td[1]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[5]/tr[1]/td[2]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[5]/tr[2]/td[1]', 'style')); + self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[5]/tr[2]/td[2]', 'style')); + + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/table[6]', 'style')); + self::assertEquals('tstyle', Helper::getTextContent($xpath, '/html/body/div/table[6]', 'class')); + $style = Helper::getTextContent($xpath, '/html/head/style'); + self::assertNotFalse(preg_match('/^[.]tstyle[^\\r\\n]*/m', $style, $matches)); + self::assertEquals(".tstyle {table-layout: auto; $cssnone}", $matches[0]); + } +} diff --git a/tests/PhpWordTests/Writer/HTML/FontTest.php b/tests/PhpWordTests/Writer/HTML/FontTest.php index cffcd6c7de..442c2639c9 100644 --- a/tests/PhpWordTests/Writer/HTML/FontTest.php +++ b/tests/PhpWordTests/Writer/HTML/FontTest.php @@ -113,9 +113,9 @@ public function testFontNames2(): void $phpWord->setDefaultFontName('Courier New'); $phpWord->setDefaultFontSize(12); $phpWord->addFontStyle('style1', ['name' => 'Tahoma', 'size' => 10, 'color' => '1B2232', 'bold' => true]); - $phpWord->addFontStyle('style2', ['name' => 'Arial', 'size' => 10, 'htmlGenericFont' => 'sans-serif']); - $phpWord->addFontStyle('style3', ['name' => 'DejaVu Sans Monospace', 'size' => 10, 'htmlGenericFont' => 'monospace']); - $phpWord->addFontStyle('style4', ['name' => 'Arial', 'size' => 10, 'htmlGenericFont' => 'invalid']); + $phpWord->addFontStyle('style2', ['name' => 'Arial', 'size' => 10, 'fallbackFont' => 'sans-serif']); + $phpWord->addFontStyle('style3', ['name' => 'DejaVu Sans Monospace', 'size' => 10, 'fallbackFont' => 'monospace']); + $phpWord->addFontStyle('style4', ['name' => 'Arial', 'size' => 10, 'fallbackFont' => 'invalid']); $section1 = $phpWord->addSection(); $section1->addText('Default font'); $section1->addText('Tahoma', 'style1'); @@ -159,11 +159,10 @@ public function testFontNames3(): void $phpWord = new PhpWord(); $phpWord->setDefaultFontName('Courier New'); $phpWord->setDefaultFontSize(12); - $phpWord->setDefaultHtmlGenericFont('monospace'); $phpWord->addFontStyle('style1', ['name' => 'Tahoma', 'size' => 10, 'color' => '1B2232', 'bold' => true]); - $phpWord->addFontStyle('style2', ['name' => 'Arial', 'size' => 10, 'htmlGenericFont' => 'sans-serif']); - $phpWord->addFontStyle('style3', ['name' => 'DejaVu Sans Monospace', 'size' => 10, 'htmlGenericFont' => 'monospace']); - $phpWord->addFontStyle('style4', ['name' => 'Arial', 'size' => 10, 'htmlGenericFont' => 'invalid']); + $phpWord->addFontStyle('style2', ['name' => 'Arial', 'size' => 10, 'fallbackFont' => 'sans-serif']); + $phpWord->addFontStyle('style3', ['name' => 'DejaVu Sans Monospace', 'size' => 10, 'fallbackFont' => 'monospace']); + $phpWord->addFontStyle('style4', ['name' => 'Arial', 'size' => 10, 'fallbackFont' => 'invalid']); $section1 = $phpWord->addSection(); $section1->addText('Default font'); $section1->addText('Tahoma', 'style1'); @@ -171,7 +170,7 @@ public function testFontNames3(): void $section1->addText('DejaVu Sans Monospace', 'style3'); $section1->addText('Arial with invalid fallback', 'style4'); - $dom = Helper::getAsHTML($phpWord); + $dom = Helper::getAsHTML($phpWord, '', 'monospace'); $xpath = new DOMXPath($dom); self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/p[1]', 'class')); @@ -205,12 +204,11 @@ public function testFontNames3(): void public function testWhiteSpace(): void { $phpWord = new PhpWord(); - $phpWord->setDefaultHtmlWhiteSpace('pre-wrap'); $phpWord->setDefaultFontSize(12); - $phpWord->addFontStyle('style1', ['name' => 'Courier New', 'size' => 10, 'htmlWhiteSpace' => 'pre-wrap']); - $phpWord->addFontStyle('style2', ['name' => 'Courier New', 'size' => 10, 'htmlWhiteSpace' => 'invalid']); - $phpWord->addFontStyle('style3', ['name' => 'Courier New', 'size' => 10, 'htmlWhiteSpace' => 'normal']); - $phpWord->addFontStyle('style4', ['name' => 'Courier New', 'size' => 10, 'htmlWhiteSpace' => 'invalid']); + $phpWord->addFontStyle('style1', ['name' => 'Courier New', 'size' => 10, 'whiteSpace' => 'pre-wrap']); + $phpWord->addFontStyle('style2', ['name' => 'Courier New', 'size' => 10, 'whiteSpace' => 'invalid']); + $phpWord->addFontStyle('style3', ['name' => 'Courier New', 'size' => 10, 'whiteSpace' => 'normal']); + $phpWord->addFontStyle('style4', ['name' => 'Courier New', 'size' => 10, 'whiteSpace' => 'invalid']); $text = 'This is a long line which will be split over 2 lines with pre-wrap'; $section1 = $phpWord->addSection(); $section1->addText($text); @@ -219,7 +217,7 @@ public function testWhiteSpace(): void $section1->addText($text, 'style3'); $section1->addText($text, 'style4'); - $dom = Helper::getAsHTML($phpWord); + $dom = Helper::getAsHTML($phpWord, 'pre-wrap'); $xpath = new DOMXPath($dom); $style = Helper::getTextContent($xpath, '/html/head/style'); @@ -245,7 +243,7 @@ public function testWhiteSpace(): void public function testInline(): void { $phpWord = new PhpWord(); - $style1 = ['name' => 'Courier New', 'size' => 10, 'htmlWhiteSpace' => 'pre-wrap']; + $style1 = ['name' => 'Courier New', 'size' => 10, 'whiteSpace' => 'pre-wrap']; $style2 = ['name' => 'Verdana', 'size' => 8.5]; $text = 'This is a paragraph.'; $section1 = $phpWord->addSection(); diff --git a/tests/PhpWordTests/Writer/HTML/Helper.php b/tests/PhpWordTests/Writer/HTML/Helper.php index ccd542a1c6..b777d4be14 100644 --- a/tests/PhpWordTests/Writer/HTML/Helper.php +++ b/tests/PhpWordTests/Writer/HTML/Helper.php @@ -84,9 +84,11 @@ public static function getLength(DOMXPath $xpath, string $query): int return $returnVal; } - public static function getAsHTML(PhpWord $phpWord): DOMDocument + public static function getAsHTML(PhpWord $phpWord, string $defaultWhiteSpace = '', string $defaultGenericFont = ''): DOMDocument { $htmlWriter = new HTML($phpWord); + $htmlWriter->setDefaultWhiteSpace($defaultWhiteSpace); + $htmlWriter->setDefaultGenericFont($defaultGenericFont); $dom = new DOMDocument(); $dom->loadHTML($htmlWriter->getContent()); diff --git a/tests/PhpWordTests/Writer/HTML/ParagraphTest.php b/tests/PhpWordTests/Writer/HTML/ParagraphTest.php index 42c338cdb8..dc306df978 100644 --- a/tests/PhpWordTests/Writer/HTML/ParagraphTest.php +++ b/tests/PhpWordTests/Writer/HTML/ParagraphTest.php @@ -67,7 +67,7 @@ public function testParagraphAndFontStyles(): void $phpWord->addParagraphStyle('indented', [ 'indentation' => ['left' => 0.50 * Converter::INCH_TO_TWIP, 'right' => 0.60 * Converter::INCH_TO_TWIP], ]); - $phpWord->addFontStyle('style1', ['name' => 'Courier New', 'size' => 10, 'htmlWhiteSpace' => 'pre-wrap', 'htmlGenericFont' => 'monospace']); + $phpWord->addFontStyle('style1', ['name' => 'Courier New', 'size' => 10, 'whiteSpace' => 'pre-wrap', 'fallbackFont' => 'monospace']); $text = 'This is a paragraph. It should be long enough to show the effects of indentation on both the right and left sides.'; $section1 = $phpWord->addSection(); $section1->addText($text, 'style1', $pstyle1); diff --git a/tests/PhpWordTests/Writer/HTML/StyleTest.php b/tests/PhpWordTests/Writer/HTML/StyleTest.php index 0a6d15d3f6..f11fd3652d 100644 --- a/tests/PhpWordTests/Writer/HTML/StyleTest.php +++ b/tests/PhpWordTests/Writer/HTML/StyleTest.php @@ -30,7 +30,7 @@ class StyleTest extends \PHPUnit\Framework\TestCase */ public function testEmptyStyles(): void { - $styles = ['Font', 'Paragraph', 'Image']; + $styles = ['Font', 'Paragraph', 'Image', 'Table']; foreach ($styles as $style) { $objectClass = 'PhpOffice\\PhpWord\\Writer\\HTML\\Style\\' . $style; $object = new $objectClass(); @@ -38,142 +38,4 @@ public function testEmptyStyles(): void self::assertEquals('', $object->write()); } } - - /** - * Tests writing table with border styles. - */ - public function testWriteTableBorders(): void - { - $phpWord = new PhpWord(); - $section = $phpWord->addSection(); - - $bsnone = ['borderStyle' => 'none']; - $table1 = $section->addTable($bsnone); - $row1 = $table1->addRow(); - $row1->addCell(null, $bsnone)->addText('Row 1 Cell 1'); - $row1->addCell(null, $bsnone)->addText('Row 1 Cell 2'); - $row2 = $table1->addRow(); - $row2->addCell(null, $bsnone)->addText('Row 2 Cell 1'); - $row2->addCell(null, $bsnone)->addText('Row 2 Cell 2'); - - $table1 = $section->addTable(); - $row1 = $table1->addRow(); - $row1->addCell()->addText('Row 1 Cell 1'); - $row1->addCell()->addText('Row 1 Cell 2'); - $row2 = $table1->addRow(); - $row2->addCell()->addText('Row 2 Cell 1'); - $row2->addCell()->addText('Row 2 Cell 2'); - - $bstyle = ['borderStyle' => 'dashed', 'borderColor' => 'red']; - $table1 = $section->addTable($bstyle); - $row1 = $table1->addRow(); - $row1->addCell(null, $bstyle)->addText('Row 1 Cell 1'); - $row1->addCell(null, $bstyle)->addText('Row 1 Cell 2'); - $row2 = $table1->addRow(); - $row2->addCell(null, $bstyle)->addText('Row 2 Cell 1'); - $row2->addCell(null, $bstyle)->addText('Row 2 Cell 2'); - - $bstyle = [ - 'borderTopStyle' => 'dotted', - 'borderLeftStyle' => 'dashed', - 'borderRightStyle' => 'dashed', - 'borderBottomStyle' => 'dotted', - 'borderTopColor' => 'blue', - 'borderLeftColor' => 'green', - 'borderRightColor' => 'green', - 'borderBottomColor' => 'blue', - ]; - $table1 = $section->addTable($bstyle); - $row1 = $table1->addRow(); - $row1->addCell(null, $bstyle)->addText('Row 1 Cell 1'); - $row1->addCell(null, $bstyle)->addText('Row 1 Cell 2'); - $row2 = $table1->addRow(); - $row2->addCell(null, $bstyle)->addText('Row 2 Cell 1'); - $row2->addCell(null, $bstyle)->addText('Row 2 Cell 2'); - - $bstyle = ['borderStyle' => 'solid', 'borderSize' => 5]; - $table1 = $section->addTable($bstyle); - $row1 = $table1->addRow(); - $row1->addCell(null, $bstyle)->addText('Row 1 Cell 1'); - $row1->addCell(null, $bstyle)->addText('Row 1 Cell 2'); - $row2 = $table1->addRow(); - $row2->addCell(null, $bstyle)->addText('Row 2 Cell 1'); - $row2->addCell(null, $bstyle)->addText('Row 2 Cell 2'); - - $phpWord->addTableStyle('tstyle', ['borderStyle' => 'solid', 'borderSize' => 5]); - $table1 = $section->addTable('tstyle'); - $row1 = $table1->addRow(); - $row1->addCell(null, 'tstyle')->addText('Row 1 Cell 1'); - $row1->addCell(null, 'tstyle')->addText('Row 1 Cell 2'); - $row2 = $table1->addRow(); - $row2->addCell(null, 'tstyle')->addText('Row 2 Cell 1'); - $row2->addCell(null, 'tstyle')->addText('Row 2 Cell 2'); - - $dom = Helper::getAsHTML($phpWord); - $xpath = new DOMXPath($dom); - - $cssnone = ' border-top-style: none;' - . ' border-left-style: none; ' - . 'border-bottom-style: none; ' - . 'border-right-style: none;'; - self::assertEquals("table-layout: auto;$cssnone", Helper::getTextContent($xpath, '/html/body/div/table[1]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[1]/tr[1]/td[1]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[1]/tr[1]/td[2]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[1]/tr[2]/td[1]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[1]/tr[2]/td[2]', 'style')); - - self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/table[2]', 'style')); - self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/table[2]/tr[1]/td[1]', 'style')); - self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/table[2]/tr[1]/td[2]', 'style')); - self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/table[2]/tr[2]/td[1]', 'style')); - self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/table[2]/tr[2]/td[2]', 'style')); - - $cssnone = ' border-top-style: dashed;' - . ' border-top-color: red;' - . ' border-left-style: dashed;' - . ' border-left-color: red;' - . ' border-bottom-style: dashed;' - . ' border-bottom-color: red;' - . ' border-right-style: dashed;' - . ' border-right-color: red;'; - self::assertEquals("table-layout: auto;$cssnone", Helper::getTextContent($xpath, '/html/body/div/table[3]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[3]/tr[1]/td[1]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[3]/tr[1]/td[2]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[3]/tr[2]/td[1]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[3]/tr[2]/td[2]', 'style')); - - $cssnone = ' border-top-style: dotted;' - . ' border-top-color: blue;' - . ' border-left-style: dashed;' - . ' border-left-color: green;' - . ' border-bottom-style: dotted;' - . ' border-bottom-color: blue;' - . ' border-right-style: dashed;' - . ' border-right-color: green;'; - self::assertEquals("table-layout: auto;$cssnone", Helper::getTextContent($xpath, '/html/body/div/table[4]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[4]/tr[1]/td[1]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[4]/tr[1]/td[2]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[4]/tr[2]/td[1]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[4]/tr[2]/td[2]', 'style')); - - $cssnone = ' border-top-style: solid;' - . ' border-top-width: 0.25pt;' - . ' border-left-style: solid;' - . ' border-left-width: 0.25pt;' - . ' border-bottom-style: solid;' - . ' border-bottom-width: 0.25pt;' - . ' border-right-style: solid;' - . ' border-right-width: 0.25pt;'; - self::assertEquals("table-layout: auto;$cssnone", Helper::getTextContent($xpath, '/html/body/div/table[5]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[5]/tr[1]/td[1]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[5]/tr[1]/td[2]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[5]/tr[2]/td[1]', 'style')); - self::assertEquals($cssnone, Helper::getTextContent($xpath, '/html/body/div/table[5]/tr[2]/td[2]', 'style')); - - self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/table[6]', 'style')); - self::assertEquals('tstyle', Helper::getTextContent($xpath, '/html/body/div/table[6]', 'class')); - $style = Helper::getTextContent($xpath, '/html/head/style'); - self::assertNotFalse(preg_match('/^[.]tstyle[^\\r\\n]*/m', $style, $matches)); - self::assertEquals(".tstyle {table-layout: auto;$cssnone}", $matches[0]); - } } diff --git a/tests/PhpWordTests/Writer/HTMLTest.php b/tests/PhpWordTests/Writer/HTMLTest.php index 8303570e92..58cfb00161 100644 --- a/tests/PhpWordTests/Writer/HTMLTest.php +++ b/tests/PhpWordTests/Writer/HTMLTest.php @@ -37,7 +37,7 @@ public function testConstruct(): void { $object = new HTML(new PhpWord()); - self::assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $object->getPhpWord()); + self::assertInstanceOf(PhpWord::class, $object->getPhpWord()); } /** @@ -51,6 +51,39 @@ public function testConstructWithNull(): void $object->getPhpWord(); } + public function testEditCallback(): void + { + $object = new HTML(new PhpWord()); + + self::assertNull($object->getEditCallback()); + self::assertInstanceOf(HTML::class, $object->setEditCallback(function(string $html): string {return $html;})); + self::assertIsCallable($object->getEditCallback()); + self::assertInstanceOf(HTML::class, $object->setEditCallback(null)); + self::assertNull($object->getEditCallback()); + } + + public function testDefaultGenericFont(): void + { + $object = new HTML(new PhpWord()); + + self::assertEquals('', $object->getDefaultGenericFont()); + self::assertInstanceOf(HTML::class, $object->setDefaultGenericFont('test')); + self::assertEquals('', $object->getDefaultGenericFont()); + self::assertInstanceOf(HTML::class, $object->setDefaultGenericFont('cursive')); + self::assertEquals('cursive', $object->getDefaultGenericFont()); + } + + public function testDefaultWhiteSpace(): void + { + $object = new HTML(new PhpWord()); + + self::assertEquals('', $object->getDefaultWhiteSpace()); + self::assertInstanceOf(HTML::class, $object->setDefaultWhiteSpace('test')); + self::assertEquals('', $object->getDefaultWhiteSpace()); + self::assertInstanceOf(HTML::class, $object->setDefaultWhiteSpace('pre-line')); + self::assertEquals('pre-line', $object->getDefaultWhiteSpace()); + } + /** * Save. */ diff --git a/tests/PhpWordTests/Writer/PDF/MPDFTest.php b/tests/PhpWordTests/Writer/PDF/MPDFTest.php index 9dbbf9d5ac..0fe53456ba 100644 --- a/tests/PhpWordTests/Writer/PDF/MPDFTest.php +++ b/tests/PhpWordTests/Writer/PDF/MPDFTest.php @@ -47,9 +47,6 @@ public function testConstruct(): void $section->addText('Section 2 - landscape'); $writer = new MPDF($phpWord); - /** @var callable */ - $callback = [self::class, 'editContent']; - $writer->setEditHtmlCallback($callback); $writer->save($file); self::assertFileExists($file); @@ -57,23 +54,33 @@ public function testConstruct(): void unlink($file); } - /** - * Test set/get abstract renderer options. - */ - public function testSetGetAbstractRendererOptions(): void + public function testEditCallback(): void { - $rendererName = Settings::PDF_RENDERER_MPDF; - $rendererLibraryPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/mpdf/mpdf'); - Settings::setPdfRenderer($rendererName, (string) $rendererLibraryPath); - Settings::setPdfRendererOptions([ - 'font' => 'Arial', - ]); - $writer = new PDF(new PhpWord()); - self::assertEquals('Arial', $writer->getFont()); + $file = __DIR__ . '/../../_files/mpdf.pdf'; + + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $section->addText('Test 1'); + $section->addPageBreak(); + $section->addText('Test 2'); + $oSettings = new \PhpOffice\PhpWord\Style\Section(); + $oSettings->setSettingValue('orientation', 'landscape'); + $section = $phpWord->addSection($oSettings); // @phpstan-ignore-line + $section->addText('Section 2 - landscape'); + + $writer = new MPDF($phpWord); + /** @var callable */ + $callback = [self::class, 'cbEditContent']; + $writer->setEditCallback($callback); + $writer->save($file); + + self::assertFileExists($file); + + unlink($file); } // add a footer - public static function editContent(string $html): string + public static function cbEditContent(string $html): string { $afterBody = '
{PAGENO}
' . MPDF::SIMULATED_BODY_START; $beforeBody = ''; @@ -90,4 +97,19 @@ public static function editContent(string $html): string return $html; } + + /** + * Test set/get abstract renderer options. + */ + public function testSetGetAbstractRendererOptions(): void + { + $rendererName = Settings::PDF_RENDERER_MPDF; + $rendererLibraryPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/mpdf/mpdf'); + Settings::setPdfRenderer($rendererName, $rendererLibraryPath); + Settings::setPdfRendererOptions([ + 'font' => 'Arial', + ]); + $writer = new PDF(new PhpWord()); + self::assertEquals('Arial', $writer->getFont()); + } } diff --git a/tests/PhpWordTests/Writer/PDFTest.php b/tests/PhpWordTests/Writer/PDFTest.php index 5a2883feed..fc4064a23f 100644 --- a/tests/PhpWordTests/Writer/PDFTest.php +++ b/tests/PhpWordTests/Writer/PDFTest.php @@ -38,7 +38,7 @@ public function testConstruct(): void $rendererName = Settings::PDF_RENDERER_DOMPDF; $rendererLibraryPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/dompdf/dompdf'); - Settings::setPdfRenderer($rendererName, (string) $rendererLibraryPath); + Settings::setPdfRenderer($rendererName, $rendererLibraryPath); $writer = new PDF(new PhpWord()); $writer->save($file); diff --git a/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php b/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php index c87379678d..537fb93d1a 100644 --- a/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php @@ -31,7 +31,7 @@ class TOCTest extends \PHPUnit\Framework\TestCase */ protected function tearDown(): void { - //TestHelperDOCX::clear(); + TestHelperDOCX::clear(); } public function testWriteTitlePageNumber(): void