From 04b224caa5b5dca5b75fdf6f84649f0786812eee Mon Sep 17 00:00:00 2001 From: rikvdlooi Date: Wed, 15 Apr 2020 22:34:19 +0200 Subject: [PATCH 001/246] Fixed setting width of Cell Style The setWidth method did not change the width in the style, seems to be a small mistake. Now the width is correctly for the Cell Style. --- src/PhpWord/Style/Cell.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index 1276b5b59a..8c329ab310 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -299,7 +299,7 @@ public function getWidth() */ public function setWidth($value) { - $this->setIntVal($value); + $this->width = $this->setIntVal($value); return $this; } From 5bd4ad39a55e35c380d28ead00a6afcd349a3514 Mon Sep 17 00:00:00 2001 From: brammeleman <43443291+brammeleman@users.noreply.github.com> Date: Tue, 29 Jun 2021 11:57:41 +0200 Subject: [PATCH 002/246] fixed code example classes not found and missing dollar sign --- docs/general.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/general.rst b/docs/general.rst index 0d08739729..145df162ab 100644 --- a/docs/general.rst +++ b/docs/general.rst @@ -192,11 +192,11 @@ You can also specify the status of the spell and grammar checks, marking spellin .. code-block:: php - $proofState = new ProofState(); - $proofState->setGrammar(ProofState::CLEAN); - $proofState->setSpelling(ProofState::DIRTY); + $proofState = new \PhpOffice\PhpWord\ComplexType\ProofState(); + $proofState->setGrammar(\PhpOffice\PhpWord\ComplexType\ProofState::CLEAN); + $proofState->setSpelling(\PhpOffice\PhpWord\ComplexType\ProofState::DIRTY); - $phpWord->getSettings()->setProofState(proofState); + $phpWord->getSettings()->setProofState($proofState); Track Revisions ~~~~~~~~~~~~~~~ From d9c1daa89cfc34f416926bfcd9df48634aa3510d Mon Sep 17 00:00:00 2001 From: Amgad Naiem Date: Mon, 6 Dec 2021 22:39:26 +0200 Subject: [PATCH 003/246] Added Swedish language --- src/PhpWord/Style/Language.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index 7b2de51e07..3f3c2901f9 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -67,6 +67,9 @@ final class Language extends AbstractStyle const NL_NL = 'nl-NL'; const NL_NL_ID = 1043; + + const SV_SE = 'sv-SE'; + const SV_SE_ID = 1053; const UK_UA = 'uk-UA'; const UK_UA_ID = 1058; From e9cd17d4c7bc0ab4df09e858284369dbf7a98fff Mon Sep 17 00:00:00 2001 From: Maarten de Keizer Date: Tue, 4 Jan 2022 10:22:38 +0100 Subject: [PATCH 004/246] Add destructor wich will try to clean up temp file of the template processor --- src/PhpWord/TemplateProcessor.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 3f7770d3d7..efabe4237c 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -132,6 +132,14 @@ public function __construct($documentTemplate) $this->tempDocumentContentTypes = $this->zipClass->getFromName($this->getDocumentContentTypesName()); } + public function __destruct() + { + // if the temp file still exists, remove it when running destruct + if ($this->tempDocumentFilename && file_exists($this->tempDocumentFilename) && is_writable($this->tempDocumentFilename)) { + @unlink($this->tempDocumentFilename); + } + } + /** * Expose zip class * From e159b723bde376a1385638b7e3bed0305ba154f1 Mon Sep 17 00:00:00 2001 From: Tobias van Beek Date: Tue, 4 Jan 2022 14:02:52 +0100 Subject: [PATCH 005/246] Update homepage in composer.json I found out that the homepage link on packagist.org points to: http://phpoffice.github.io/ but that site doesn't exist. So this PR updates the link to the documentation site. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e588ef7bd1..e315bad31c 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "docx", "OOXML", "OpenXML", "Office Open XML", "ISO IEC 29500", "WordprocessingML", "RTF", "Rich Text Format", "doc", "odt", "ODF", "OpenDocument", "PDF", "HTML" ], - "homepage": "http://phpoffice.github.io/", + "homepage": "https://phpword.readthedocs.io/", "type": "library", "license": "LGPL-3.0", "authors": [ From c57c2929155f19833c75bafddbe93e82597036fc Mon Sep 17 00:00:00 2001 From: Gareth Ellis Date: Tue, 8 Feb 2022 12:40:06 +0000 Subject: [PATCH 006/246] #2187 Addresses deprecation on PHP 8.1 in ZipArchi --- src/PhpWord/Shared/ZipArchive.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/PhpWord/Shared/ZipArchive.php b/src/PhpWord/Shared/ZipArchive.php index bc71e74b17..6517ca8abf 100644 --- a/src/PhpWord/Shared/ZipArchive.php +++ b/src/PhpWord/Shared/ZipArchive.php @@ -133,6 +133,13 @@ public function open($filename, $flags = null) if (!$this->usePclzip) { $zip = new \ZipArchive(); + + // PHP 8.1 compat - passing null as second arg to \ZipArchive::open() is deprecated + // passing 0 achieves the same behaviour + if ($flags === null) { + $flags = 0; + } + $result = $zip->open($this->filename, $flags); // Scrutizer will report the property numFiles does not exist From 3bcd4b5370d6ae1b5c0822ba385294ca25263fc0 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Thu, 17 Feb 2022 16:37:24 +0100 Subject: [PATCH 007/246] PHP 8.1 compatibility --- src/PhpWord/TemplateProcessor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 3f7770d3d7..664d46887e 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -438,7 +438,7 @@ private function chooseImageDimension($baseValue, $inlineValue, $defaultValue) if (is_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', isset($value) ? $value : '')) { $value = null; } if (is_null($value)) { From be0190cd5d8f95b4be08d5853b107aa4e352759a Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Thu, 17 Feb 2022 16:40:03 +0100 Subject: [PATCH 008/246] 0.18.3 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9b4ec0af0..6e140f555b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [0.18.3](https://github.com/PHPOffice/PHPWord/tree/0.18.3) (2022-02-17) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.18.2...0.18.3) + +### Bug fixes +- PHP 8.1 compatibility + ## [0.18.2](https://github.com/PHPOffice/PHPWord/tree/0.18.2) (2021-06-04) [Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.18.1...0.18.2) From 2bba013311bdb3e728d3facc807b77e02561d894 Mon Sep 17 00:00:00 2001 From: Michael Als Date: Tue, 29 Mar 2022 13:13:45 +0000 Subject: [PATCH 009/246] PHP 8.1 compatability fix for PreserveText --- src/PhpWord/Element/PreserveText.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Element/PreserveText.php b/src/PhpWord/Element/PreserveText.php index c0e64268ba..803ee4f395 100644 --- a/src/PhpWord/Element/PreserveText.php +++ b/src/PhpWord/Element/PreserveText.php @@ -60,7 +60,7 @@ public function __construct($text = null, $fontStyle = null, $paragraphStyle = n $this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle); $this->text = SharedText::toUTF8($text); - $matches = preg_split('/({.*?})/', $this->text, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + $matches = preg_split('/({.*?})/', $this->text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); if (isset($matches[0])) { $this->text = $matches; } From 6b331603e6a56781e04fb5c35a1b0aadcf58fe52 Mon Sep 17 00:00:00 2001 From: Michael Als Date: Wed, 30 Mar 2022 12:42:45 +0000 Subject: [PATCH 010/246] Added return type will change to XMLWriter.php --- src/PhpWord/Shared/XMLWriter.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PhpWord/Shared/XMLWriter.php b/src/PhpWord/Shared/XMLWriter.php index 930ad62ee1..882492e00f 100644 --- a/src/PhpWord/Shared/XMLWriter.php +++ b/src/PhpWord/Shared/XMLWriter.php @@ -171,6 +171,7 @@ public function writeAttributeIf($condition, $attribute, $value) * @param mixed $value * @return bool */ + #[\ReturnTypeWillChange] public function writeAttribute($name, $value) { if (is_float($value)) { From fc18246b206374ce81d0289c76bba67c6f327ff8 Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Wed, 8 Jun 2022 14:14:25 +0200 Subject: [PATCH 011/246] PreserveText preg_split fix third parameter must be -1 not null (php 8.1 deprecate warning) --- src/PhpWord/Element/PreserveText.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Element/PreserveText.php b/src/PhpWord/Element/PreserveText.php index c0e64268ba..803ee4f395 100644 --- a/src/PhpWord/Element/PreserveText.php +++ b/src/PhpWord/Element/PreserveText.php @@ -60,7 +60,7 @@ public function __construct($text = null, $fontStyle = null, $paragraphStyle = n $this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle); $this->text = SharedText::toUTF8($text); - $matches = preg_split('/({.*?})/', $this->text, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + $matches = preg_split('/({.*?})/', $this->text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); if (isset($matches[0])) { $this->text = $matches; } From 91416e48ac4bf320fb4c0949ed238d80e94ee41c Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Wed, 8 Jun 2022 14:22:51 +0200 Subject: [PATCH 012/246] XMLWriter ReturnTypeWillChange fix add #[\ReturnTypeWillChange] Attribute to the function writeAttribute (php 8.1 deprecate warning) --- src/PhpWord/Shared/XMLWriter.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PhpWord/Shared/XMLWriter.php b/src/PhpWord/Shared/XMLWriter.php index 930ad62ee1..dbe0db1dfa 100644 --- a/src/PhpWord/Shared/XMLWriter.php +++ b/src/PhpWord/Shared/XMLWriter.php @@ -171,6 +171,7 @@ public function writeAttributeIf($condition, $attribute, $value) * @param mixed $value * @return bool */ + #[\ReturnTypeWillChange] public function writeAttribute($name, $value) { if (is_float($value)) { From 945cbd9b93c67d094735218a41a86a46721a7170 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 20 Jul 2022 14:04:04 +0200 Subject: [PATCH 013/246] HTML Reader : Heading in Text Run is not allowed --- src/PhpWord/Shared/Html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index a2ea946524..5739ec5539 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -440,7 +440,7 @@ protected static function parseCell($node, $element, &$styles) */ protected static function shouldAddTextRun(\DOMNode $node) { - $containsBlockElement = self::$xpath->query('.//table|./p|./ul|./ol', $node)->length > 0; + $containsBlockElement = self::$xpath->query('.//table|./p|./ul|./ol|./h1|./h2|./h3|./h4|./h5|./h6', $node)->length > 0; if ($containsBlockElement) { return false; } From 2f93873a7c16befb5d79a3e8b1658533b3e54726 Mon Sep 17 00:00:00 2001 From: Seamus Lee Date: Sat, 30 Jul 2022 07:28:01 +0000 Subject: [PATCH 014/246] PHP8.1 Fix issue with passing NULL value for locale into string function --- src/PhpWord/Style/Language.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index 7b2de51e07..7f3dbec767 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -232,7 +232,7 @@ private function validateLocale($locale) $locale = str_replace('_', '-', $locale); } - if (strlen($locale) === 2) { + if ($locale !== null && strlen($locale) === 2) { return strtolower($locale) . '-' . strtoupper($locale); } From 26757c29bb8e3778ed2d901615a294faf6457bd4 Mon Sep 17 00:00:00 2001 From: amir Date: Fri, 12 Aug 2022 14:38:49 +0400 Subject: [PATCH 015/246] Add softhyphen support to word reader --- src/PhpWord/Reader/Word2007/AbstractPart.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 729c0b95b0..0d8a7e1731 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -327,6 +327,8 @@ protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, Abstrac $element->setChangeInfo($type, $author, $date); } } + } elseif ($node->nodeName=='w:softHyphen') { + $element=$parent->addText("\u{200c}", $fontStyle, $paragraphStyle); } } From 2de551647bf075361a657a94332a8bc0dbadd056 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Tue, 6 Sep 2022 21:58:16 +0200 Subject: [PATCH 016/246] HTML Reader : Style page-break-after in paragraph --- src/PhpWord/Shared/Html.php | 13 ++++++++++--- tests/PhpWord/Shared/HtmlTest.php | 16 +++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index a2ea946524..63a0a113b2 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -257,14 +257,16 @@ protected static function parseChildNodes($node, $element, $styles, $data) * @param \DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element * @param array &$styles - * @return \PhpOffice\PhpWord\Element\TextRun + * @return \PhpOffice\PhpWord\Element\TextRun|\PhpOffice\PhpWord\Element\PageBreak */ protected static function parseParagraph($node, $element, &$styles) { $styles['paragraph'] = self::recursiveParseStylesInHierarchy($node, $styles['paragraph']); - $newElement = $element->addTextRun($styles['paragraph']); + if (isset($styles['paragraph']['isPageBreak']) && $styles['paragraph']['isPageBreak']) { + return $element->addPageBreak(); + } - return $newElement; + return $element->addTextRun($styles['paragraph']); } /** @@ -771,6 +773,11 @@ protected static function parseStyle($attribute, $styles) $styles['valign'] = self::mapAlignVertical($matches[0]); } break; + case 'page-break-after': + if ($cValue == 'always') { + $styles['isPageBreak'] = true; + } + break; } } diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 80f96d5773..eecec002dc 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -291,6 +291,20 @@ public function testParseParagraphAndSpanStyle() $this->assertEquals('single', $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:r/w:rPr/w:u', 'w:val')); } + /** + * Test parsing paragraph with `page-break-after` style + */ + public function testParseParagraphWithPageBreak() + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + Html::addHtml($section, '

'); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:br')); + $this->assertEquals('page', $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:br', 'w:type')); + } + /** * Test parsing table */ @@ -776,7 +790,7 @@ public function testParseCellspacingRowBgColor() /** * Parse horizontal rule */ - public function testParseHorizRule() + public function testParseHorizontalRule() { $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); From 83b0bef3a891e2304f9fe4cc832d3e5705b6fe31 Mon Sep 17 00:00:00 2001 From: neopheus Date: Mon, 12 Sep 2022 12:56:45 +0200 Subject: [PATCH 017/246] Fix #2290 --- src/PhpWord/TemplateProcessor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 664d46887e..14c95b18d6 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -257,7 +257,7 @@ protected static function ensureMacroCompleted($macro) */ protected static function ensureUtf8Encoded($subject) { - if (!Text::isUTF8($subject)) { + if (!Text::isUTF8($subject) && !is_null($subject)) { $subject = utf8_encode($subject); } From 077175efbef67fbaef1e3145b7d544e1b2c17893 Mon Sep 17 00:00:00 2001 From: neopheus Date: Mon, 12 Sep 2022 13:48:13 +0200 Subject: [PATCH 018/246] Fix : htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated --- src/PhpWord/Escaper/Xml.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Escaper/Xml.php b/src/PhpWord/Escaper/Xml.php index a769c5e189..073e297d2c 100644 --- a/src/PhpWord/Escaper/Xml.php +++ b/src/PhpWord/Escaper/Xml.php @@ -27,6 +27,6 @@ class Xml extends AbstractEscaper protected function escapeSingleValue($input) { // todo: omit encoding parameter after migration onto PHP 5.4 - return htmlspecialchars($input, ENT_QUOTES, 'UTF-8'); + return (!is_null($input)) ? htmlspecialchars($input, ENT_QUOTES, 'UTF-8') : null; } } From fa84160f7f55a6e28c24cb5b8769518383c09c47 Mon Sep 17 00:00:00 2001 From: neopheus Date: Mon, 12 Sep 2022 13:59:21 +0200 Subject: [PATCH 019/246] str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated" --- src/PhpWord/Escaper/Xml.php | 2 +- src/PhpWord/TemplateProcessor.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/Escaper/Xml.php b/src/PhpWord/Escaper/Xml.php index 073e297d2c..316ee85e63 100644 --- a/src/PhpWord/Escaper/Xml.php +++ b/src/PhpWord/Escaper/Xml.php @@ -27,6 +27,6 @@ class Xml extends AbstractEscaper protected function escapeSingleValue($input) { // todo: omit encoding parameter after migration onto PHP 5.4 - return (!is_null($input)) ? htmlspecialchars($input, ENT_QUOTES, 'UTF-8') : null; + return (!is_null($input)) ? htmlspecialchars($input, ENT_QUOTES, 'UTF-8') : ''; } } diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 14c95b18d6..09f5461995 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -261,7 +261,7 @@ protected static function ensureUtf8Encoded($subject) $subject = utf8_encode($subject); } - return $subject; + return (!is_null($subject)) ? $subject : ''; } /** From a4cdcd625006f49097ad9a6904f9ebeaa8c7956b Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 14 Sep 2022 17:50:54 +0200 Subject: [PATCH 020/246] HTML Reader : Use `border` attribute for tables --- src/PhpWord/Shared/Html.php | 16 +++++----------- tests/PhpWord/Shared/HtmlTest.php | 29 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 3b8d587fdc..f57fb0a955 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -372,17 +372,11 @@ protected static function parseTable($node, $element, &$styles) $newElement = $element->addTable($elementStyles); - // $attributes = $node->attributes; - // if ($attributes->getNamedItem('width') !== null) { - // $newElement->setWidth($attributes->getNamedItem('width')->value); - // } - - // if ($attributes->getNamedItem('height') !== null) { - // $newElement->setHeight($attributes->getNamedItem('height')->value); - // } - // if ($attributes->getNamedItem('width') !== null) { - // $newElement=$element->addCell($width=$attributes->getNamedItem('width')->value); - // } + $attributes = $node->attributes; + if ($attributes->getNamedItem('border') !== null) { + $border = (int) $attributes->getNamedItem('border')->value; + $newElement->getStyle()->setBorderSize(Converter::pixelToTwip($border)); + } return $newElement; } diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index eecec002dc..fdf3e37c3c 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -351,6 +351,35 @@ public function testParseTable() $this->assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc[2]/w:p/w:pPr/w:pBdr')); } + /** + * Test parsing table (attribute border) + */ + public function testParseTableAttributeBorder() + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $html = ' + + + + + + + + + +
Header
Cell 1
Cell 2
'; + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:tbl')); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tblPr')); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tblPr/w:tblBorders')); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tblPr/w:tblBorders/w:top')); + // 10 pixels = 150 twips + $this->assertEquals(150, $doc->getElementAttribute('/w:document/w:body/w:tbl/w:tblPr/w:tblBorders/w:top', 'w:sz')); + } + /** * Tests parsing of ul/li */ From 26532b5f3ffb27ef337ca176abc30ec63500510c Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Thu, 15 Sep 2022 17:45:46 +0200 Subject: [PATCH 021/246] Test PHP 8.1 --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d8bc57c2a1..f25e761c45 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,7 @@ jobs: - "7.3" - "7.4" - "8.0" + - "8.1" name: PHP ${{ matrix.php-version }} From 54415c113bab0fe2445d8b6ec4f90a8d6907e3bf Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Thu, 15 Sep 2022 17:55:24 +0200 Subject: [PATCH 022/246] Fix code style --- src/PhpWord/Shared/XMLWriter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Shared/XMLWriter.php b/src/PhpWord/Shared/XMLWriter.php index dbe0db1dfa..882492e00f 100644 --- a/src/PhpWord/Shared/XMLWriter.php +++ b/src/PhpWord/Shared/XMLWriter.php @@ -171,7 +171,7 @@ public function writeAttributeIf($condition, $attribute, $value) * @param mixed $value * @return bool */ - #[\ReturnTypeWillChange] + #[\ReturnTypeWillChange] public function writeAttribute($name, $value) { if (is_float($value)) { From 301e481fbe1acb04b5253adf1a8ecee948e3bc60 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Thu, 15 Sep 2022 19:07:28 +0200 Subject: [PATCH 023/246] loadConfig returns config that was actually applied --- src/PhpWord/Settings.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/Settings.php b/src/PhpWord/Settings.php index 80e512d2a7..7966331776 100644 --- a/src/PhpWord/Settings.php +++ b/src/PhpWord/Settings.php @@ -424,19 +424,21 @@ public static function loadConfig($filename = null) if ($configFile !== null) { $config = @parse_ini_file($configFile); if ($config === false) { - return $config; + return array(); } } // Set config value + $appliedConfig = array(); foreach ($config as $key => $value) { $method = "set{$key}"; if (method_exists(__CLASS__, $method)) { self::$method($value); + $appliedConfig[$key] = $value; } } - return $config; + return $appliedConfig; } /** From ecee8339c37200fd68d1d027aac74efb27a603b0 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Thu, 15 Sep 2022 19:10:04 +0200 Subject: [PATCH 024/246] Don't use teamcity format in CI It's much harder to read for human --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f25e761c45..e292c5039e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,7 +73,7 @@ jobs: uses: mheap/phpunit-matcher-action@v1 - name: Test with PHPUnit - run: ./vendor/bin/phpunit --teamcity --no-coverage -c ./ + run: ./vendor/bin/phpunit --no-coverage php-cs-fixer: runs-on: ubuntu-latest From f853b9f12586cfe6422ec72a8223a37bb64cceff Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Thu, 15 Sep 2022 21:43:36 +0200 Subject: [PATCH 025/246] Tolerate small imprecisions --- tests/PhpWord/Shared/ConverterTest.php | 40 +++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/PhpWord/Shared/ConverterTest.php b/tests/PhpWord/Shared/ConverterTest.php index 668837742b..82bcaf845e 100644 --- a/tests/PhpWord/Shared/ConverterTest.php +++ b/tests/PhpWord/Shared/ConverterTest.php @@ -36,70 +36,70 @@ public function testUnitConversions() foreach ($values as $value) { $result = Converter::cmToTwip($value); - $this->assertEquals($value / 2.54 * 1440, $result); + $this->assertEquals($value / 2.54 * 1440, $result, '', 0.00001); $result = Converter::cmToInch($value); - $this->assertEquals($value / 2.54, $result); + $this->assertEquals($value / 2.54, $result, '', 0.00001); $result = Converter::cmToPixel($value); - $this->assertEquals($value / 2.54 * 96, $result); + $this->assertEquals($value / 2.54 * 96, $result, '', 0.00001); $result = Converter::cmToPoint($value); - $this->assertEquals($value / 2.54 * 72, $result); + $this->assertEquals($value / 2.54 * 72, $result, '', 0.00001); $result = Converter::cmToEmu($value); - $this->assertEquals(round($value / 2.54 * 96 * 9525), $result); + $this->assertEquals(round($value / 2.54 * 96 * 9525), $result, '', 0.00001); $result = Converter::inchToTwip($value); - $this->assertEquals($value * 1440, $result); + $this->assertEquals($value * 1440, $result, '', 0.00001); $result = Converter::inchToCm($value); - $this->assertEquals($value * 2.54, $result); + $this->assertEquals($value * 2.54, $result, '', 0.00001); $result = Converter::inchToPixel($value); - $this->assertEquals($value * 96, $result); + $this->assertEquals($value * 96, $result, '', 0.00001); $result = Converter::inchToPoint($value); - $this->assertEquals($value * 72, $result); + $this->assertEquals($value * 72, $result, '', 0.00001); $result = Converter::inchToEmu($value); - $this->assertEquals(round($value * 96 * 9525), $result); + $this->assertEquals(round($value * 96 * 9525), $result, '', 0.00001); $result = Converter::pixelToTwip($value); - $this->assertEquals($value / 96 * 1440, $result); + $this->assertEquals($value / 96 * 1440, $result, '', 0.00001); $result = Converter::pixelToCm($value); - $this->assertEquals($value / 96 * 2.54, $result); + $this->assertEquals($value / 96 * 2.54, $result, '', 0.00001); $result = Converter::pixelToPoint($value); - $this->assertEquals($value / 96 * 72, $result); + $this->assertEquals($value / 96 * 72, $result, '', 0.00001); $result = Converter::pixelToEmu($value); - $this->assertEquals(round($value * 9525), $result); + $this->assertEquals(round($value * 9525), $result, '', 0.00001); $result = Converter::pointToTwip($value); - $this->assertEquals($value * 20, $result); + $this->assertEquals($value * 20, $result, '', 0.00001); $result = Converter::pointToCm($value); $this->assertEquals($value * 0.035277778, $result, '', 0.00001); $result = Converter::pointToPixel($value); - $this->assertEquals($value / 72 * 96, $result); + $this->assertEquals($value / 72 * 96, $result, '', 0.00001); $result = Converter::pointToEmu($value); - $this->assertEquals(round($value / 72 * 96 * 9525), $result); + $this->assertEquals(round($value / 72 * 96 * 9525), $result, '', 0.00001); $result = Converter::emuToPixel($value); - $this->assertEquals(round($value / 9525), $result); + $this->assertEquals(round($value / 9525), $result, '', 0.00001); $result = Converter::picaToPoint($value); $this->assertEquals($value / 6 * 72, $result, '', 0.00001); $result = Converter::degreeToAngle($value); - $this->assertEquals((int) round($value * 60000), $result); + $this->assertEquals((int) round($value * 60000), $result, '', 0.00001); $result = Converter::angleToDegree($value); - $this->assertEquals(round($value / 60000), $result); + $this->assertEquals(round($value / 60000), $result, '', 0.00001); } } From 0e8bcb63e7f83efda40cc4f31b4c00d10a297e53 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 16 Sep 2022 10:17:31 +0200 Subject: [PATCH 026/246] Drop PHP 7.3 and older This is according to our formal, published, policy to only support eol PHP after 6 months within PHPOffice organisation. See https://phpspreadsheet.readthedocs.io/en/latest/#php-version-support --- .github/workflows/ci.yml | 2 - README.md | 4 +- composer.json | 7 ++-- docs/faq.rst | 16 -------- docs/installing.rst | 4 +- samples/index.php | 2 +- src/PhpWord/Element/Image.php | 22 +---------- src/PhpWord/Escaper/Xml.php | 3 +- src/PhpWord/Shared/PCLZip/pclzip.lib.php | 23 ----------- tests/PhpWord/Writer/PDF/TCPDFTest.php | 12 ------ .../AbstractWebServerEmbeddedTest.php | 38 +++---------------- 11 files changed, 17 insertions(+), 116 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e292c5039e..a8318e33f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,8 +8,6 @@ jobs: strategy: matrix: php-version: - - '7.2' - - "7.3" - "7.4" - "8.0" - "8.1" diff --git a/README.md b/README.md index c50ffc6efc..1e81c2b90b 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Read more about PHPWord: ## Features -With PHPWord, you can create OOXML, ODF, or RTF documents dynamically using your PHP 5.3.3+ scripts. Below are some of the things that you can do with PHPWord library: +With PHPWord, you can create OOXML, ODF, or RTF documents dynamically using your PHP scripts. Below are some of the things that you can do with PHPWord library: - Set document properties, e.g. title, subject, and creator. - Create document sections with different settings, e.g. portrait/landscape, page size, and page numbering @@ -60,7 +60,7 @@ With PHPWord, you can create OOXML, ODF, or RTF documents dynamically using your PHPWord requires the following: -- PHP 5.3.3+ +- PHP 7.4+ - [XML Parser extension](http://www.php.net/manual/en/xml.installation.php) - [Laminas Escaper component](https://docs.laminas.dev/laminas-escaper/intro/) - [Zip extension](http://php.net/manual/en/book.zip.php) (optional, used to write OOXML and ODF) diff --git a/composer.json b/composer.json index e588ef7bd1..4c212072fc 100644 --- a/composer.json +++ b/composer.json @@ -58,9 +58,10 @@ "fix": "Fixes issues found by PHP-CS" }, "require": { - "php": "^5.3.3 || ^7.0 || ^8.0", + "php": "^7.4 || ^8.0", "ext-xml": "*", - "laminas/laminas-escaper": "^2.2" + "laminas/laminas-escaper": "^2.2", + "symfony/process": "^5.4" }, "require-dev": { "ext-zip": "*", @@ -71,7 +72,7 @@ "phpmd/phpmd": "2.*", "phploc/phploc": "2.* || 3.* || 4.* || 5.* || 6.* || 7.*", "dompdf/dompdf":"0.8.* || 1.0.*", - "tecnickcom/tcpdf": "6.*", + "tecnickcom/tcpdf": "^6.4", "mpdf/mpdf": "5.7.4 || 6.* || 7.* || 8.*", "php-coveralls/php-coveralls": "1.1.0 || ^2.0" }, diff --git a/docs/faq.rst b/docs/faq.rst index 19fca1057f..451e1d7305 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -6,19 +6,3 @@ Frequently asked questions How contribute to PHPWord? -------------------------- - Improve the documentation (`Sphinx Format `__) - -Is this the same with PHPWord that I found in CodePlex? -------------------------------------------------------- - -No. This one is much better with tons of new features that you can’t -find in PHPWord 0.6.3. The development in CodePlex is halted and -switched to GitHub to allow more participation from the crowd. The more -the merrier, right? - -I’ve been running PHPWord from CodePlex flawlessly, but I can’t use the latest PHPWord from GitHub. Why? --------------------------------------------------------------------------------------------------------- - -PHPWord requires PHP 5.3+ since 0.8, while PHPWord 0.6.3 from CodePlex -can run with PHP 5.2. There’s a lot of new features that we can get from -PHP 5.3 and it’s been around since 2009! You should upgrade your PHP -version to use PHPWord 0.8+. diff --git a/docs/installing.rst b/docs/installing.rst index 7765aee88f..082c60bcad 100644 --- a/docs/installing.rst +++ b/docs/installing.rst @@ -8,9 +8,9 @@ Requirements Mandatory: -- PHP 5.3.3+ +- composer +- PHP 7.4+ - `XML Parser `__ extension -- `Laminas Escaper `__ component Optional: diff --git a/samples/index.php b/samples/index.php index 20b56b8317..d539cd620d 100644 --- a/samples/index.php +++ b/samples/index.php @@ -4,7 +4,7 @@ use PhpOffice\PhpWord\Settings; $requirements = array( - 'php' => array('PHP 5.3.3', version_compare(PHP_VERSION, '5.3.3', '>=')), + 'php' => array('PHP 7.4', version_compare(PHP_VERSION, '7.4', '>=')), 'xml' => array('PHP extension XML', extension_loaded('xml')), 'temp' => array('Temp folder "' . Settings::getTempDir() . '" is writable', is_writable(Settings::getTempDir())), 'zip' => array('PHP extension ZipArchive (optional)', extension_loaded('zip')), diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php index 2e25fd18e5..d53da182f5 100644 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -410,7 +410,7 @@ private function checkImage() if ($this->sourceType == self::SOURCE_ARCHIVE) { $imageData = $this->getArchiveImageSize($this->source); } elseif ($this->sourceType == self::SOURCE_STRING) { - $imageData = $this->getStringImageSize($this->source); + $imageData = @getimagesizefromstring($this->source); } else { $imageData = @getimagesize($this->source); } @@ -501,26 +501,6 @@ private function getArchiveImageSize($source) return $imageData; } - /** - * get image size from string - * - * @param string $source - * - * @codeCoverageIgnore this method is just a replacement for getimagesizefromstring which exists only as of PHP 5.4 - */ - private function getStringImageSize($source) - { - $result = false; - if (!function_exists('getimagesizefromstring')) { - $uri = 'data://application/octet-stream;base64,' . base64_encode($source); - $result = @getimagesize($uri); - } else { - $result = @getimagesizefromstring($source); - } - - return $result; - } - /** * Set image functions and extensions. */ diff --git a/src/PhpWord/Escaper/Xml.php b/src/PhpWord/Escaper/Xml.php index 316ee85e63..16ce2340cd 100644 --- a/src/PhpWord/Escaper/Xml.php +++ b/src/PhpWord/Escaper/Xml.php @@ -26,7 +26,6 @@ class Xml extends AbstractEscaper { protected function escapeSingleValue($input) { - // todo: omit encoding parameter after migration onto PHP 5.4 - return (!is_null($input)) ? htmlspecialchars($input, ENT_QUOTES, 'UTF-8') : ''; + return (!is_null($input)) ? htmlspecialchars($input, ENT_QUOTES) : ''; } } diff --git a/src/PhpWord/Shared/PCLZip/pclzip.lib.php b/src/PhpWord/Shared/PCLZip/pclzip.lib.php index 3fbc932744..62927497bb 100644 --- a/src/PhpWord/Shared/PCLZip/pclzip.lib.php +++ b/src/PhpWord/Shared/PCLZip/pclzip.lib.php @@ -3258,17 +3258,6 @@ public function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_rem $v_extract = true; } } - // ----- Look for extract by ereg rule - // ereg() is deprecated with PHP 5.3 - /* - elseif ( (isset($p_options[PCLZIP_OPT_BY_EREG])) - && ($p_options[PCLZIP_OPT_BY_EREG] != "")) { - - if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) { - $v_extract = true; - } - } - */ // ----- Look for extract by preg rule } elseif ((isset($p_options[PCLZIP_OPT_BY_PREG])) && ($p_options[PCLZIP_OPT_BY_PREG] != "")) { @@ -4545,18 +4534,6 @@ public function privDeleteByRule(&$p_result_list, &$p_options) } } - // ----- Look for extract by ereg rule - // ereg() is deprecated with PHP 5.3 - /* - elseif ( (isset($p_options[PCLZIP_OPT_BY_EREG])) - && ($p_options[PCLZIP_OPT_BY_EREG] != "")) { - - if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) { - $v_found = true; - } - } - */ - // ----- Look for extract by preg rule } elseif ((isset($p_options[PCLZIP_OPT_BY_PREG])) && ($p_options[PCLZIP_OPT_BY_PREG] != "")) { diff --git a/tests/PhpWord/Writer/PDF/TCPDFTest.php b/tests/PhpWord/Writer/PDF/TCPDFTest.php index 53e55ca0b6..6dc8f24cb7 100644 --- a/tests/PhpWord/Writer/PDF/TCPDFTest.php +++ b/tests/PhpWord/Writer/PDF/TCPDFTest.php @@ -33,18 +33,6 @@ class TCPDFTest extends \PHPUnit\Framework\TestCase */ public function testConstruct() { - // TCPDF version 6.3.5 doesn't support PHP 5.3, fixed via https://github.com/tecnickcom/TCPDF/pull/197, - // pending new release. - if (version_compare(PHP_VERSION, '5.4.0', '<')) { - return; - } - - // TCPDF version 6.3.5 doesn't support PHP 8.0, fixed via https://github.com/tecnickcom/TCPDF/pull/293, - // pending new release. - if (version_compare(PHP_VERSION, '8.0.0', '>=')) { - return; - } - $file = __DIR__ . '/../../_files/tcpdf.pdf'; $phpWord = new PhpWord(); diff --git a/tests/PhpWord/_includes/AbstractWebServerEmbeddedTest.php b/tests/PhpWord/_includes/AbstractWebServerEmbeddedTest.php index 25fe836ac1..bb010aa103 100644 --- a/tests/PhpWord/_includes/AbstractWebServerEmbeddedTest.php +++ b/tests/PhpWord/_includes/AbstractWebServerEmbeddedTest.php @@ -25,39 +25,18 @@ abstract class AbstractWebServerEmbeddedTest extends \PHPUnit\Framework\TestCase public static function setUpBeforeClass() { - if (self::isBuiltinServerSupported()) { - $commandLine = 'php -S localhost:8080 -t tests/PhpWord/_files'; + $commandLine = 'php -S localhost:8080 -t tests/PhpWord/_files'; - /* - * Make sure to invoke \Symfony\Component\Process\Process correctly - * regardless of PHP version used. - * - * In Process version >= 5 / PHP >= 7.2.5, the constructor requires - * an array, while in version < 3.3 / PHP < 5.5.9 it requires a string. - * In between, it can accept both. - * - * Process::fromShellCommandLine() was introduced in version 4.2.0, - * to enable recent versions of Process to parse a command string, - * so if it is not available it means it is still possible to pass - * a string to the constructor. - */ - if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandLine')) { - self::$httpServer = Process::fromShellCommandline($commandLine); - } else { - self::$httpServer = new Process($commandLine); - } - self::$httpServer->start(); - while (!self::$httpServer->isRunning()) { - usleep(1000); - } + self::$httpServer = Process::fromShellCommandline($commandLine); + self::$httpServer->start(); + while (!self::$httpServer->isRunning()) { + usleep(1000); } } public static function tearDownAfterClass() { - if (self::isBuiltinServerSupported()) { - self::$httpServer->stop(); - } + self::$httpServer->stop(); } protected static function getBaseUrl() @@ -91,9 +70,4 @@ protected static function getRemoteBmpImageUrl() return 'https://samples.libav.org/image-samples/RACECAR.BMP'; } - - private static function isBuiltinServerSupported() - { - return version_compare(PHP_VERSION, '5.4.0', '>='); - } } From 207438270fdd9fafcf96347ee495d519bc23e381 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 16 Sep 2022 10:19:51 +0200 Subject: [PATCH 027/246] Drop implicit code coverage Because not all PHP installs have code coverage enabled, and that makes testing more difficult, and slower than necessary. Instead, use local config if you need to always have code coverage. --- phpunit.xml.dist | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 4a8824468e..5e1d25bad6 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -20,9 +20,4 @@ - - - - - - \ No newline at end of file + From 25c56a3e2db957a745a592a4a5c3fb69366f85d7 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 16 Sep 2022 11:27:29 +0200 Subject: [PATCH 028/246] Update all PHP dependencies This way we can share the same dependencies across PHP 7.4 to PHP 8.1, and simplify our CI pipeline --- .github/workflows/ci.yml | 24 +-------- composer.json | 22 ++++---- src/PhpWord/Element/PreserveText.php | 2 +- src/PhpWord/Reader/MsDoc.php | 6 +-- src/PhpWord/Settings.php | 2 +- src/PhpWord/Shared/Html.php | 2 +- src/PhpWord/Shared/XMLWriter.php | 4 +- src/PhpWord/Writer/RTF/Element/Title.php | 2 +- src/PhpWord/Writer/RTF/Style/Paragraph.php | 4 +- .../ComplexType/FootnotePropertiesTest.php | 9 ++-- tests/PhpWord/ComplexType/ProofStateTest.php | 6 +-- tests/PhpWord/Element/CellTest.php | 8 ++- tests/PhpWord/Element/CommentTest.php | 10 ++-- tests/PhpWord/Element/FieldTest.php | 20 +++---- tests/PhpWord/Element/FooterTest.php | 2 +- tests/PhpWord/Element/FootnoteTest.php | 2 +- tests/PhpWord/Element/HeaderTest.php | 5 +- tests/PhpWord/Element/ImageTest.php | 12 ++--- tests/PhpWord/Element/ObjectTest.php | 3 +- tests/PhpWord/Element/RowTest.php | 2 +- tests/PhpWord/Element/SDTTest.php | 5 +- tests/PhpWord/Element/SectionTest.php | 6 +-- tests/PhpWord/Element/TitleTest.php | 4 +- .../Exception/CopyFileExceptionTest.php | 2 +- .../CreateTemporaryFileExceptionTest.php | 2 +- tests/PhpWord/Exception/ExceptionTest.php | 2 +- .../Exception/InvalidImageExceptionTest.php | 2 +- .../Exception/InvalidStyleExceptionTest.php | 2 +- .../UnsupportedImageTypeExceptionTest.php | 2 +- tests/PhpWord/IOFactoryTest.php | 6 +-- tests/PhpWord/MediaTest.php | 5 +- tests/PhpWord/Metadata/SettingsTest.php | 10 ++-- tests/PhpWord/PhpWordTest.php | 8 ++- tests/PhpWord/Reader/HTMLTest.php | 5 +- tests/PhpWord/Reader/MsDocTest.php | 4 +- tests/PhpWord/Reader/RTFTest.php | 5 +- tests/PhpWord/SettingsTest.php | 4 +- tests/PhpWord/Shared/ConverterTest.php | 48 ++++++++--------- tests/PhpWord/Shared/DrawingTest.php | 2 +- tests/PhpWord/Shared/HtmlTest.php | 5 +- tests/PhpWord/Shared/XMLReaderTest.php | 6 +-- tests/PhpWord/Style/AbstractStyleTest.php | 3 +- tests/PhpWord/Style/ChartTest.php | 2 +- tests/PhpWord/Style/FontTest.php | 7 ++- tests/PhpWord/Style/ImageTest.php | 3 +- tests/PhpWord/Style/LanguageTest.php | 3 +- tests/PhpWord/Style/PaperTest.php | 10 ++-- tests/PhpWord/Style/ParagraphTest.php | 5 +- tests/PhpWord/Style/SectionTest.php | 20 +++---- tests/PhpWord/Style/TextBoxTest.php | 3 +- tests/PhpWord/TemplateProcessorTest.php | 52 +++++++++---------- tests/PhpWord/Writer/HTML/ElementTest.php | 2 +- tests/PhpWord/Writer/HTML/PartTest.php | 3 +- tests/PhpWord/Writer/HTMLTest.php | 5 +- .../Writer/ODText/Element/ImageTest.php | 2 +- tests/PhpWord/Writer/ODText/ElementTest.php | 2 +- .../Writer/ODText/Part/AbstractPartTest.php | 5 +- .../Writer/ODText/Part/ContentTest.php | 2 +- .../PhpWord/Writer/ODText/Style/FontTest.php | 2 +- .../Writer/ODText/Style/ParagraphTest.php | 2 +- .../Writer/ODText/Style/SectionTest.php | 2 +- tests/PhpWord/Writer/ODTextTest.php | 8 ++- tests/PhpWord/Writer/PDFTest.php | 5 +- tests/PhpWord/Writer/RTFTest.php | 5 +- .../Writer/Word2007/Element/ChartTest.php | 4 +- .../Writer/Word2007/Element/FormFieldTest.php | 2 +- tests/PhpWord/Writer/Word2007/ElementTest.php | 2 +- .../Writer/Word2007/Part/AbstractPartTest.php | 5 +- .../Writer/Word2007/Part/CommentsTest.php | 2 +- .../Writer/Word2007/Part/DocumentTest.php | 4 +- .../Writer/Word2007/Part/FootnotesTest.php | 2 +- .../Writer/Word2007/Part/NumberingTest.php | 2 +- .../Writer/Word2007/Part/SettingsTest.php | 2 +- .../Writer/Word2007/Part/StylesTest.php | 2 +- tests/PhpWord/Writer/Word2007/PartTest.php | 4 +- .../Writer/Word2007/Style/FontTest.php | 2 +- .../Writer/Word2007/Style/ImageTest.php | 18 +++---- .../Writer/Word2007/Style/ParagraphTest.php | 2 +- .../Writer/Word2007/Style/SectionTest.php | 2 +- .../Writer/Word2007/Style/TableTest.php | 2 +- tests/PhpWord/Writer/Word2007Test.php | 5 +- .../AbstractWebServerEmbeddedTest.php | 4 +- tests/PhpWord/_includes/TestHelperDOCX.php | 2 +- 83 files changed, 215 insertions(+), 288 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a8318e33f9..56b4a86b05 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,30 +36,8 @@ jobs: key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- - - name: Update PHPUnit version for PHP 8 - id: composer-lock - if: "startsWith(matrix.php-version, '8.')" - run: | - rm -f composer.lock - echo "::set-output name=flags::--ignore-platform-reqs" - composer remove phpunit/phpunit --dev --no-update --no-interaction - composer require phpunit/phpunit ^8.0 --dev --no-update - - name: Install dependencies - run: composer update --no-progress --prefer-dist --optimize-autoloader ${{ steps.composer-lock.outputs.flags }} - - - name: Update code to make PHPUnit 8 compatible - if: "startsWith(matrix.php-version, '8.')" - run: | - find ./tests/ -name "*.php" -type f -exec sed -i -e 's/function setUpBeforeClass()$/function setUpBeforeClass(): void/' {} \; - find ./tests/ -name "*.php" -type f -exec sed -i -e 's/function tearDownAfterClass()$/function tearDownAfterClass(): void/' {} \; - find ./tests/ -name "*.php" -type f -exec sed -i -e 's/function setUp()$/function setUp(): void/' {} \; - find ./tests/ -name "*.php" -type f -exec sed -i -e 's/function tearDown()$/function tearDown(): void/' {} \; - find ./tests/ -name "*.php" -type f -exec sed -i -e 's/->assertContains(/->assertStringContainsString(/' {} \; - find ./tests/ -name "*.php" -type f -exec sed -i -e 's/->assertNotContains(/->assertStringNotContainsString(/' {} \; - find ./tests/ -name "*.php" -type f -exec sed -i -e "s/->assertInternalType('array', /->assertIsArray(/" {} \; - sed -i "s/\$this->addWarning('The @expectedException,/\/\/\$this->addWarning('The @expectedException,/" ./vendor/phpunit/phpunit/src/Framework/TestCase.php - sed -i "s/self::createWarning('The optional \$delta/\/\/self::createWarning('The optional \$delta/" ./vendor/phpunit/phpunit/src/Framework/Assert.php + run: composer install --no-progress --prefer-dist --optimize-autoloader - name: Setup problem matchers for PHP run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" diff --git a/composer.json b/composer.json index 4c212072fc..5dad85075a 100644 --- a/composer.json +++ b/composer.json @@ -59,22 +59,24 @@ }, "require": { "php": "^7.4 || ^8.0", + "ext-dom": "*", + "ext-json": "*", "ext-xml": "*", - "laminas/laminas-escaper": "^2.2", + "laminas/laminas-escaper": "^2.10", "symfony/process": "^5.4" }, "require-dev": { "ext-zip": "*", "ext-gd": "*", - "phpunit/phpunit": "^4.8.36 || ^7.0", - "squizlabs/php_codesniffer": "^2.9 || ^3.5", - "friendsofphp/php-cs-fixer": "^2.2", - "phpmd/phpmd": "2.*", - "phploc/phploc": "2.* || 3.* || 4.* || 5.* || 6.* || 7.*", - "dompdf/dompdf":"0.8.* || 1.0.*", - "tecnickcom/tcpdf": "^6.4", - "mpdf/mpdf": "5.7.4 || 6.* || 7.* || 8.*", - "php-coveralls/php-coveralls": "1.1.0 || ^2.0" + "dompdf/dompdf": "^2.0", + "friendsofphp/php-cs-fixer": "^3.11", + "mpdf/mpdf": "^8.1", + "php-coveralls/php-coveralls": "^2.5", + "phploc/phploc": "^7.0", + "phpmd/phpmd": "^2.13", + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.7", + "tecnickcom/tcpdf": "^6.5" }, "suggest": { "ext-zip": "Allows writing OOXML and ODF", diff --git a/src/PhpWord/Element/PreserveText.php b/src/PhpWord/Element/PreserveText.php index 803ee4f395..a6210bab8a 100644 --- a/src/PhpWord/Element/PreserveText.php +++ b/src/PhpWord/Element/PreserveText.php @@ -60,7 +60,7 @@ public function __construct($text = null, $fontStyle = null, $paragraphStyle = n $this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle); $this->text = SharedText::toUTF8($text); - $matches = preg_split('/({.*?})/', $this->text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + $matches = preg_split('/({.*?})/', $this->text ?? '', -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); if (isset($matches[0])) { $this->text = $matches; } diff --git a/src/PhpWord/Reader/MsDoc.php b/src/PhpWord/Reader/MsDoc.php index b4c194ca2a..3a7967b3cd 100644 --- a/src/PhpWord/Reader/MsDoc.php +++ b/src/PhpWord/Reader/MsDoc.php @@ -1499,9 +1499,9 @@ private function readSprm($sprm) { $oSprm = new \stdClass(); $oSprm->isPmd = $sprm & 0x01FF; - $oSprm->f = ($sprm / 512) & 0x0001; - $oSprm->sgc = ($sprm / 1024) & 0x0007; - $oSprm->spra = ($sprm / 8192); + $oSprm->f = (int)($sprm / 512) & 0x0001; + $oSprm->sgc = (int)($sprm / 1024) & 0x0007; + $oSprm->spra = (int)($sprm / 8192); return $oSprm; } diff --git a/src/PhpWord/Settings.php b/src/PhpWord/Settings.php index 7966331776..457156aacc 100644 --- a/src/PhpWord/Settings.php +++ b/src/PhpWord/Settings.php @@ -255,7 +255,7 @@ public static function getPdfRendererPath() */ public static function setPdfRendererPath($libraryBaseDir) { - if (false === file_exists($libraryBaseDir) || false === is_readable($libraryBaseDir)) { + if (!$libraryBaseDir || false === file_exists($libraryBaseDir) || false === is_readable($libraryBaseDir)) { return false; } self::$pdfRendererPath = $libraryBaseDir; diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index f57fb0a955..530074e183 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -620,7 +620,7 @@ protected static function parseStyle($attribute, $styles) foreach ($properties as $property) { list($cKey, $cValue) = array_pad(explode(':', $property, 2), 2, null); - $cValue = trim($cValue); + $cValue = trim($cValue ?? ''); $cKey = strtolower(trim($cKey)); switch ($cKey) { case 'text-decoration': diff --git a/src/PhpWord/Shared/XMLWriter.php b/src/PhpWord/Shared/XMLWriter.php index 882492e00f..4d0afc5e13 100644 --- a/src/PhpWord/Shared/XMLWriter.php +++ b/src/PhpWord/Shared/XMLWriter.php @@ -59,7 +59,7 @@ public function __construct($pTemporaryStorage = self::STORAGE_MEMORY, $pTempora if ($pTemporaryStorage == self::STORAGE_MEMORY) { $this->openMemory(); } else { - if (!is_dir($pTemporaryStorageDir)) { + if (!$pTemporaryStorageDir || !is_dir($pTemporaryStorageDir)) { $pTemporaryStorageDir = sys_get_temp_dir(); } // Create temporary filename @@ -178,6 +178,6 @@ public function writeAttribute($name, $value) $value = json_encode($value); } - return parent::writeAttribute($name, $value); + return parent::writeAttribute($name, $value ?? ''); } } diff --git a/src/PhpWord/Writer/RTF/Element/Title.php b/src/PhpWord/Writer/RTF/Element/Title.php index 77ebff1769..7fc6a6534a 100644 --- a/src/PhpWord/Writer/RTF/Element/Title.php +++ b/src/PhpWord/Writer/RTF/Element/Title.php @@ -29,7 +29,7 @@ protected function getStyles() /** @var \PhpOffice\PhpWord\Element\Title $element Type hint */ $element = $this->element; $style = $element->getStyle(); - $style = str_replace('Heading', 'Heading_', $style); + $style = str_replace('Heading', 'Heading_', $style ?? ''); $style = \PhpOffice\PhpWord\Style::getStyle($style); if ($style instanceof \PhpOffice\PhpWord\Style\Font) { $this->fontStyle = $style; diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index 9f8cf9dff0..59d4ebafe2 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -65,8 +65,8 @@ public function write() $content .= $alignments[$style->getAlignment()]; } $content .= $this->writeIndentation($style->getIndentation()); - $content .= $this->getValueIf($spaceBefore !== null, '\sb' . round($spaceBefore)); - $content .= $this->getValueIf($spaceAfter !== null, '\sa' . round($spaceAfter)); + $content .= $this->getValueIf($spaceBefore !== null, '\sb' . round($spaceBefore??0)); + $content .= $this->getValueIf($spaceAfter !== null, '\sa' . round($spaceAfter??0)); $lineHeight = $style->getLineHeight(); if ($lineHeight) { $lineHeightAdjusted = (int) ($lineHeight * 240); diff --git a/tests/PhpWord/ComplexType/FootnotePropertiesTest.php b/tests/PhpWord/ComplexType/FootnotePropertiesTest.php index 4448daf865..e8ca7b3a79 100644 --- a/tests/PhpWord/ComplexType/FootnotePropertiesTest.php +++ b/tests/PhpWord/ComplexType/FootnotePropertiesTest.php @@ -46,33 +46,30 @@ public function testSetGetNormal() /** * Test throws exception if wrong position given - * - * @expectedException \InvalidArgumentException */ public function testWrongPos() { + $this->expectException(\InvalidArgumentException::class); $footnoteProp = new FootnoteProperties(); $footnoteProp->setPos(NumberFormat::LOWER_ROMAN); } /** * Test throws exception if wrong number format given - * - * @expectedException \InvalidArgumentException */ public function testWrongNumFmt() { + $this->expectException(\InvalidArgumentException::class); $footnoteProp = new FootnoteProperties(); $footnoteProp->setNumFmt(FootnoteProperties::POSITION_DOC_END); } /** * Test throws exception if wrong number restart given - * - * @expectedException \InvalidArgumentException */ public function testWrongNumRestart() { + $this->expectException(\InvalidArgumentException::class); $footnoteProp = new FootnoteProperties(); $footnoteProp->setNumRestart(NumberFormat::LOWER_ROMAN); } diff --git a/tests/PhpWord/ComplexType/ProofStateTest.php b/tests/PhpWord/ComplexType/ProofStateTest.php index cd1e77f7f0..ace51803ba 100644 --- a/tests/PhpWord/ComplexType/ProofStateTest.php +++ b/tests/PhpWord/ComplexType/ProofStateTest.php @@ -39,22 +39,20 @@ public function testGetSet() /** * Test throws exception if wrong grammar proof state value given - * - * @expectedException \InvalidArgumentException */ public function testWrongGrammar() { + $this->expectException(\InvalidArgumentException::class); $pState = new ProofState(); $pState->setGrammar('Wrong'); } /** * Test throws exception if wrong spelling proof state value given - * - * @expectedException \InvalidArgumentException */ public function testWrongSpelling() { + $this->expectException(\InvalidArgumentException::class); $pState = new ProofState(); $pState->setSpelling('Wrong'); } diff --git a/tests/PhpWord/Element/CellTest.php b/tests/PhpWord/Element/CellTest.php index f0d639bc30..0cac9bb72b 100644 --- a/tests/PhpWord/Element/CellTest.php +++ b/tests/PhpWord/Element/CellTest.php @@ -188,11 +188,10 @@ public function testAddObjectXLS() /** * Test add object exception - * - * @expectedException \PhpOffice\PhpWord\Exception\InvalidObjectException */ public function testAddObjectException() { + $this->expectException(\PhpOffice\PhpWord\Exception\InvalidObjectException::class); $src = __DIR__ . '/../_files/xsl/passthrough.xsl'; $oCell = new Cell(); $oCell->addObject($src); @@ -227,11 +226,10 @@ public function testAddPreserveTextNotUTF8() /** * Add preserve text exception - * - * @expectedException \BadMethodCallException */ public function testAddPreserveTextException() { + $this->expectException(\BadMethodCallException::class); $oCell = new Cell(); $oCell->setDocPart('TextRun', 1); $oCell->addPreserveText('text'); @@ -268,6 +266,6 @@ public function testGetElements() { $oCell = new Cell(); - $this->assertInternalType('array', $oCell->getElements()); + $this->assertIsArray($oCell->getElements()); } } diff --git a/tests/PhpWord/Element/CommentTest.php b/tests/PhpWord/Element/CommentTest.php index b9c3dfce5a..eea944d5ee 100644 --- a/tests/PhpWord/Element/CommentTest.php +++ b/tests/PhpWord/Element/CommentTest.php @@ -66,7 +66,7 @@ public function testGetElements() { $oComment = new Comment('Test User', new \DateTime(), 'my_initials'); - $this->assertInternalType('array', $oComment->getElements()); + $this->assertIsArray($oComment->getElements()); } /** @@ -81,21 +81,17 @@ public function testRelationId() $this->assertEquals($iVal, $oComment->getRelationId()); } - /** - * @expectedException \InvalidArgumentException - */ public function testExceptionOnCommentStartOnComment() { + $this->expectException(\InvalidArgumentException::class); $dummyComment = new Comment('Test User', new \DateTime(), 'my_initials'); $oComment = new Comment('Test User', new \DateTime(), 'my_initials'); $oComment->setCommentRangeStart($dummyComment); } - /** - * @expectedException \InvalidArgumentException - */ public function testExceptionOnCommentEndOnComment() { + $this->expectException(\InvalidArgumentException::class); $dummyComment = new Comment('Test User', new \DateTime(), 'my_initials'); $oComment = new Comment('Test User', new \DateTime(), 'my_initials'); $oComment->setCommentRangeEnd($dummyComment); diff --git a/tests/PhpWord/Element/FieldTest.php b/tests/PhpWord/Element/FieldTest.php index 1c1c0ca1ef..df7f8b7934 100644 --- a/tests/PhpWord/Element/FieldTest.php +++ b/tests/PhpWord/Element/FieldTest.php @@ -113,48 +113,44 @@ public function testConstructWithOptionValue() /** * Test setType exception - * - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Invalid type */ public function testSetTypeException() { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid type'); $object = new Field(); $object->setType('foo'); } /** * Test setProperties exception - * - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Invalid property */ public function testSetPropertiesException() { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid property'); $object = new Field('PAGE'); $object->setProperties(array('foo' => 'bar')); } /** * Test setOptions exception - * - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Invalid option */ public function testSetOptionsException() { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid option'); $object = new Field('PAGE'); $object->setOptions(array('foo' => 'bar')); } /** * Test setText exception - * - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Invalid text */ public function testSetTextException() { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid text'); $object = new Field('XE'); $object->setText(array()); } diff --git a/tests/PhpWord/Element/FooterTest.php b/tests/PhpWord/Element/FooterTest.php index b1ef467750..360a9005d7 100644 --- a/tests/PhpWord/Element/FooterTest.php +++ b/tests/PhpWord/Element/FooterTest.php @@ -156,7 +156,7 @@ public function testGetElements() { $oFooter = new Footer(1); - $this->assertInternalType('array', $oFooter->getElements()); + $this->assertIsArray($oFooter->getElements()); } /** diff --git a/tests/PhpWord/Element/FootnoteTest.php b/tests/PhpWord/Element/FootnoteTest.php index 4ea330f5ac..86ee0143c0 100644 --- a/tests/PhpWord/Element/FootnoteTest.php +++ b/tests/PhpWord/Element/FootnoteTest.php @@ -112,6 +112,6 @@ public function testReferenceId() public function testGetElements() { $oFootnote = new Footnote(); - $this->assertInternalType('array', $oFootnote->getElements()); + $this->assertIsArray($oFootnote->getElements()); } } diff --git a/tests/PhpWord/Element/HeaderTest.php b/tests/PhpWord/Element/HeaderTest.php index 4bbf7b74f3..3b97f887b1 100644 --- a/tests/PhpWord/Element/HeaderTest.php +++ b/tests/PhpWord/Element/HeaderTest.php @@ -178,7 +178,7 @@ public function testGetElements() { $oHeader = new Header(1); - $this->assertInternalType('array', $oHeader->getElements()); + $this->assertIsArray($oHeader->getElements()); } /** @@ -229,11 +229,10 @@ public function testEvenPage() /** * Add footnote exception - * - * @expectedException \BadMethodCallException */ public function testAddFootnoteException() { + $this->expectException(\BadMethodCallException::class); $header = new Header(1); $header->addFootnote(); } diff --git a/tests/PhpWord/Element/ImageTest.php b/tests/PhpWord/Element/ImageTest.php index e83be708d7..da3bdca2d3 100644 --- a/tests/PhpWord/Element/ImageTest.php +++ b/tests/PhpWord/Element/ImageTest.php @@ -108,32 +108,29 @@ public function testStyle() /** * Test invalid local image - * - * @expectedException \PhpOffice\PhpWord\Exception\InvalidImageException */ public function testInvalidImageLocal() { + $this->expectException(\PhpOffice\PhpWord\Exception\InvalidImageException::class); new Image(__DIR__ . '/../_files/images/thisisnotarealimage'); } /** * Test invalid PHP Image - * - * @expectedException \PhpOffice\PhpWord\Exception\InvalidImageException */ public function testInvalidImagePhp() { + $this->expectException(\PhpOffice\PhpWord\Exception\InvalidImageException::class); $object = new Image('test.php'); $object->getSource(); } /** * Test unsupported image - * - * @expectedException \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException */ public function testUnsupportedImage() { + $this->expectException(\PhpOffice\PhpWord\Exception\UnsupportedImageTypeException::class); //disable ssl verification, never do this in real application, you should pass the certificiate instead!!! $arrContextOptions = array( 'ssl' => array( @@ -236,11 +233,10 @@ public function testConstructFromGd() /** * Test invalid string image - * - * @expectedException \PhpOffice\PhpWord\Exception\InvalidImageException */ public function testInvalidImageString() { + $this->expectException(\PhpOffice\PhpWord\Exception\InvalidImageException::class); $object = new Image('this_is-a_non_valid_image'); $object->getSource(); } diff --git a/tests/PhpWord/Element/ObjectTest.php b/tests/PhpWord/Element/ObjectTest.php index 9fbe1bb554..3a7637082e 100644 --- a/tests/PhpWord/Element/ObjectTest.php +++ b/tests/PhpWord/Element/ObjectTest.php @@ -53,11 +53,10 @@ public function testConstructWithSupportedFilesLong() /** * Create new instance with non-supported files - * - * @expectedException \PhpOffice\PhpWord\Exception\InvalidObjectException */ public function testConstructWithNotSupportedFiles() { + $this->expectException(\PhpOffice\PhpWord\Exception\InvalidObjectException::class); $src = __DIR__ . '/../_files/xsl/passthrough.xsl'; $oObject = new OLEObject($src); $oObject->getSource(); diff --git a/tests/PhpWord/Element/RowTest.php b/tests/PhpWord/Element/RowTest.php index 3c53450294..01c3998189 100644 --- a/tests/PhpWord/Element/RowTest.php +++ b/tests/PhpWord/Element/RowTest.php @@ -34,7 +34,7 @@ public function testConstruct() $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Row', $oRow); $this->assertNull($oRow->getHeight()); - $this->assertInternalType('array', $oRow->getCells()); + $this->assertIsArray($oRow->getCells()); $this->assertCount(0, $oRow->getCells()); $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Row', $oRow->getStyle()); } diff --git a/tests/PhpWord/Element/SDTTest.php b/tests/PhpWord/Element/SDTTest.php index 2328dd76be..d969eb776b 100644 --- a/tests/PhpWord/Element/SDTTest.php +++ b/tests/PhpWord/Element/SDTTest.php @@ -50,12 +50,11 @@ public function testConstruct() /** * Test set type exception - * - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Invalid style value */ public function testSetTypeException() { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid style value'); $object = new SDT('comboBox'); $object->setType('foo'); } diff --git a/tests/PhpWord/Element/SectionTest.php b/tests/PhpWord/Element/SectionTest.php index 83d1214e45..f49d2ba23a 100644 --- a/tests/PhpWord/Element/SectionTest.php +++ b/tests/PhpWord/Element/SectionTest.php @@ -109,10 +109,10 @@ public function testAddElements() /** * @coversNothing - * @expectedException \PhpOffice\PhpWord\Exception\InvalidObjectException */ public function testAddObjectException() { + $this->expectException(\PhpOffice\PhpWord\Exception\InvalidObjectException::class); $source = __DIR__ . '/_files/xsl/passthrough.xsl'; $section = new Section(0); $section->addObject($source); @@ -176,11 +176,11 @@ public function testHasDifferentFirstPage() /** * @covers ::addHeader - * @expectedException \Exception - * @expectedExceptionMessage Invalid header/footer type. */ public function testAddHeaderException() { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Invalid header/footer type.'); $object = new Section(1); $object->addHeader('ODD'); } diff --git a/tests/PhpWord/Element/TitleTest.php b/tests/PhpWord/Element/TitleTest.php index 6ef87c3e8e..53d3f2abc6 100644 --- a/tests/PhpWord/Element/TitleTest.php +++ b/tests/PhpWord/Element/TitleTest.php @@ -58,11 +58,9 @@ public function testConstructWithTextRun() $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $oTitle->getText()); } - /** - * @expectedException \InvalidArgumentException - */ public function testConstructWithInvalidArgument() { + $this->expectException(\InvalidArgumentException::class); $oPageBreak = new PageBreak(); new Title($oPageBreak); } diff --git a/tests/PhpWord/Exception/CopyFileExceptionTest.php b/tests/PhpWord/Exception/CopyFileExceptionTest.php index 5fed9c9f25..1a69e4de21 100644 --- a/tests/PhpWord/Exception/CopyFileExceptionTest.php +++ b/tests/PhpWord/Exception/CopyFileExceptionTest.php @@ -27,11 +27,11 @@ class CopyFileExceptionTest extends \PHPUnit\Framework\TestCase * CopyFileException can be thrown. * * @covers ::__construct() - * @expectedException \PhpOffice\PhpWord\Exception\CopyFileException * @test */ public function testCopyFileExceptionCanBeThrown() { + $this->expectException(\PhpOffice\PhpWord\Exception\CopyFileException::class); throw new CopyFileException('C:\source\dummy.txt', 'C:\destination\dummy.txt'); } } diff --git a/tests/PhpWord/Exception/CreateTemporaryFileExceptionTest.php b/tests/PhpWord/Exception/CreateTemporaryFileExceptionTest.php index f879285e89..f5bd5f4e65 100644 --- a/tests/PhpWord/Exception/CreateTemporaryFileExceptionTest.php +++ b/tests/PhpWord/Exception/CreateTemporaryFileExceptionTest.php @@ -27,11 +27,11 @@ class CreateTemporaryFileExceptionTest extends \PHPUnit\Framework\TestCase * CreateTemporaryFileException can be thrown. * * @covers ::__construct() - * @expectedException \PhpOffice\PhpWord\Exception\CreateTemporaryFileException * @test */ public function testCreateTemporaryFileExceptionCanBeThrown() { + $this->expectException(\PhpOffice\PhpWord\Exception\CreateTemporaryFileException::class); throw new CreateTemporaryFileException(); } } diff --git a/tests/PhpWord/Exception/ExceptionTest.php b/tests/PhpWord/Exception/ExceptionTest.php index 8c7bce5774..4d4e20d12c 100644 --- a/tests/PhpWord/Exception/ExceptionTest.php +++ b/tests/PhpWord/Exception/ExceptionTest.php @@ -28,11 +28,11 @@ class ExceptionTest extends \PHPUnit\Framework\TestCase /** * Throw new exception * - * @expectedException \PhpOffice\PhpWord\Exception\Exception * @covers \PhpOffice\PhpWord\Exception\Exception */ public function testThrowException() { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); throw new Exception(); } } diff --git a/tests/PhpWord/Exception/InvalidImageExceptionTest.php b/tests/PhpWord/Exception/InvalidImageExceptionTest.php index 71da1aa9e3..e150747a28 100644 --- a/tests/PhpWord/Exception/InvalidImageExceptionTest.php +++ b/tests/PhpWord/Exception/InvalidImageExceptionTest.php @@ -28,11 +28,11 @@ class InvalidImageExceptionTest extends \PHPUnit\Framework\TestCase /** * Throw new exception * - * @expectedException \PhpOffice\PhpWord\Exception\InvalidImageException * @covers \PhpOffice\PhpWord\Exception\InvalidImageException */ public function testThrowException() { + $this->expectException(\PhpOffice\PhpWord\Exception\InvalidImageException::class); throw new InvalidImageException(); } } diff --git a/tests/PhpWord/Exception/InvalidStyleExceptionTest.php b/tests/PhpWord/Exception/InvalidStyleExceptionTest.php index 1d981449a9..b838680313 100644 --- a/tests/PhpWord/Exception/InvalidStyleExceptionTest.php +++ b/tests/PhpWord/Exception/InvalidStyleExceptionTest.php @@ -28,11 +28,11 @@ class InvalidStyleExceptionTest extends \PHPUnit\Framework\TestCase /** * Throw new exception * - * @expectedException \PhpOffice\PhpWord\Exception\InvalidStyleException * @covers \PhpOffice\PhpWord\Exception\InvalidStyleException */ public function testThrowException() { + $this->expectException(\PhpOffice\PhpWord\Exception\InvalidStyleException::class); throw new InvalidStyleException(); } } diff --git a/tests/PhpWord/Exception/UnsupportedImageTypeExceptionTest.php b/tests/PhpWord/Exception/UnsupportedImageTypeExceptionTest.php index 5b03f5e31d..add8a1ca05 100644 --- a/tests/PhpWord/Exception/UnsupportedImageTypeExceptionTest.php +++ b/tests/PhpWord/Exception/UnsupportedImageTypeExceptionTest.php @@ -28,11 +28,11 @@ class UnsupportedImageTypeExceptionTest extends \PHPUnit\Framework\TestCase /** * Throw new exception * - * @expectedException \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException * @covers \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException */ public function testThrowException() { + $this->expectException(\PhpOffice\PhpWord\Exception\UnsupportedImageTypeException::class); throw new UnsupportedImageTypeException(); } } diff --git a/tests/PhpWord/IOFactoryTest.php b/tests/PhpWord/IOFactoryTest.php index 4a59e7022a..f286dcc670 100644 --- a/tests/PhpWord/IOFactoryTest.php +++ b/tests/PhpWord/IOFactoryTest.php @@ -37,11 +37,10 @@ public function testExistingWriterCanBeCreated() /** * Create non-existing writer - * - * @expectedException \PhpOffice\PhpWord\Exception\Exception */ public function testNonexistentWriterCanNotBeCreated() { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); IOFactory::createWriter(new PhpWord(), 'Word2006'); } @@ -58,11 +57,10 @@ public function testExistingReaderCanBeCreated() /** * Create non-existing reader - * - * @expectedException \PhpOffice\PhpWord\Exception\Exception */ public function testNonexistentReaderCanNotBeCreated() { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); IOFactory::createReader('Word2006'); } diff --git a/tests/PhpWord/MediaTest.php b/tests/PhpWord/MediaTest.php index cca413f505..de42e91c3f 100644 --- a/tests/PhpWord/MediaTest.php +++ b/tests/PhpWord/MediaTest.php @@ -121,12 +121,11 @@ public function testAddFooterMediaElement() /** * Add image element exception - * - * @expectedException \Exception - * @expectedExceptionMessage Image object not assigned. */ public function testAddElementImageException() { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Image object not assigned.'); Media::addElement('section', 'image', __DIR__ . '/_files/images/mars.jpg'); } } diff --git a/tests/PhpWord/Metadata/SettingsTest.php b/tests/PhpWord/Metadata/SettingsTest.php index 9670f1d992..12be752c17 100644 --- a/tests/PhpWord/Metadata/SettingsTest.php +++ b/tests/PhpWord/Metadata/SettingsTest.php @@ -71,10 +71,10 @@ public function testDocumentProtection() /** * Test setting an invalid salt - * @expectedException \InvalidArgumentException */ public function testInvalidSalt() { + $this->expectException(\InvalidArgumentException::class); $protection = new Protection(); $protection->setSalt('123'); } @@ -125,20 +125,16 @@ public function testProofState() $this->assertEquals(ProofState::DIRTY, $oSettings->getProofState()->getSpelling()); } - /** - * @expectedException \InvalidArgumentException - */ public function testWrongProofStateGrammar() { + $this->expectException(\InvalidArgumentException::class); $proofState = new ProofState(); $proofState->setGrammar('wrong'); } - /** - * @expectedException \InvalidArgumentException - */ public function testWrongProofStateSpelling() { + $this->expectException(\InvalidArgumentException::class); $proofState = new ProofState(); $proofState->setSpelling('wrong'); } diff --git a/tests/PhpWord/PhpWordTest.php b/tests/PhpWord/PhpWordTest.php index 4acd0fe67a..09081334f8 100644 --- a/tests/PhpWord/PhpWordTest.php +++ b/tests/PhpWord/PhpWordTest.php @@ -133,11 +133,10 @@ public function testLoadTemplate() * Test load template exception * * @deprecated 0.12.0 - * - * @expectedException \PhpOffice\PhpWord\Exception\Exception */ public function testLoadTemplateException() { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); $templateFqfn = implode( DIRECTORY_SEPARATOR, array(PHPWORD_TESTS_BASE_DIR, 'PhpWord', 'Tests', '_files', 'templates', 'blanks.docx') @@ -162,12 +161,11 @@ public function testSave() /** * Test calling undefined method - * - * @expectedException \BadMethodCallException - * @expectedExceptionMessage is not defined */ public function testCallUndefinedMethod() { + $this->expectException(\BadMethodCallException::class); + $this->expectExceptionMessage('is not defined'); $phpWord = new PhpWord(); $phpWord->undefinedMethod(); } diff --git a/tests/PhpWord/Reader/HTMLTest.php b/tests/PhpWord/Reader/HTMLTest.php index 38588afc17..f903198d4d 100644 --- a/tests/PhpWord/Reader/HTMLTest.php +++ b/tests/PhpWord/Reader/HTMLTest.php @@ -39,12 +39,11 @@ public function testLoad() /** * Test load exception - * - * @expectedException \Exception - * @expectedExceptionMessage Cannot read */ public function testLoadException() { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Cannot read'); $filename = __DIR__ . '/../_files/documents/foo.html'; IOFactory::load($filename, 'HTML'); } diff --git a/tests/PhpWord/Reader/MsDocTest.php b/tests/PhpWord/Reader/MsDocTest.php index 3ce3993977..63bebef208 100644 --- a/tests/PhpWord/Reader/MsDocTest.php +++ b/tests/PhpWord/Reader/MsDocTest.php @@ -59,20 +59,20 @@ public function testLoad() /** * Test exception on not existing file - * @expectedException \Exception */ public function testFailIfFileNotReadable() { + $this->expectException(\Exception::class); $filename = __DIR__ . '/../_files/documents/not_existing_reader.doc'; IOFactory::load($filename, 'MsDoc'); } /** * Test exception on non OLE document - * @expectedException \Exception */ public function testFailIfFileNotOle() { + $this->expectException(\Exception::class); $filename = __DIR__ . '/../_files/documents/reader.odt'; IOFactory::load($filename, 'MsDoc'); } diff --git a/tests/PhpWord/Reader/RTFTest.php b/tests/PhpWord/Reader/RTFTest.php index fed00ceb36..387dd911e3 100644 --- a/tests/PhpWord/Reader/RTFTest.php +++ b/tests/PhpWord/Reader/RTFTest.php @@ -39,12 +39,11 @@ public function testLoad() /** * Test load exception - * - * @expectedException \Exception - * @expectedExceptionMessage Cannot read */ public function testLoadException() { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Cannot read'); $filename = __DIR__ . '/../_files/documents/foo.rtf'; IOFactory::load($filename, 'RTF'); } diff --git a/tests/PhpWord/SettingsTest.php b/tests/PhpWord/SettingsTest.php index 748ec71b10..ce072c7543 100644 --- a/tests/PhpWord/SettingsTest.php +++ b/tests/PhpWord/SettingsTest.php @@ -36,7 +36,7 @@ class SettingsTest extends \PHPUnit\Framework\TestCase private $tempDir; private $zipClass; - public function setUp() + public function setUp(): void { $this->compatibility = Settings::hasCompatibility(); $this->defaultFontSize = Settings::getDefaultFontSize(); @@ -50,7 +50,7 @@ public function setUp() $this->zipClass = Settings::getZipClass(); } - public function tearDown() + public function tearDown(): void { Settings::setCompatibility($this->compatibility); Settings::setDefaultFontSize($this->defaultFontSize); diff --git a/tests/PhpWord/Shared/ConverterTest.php b/tests/PhpWord/Shared/ConverterTest.php index 82bcaf845e..f6c0479e9f 100644 --- a/tests/PhpWord/Shared/ConverterTest.php +++ b/tests/PhpWord/Shared/ConverterTest.php @@ -36,70 +36,70 @@ public function testUnitConversions() foreach ($values as $value) { $result = Converter::cmToTwip($value); - $this->assertEquals($value / 2.54 * 1440, $result, '', 0.00001); + $this->assertEqualsWithDelta($value / 2.54 * 1440, $result, 0.00001); $result = Converter::cmToInch($value); - $this->assertEquals($value / 2.54, $result, '', 0.00001); + $this->assertEqualsWithDelta($value / 2.54, $result, 0.00001); $result = Converter::cmToPixel($value); - $this->assertEquals($value / 2.54 * 96, $result, '', 0.00001); + $this->assertEqualsWithDelta($value / 2.54 * 96, $result, 0.00001); $result = Converter::cmToPoint($value); - $this->assertEquals($value / 2.54 * 72, $result, '', 0.00001); + $this->assertEqualsWithDelta($value / 2.54 * 72, $result, 0.00001); $result = Converter::cmToEmu($value); - $this->assertEquals(round($value / 2.54 * 96 * 9525), $result, '', 0.00001); + $this->assertEqualsWithDelta(round($value / 2.54 * 96 * 9525), $result, 0.00001); $result = Converter::inchToTwip($value); - $this->assertEquals($value * 1440, $result, '', 0.00001); + $this->assertEqualsWithDelta($value * 1440, $result, 0.00001); $result = Converter::inchToCm($value); - $this->assertEquals($value * 2.54, $result, '', 0.00001); + $this->assertEqualsWithDelta($value * 2.54, $result, 0.00001); $result = Converter::inchToPixel($value); - $this->assertEquals($value * 96, $result, '', 0.00001); + $this->assertEqualsWithDelta($value * 96, $result, 0.00001); $result = Converter::inchToPoint($value); - $this->assertEquals($value * 72, $result, '', 0.00001); + $this->assertEqualsWithDelta($value * 72, $result, 0.00001); $result = Converter::inchToEmu($value); - $this->assertEquals(round($value * 96 * 9525), $result, '', 0.00001); + $this->assertEqualsWithDelta(round($value * 96 * 9525), $result, 0.00001); $result = Converter::pixelToTwip($value); - $this->assertEquals($value / 96 * 1440, $result, '', 0.00001); + $this->assertEqualsWithDelta($value / 96 * 1440, $result, 0.00001); $result = Converter::pixelToCm($value); - $this->assertEquals($value / 96 * 2.54, $result, '', 0.00001); + $this->assertEqualsWithDelta($value / 96 * 2.54, $result, 0.00001); $result = Converter::pixelToPoint($value); - $this->assertEquals($value / 96 * 72, $result, '', 0.00001); + $this->assertEqualsWithDelta($value / 96 * 72, $result, 0.00001); $result = Converter::pixelToEmu($value); - $this->assertEquals(round($value * 9525), $result, '', 0.00001); + $this->assertEqualsWithDelta(round($value * 9525), $result, 0.00001); $result = Converter::pointToTwip($value); - $this->assertEquals($value * 20, $result, '', 0.00001); + $this->assertEqualsWithDelta($value * 20, $result, 0.00001); $result = Converter::pointToCm($value); - $this->assertEquals($value * 0.035277778, $result, '', 0.00001); + $this->assertEqualsWithDelta($value * 0.035277778, $result, 0.00001); $result = Converter::pointToPixel($value); - $this->assertEquals($value / 72 * 96, $result, '', 0.00001); + $this->assertEqualsWithDelta($value / 72 * 96, $result, 0.00001); $result = Converter::pointToEmu($value); - $this->assertEquals(round($value / 72 * 96 * 9525), $result, '', 0.00001); + $this->assertEqualsWithDelta(round($value / 72 * 96 * 9525), $result, 0.00001); $result = Converter::emuToPixel($value); - $this->assertEquals(round($value / 9525), $result, '', 0.00001); + $this->assertEqualsWithDelta(round($value / 9525), $result, 0.00001); $result = Converter::picaToPoint($value); - $this->assertEquals($value / 6 * 72, $result, '', 0.00001); + $this->assertEqualsWithDelta($value / 6 * 72, $result, 0.00001); $result = Converter::degreeToAngle($value); - $this->assertEquals((int) round($value * 60000), $result, '', 0.00001); + $this->assertEqualsWithDelta((int) round($value * 60000), $result, 0.00001); $result = Converter::angleToDegree($value); - $this->assertEquals(round($value / 60000), $result, '', 0.00001); + $this->assertEqualsWithDelta(round($value / 60000), $result, 0.00001); } } @@ -129,8 +129,8 @@ public function testCssSizeParser() $this->assertEquals(720, Converter::cssToPoint('10in')); $this->assertEquals(7.2, Converter::cssToPoint('0.1in')); $this->assertEquals(120, Converter::cssToPoint('10pc')); - $this->assertEquals(28.346457, Converter::cssToPoint('10mm'), '', 0.000001); - $this->assertEquals(283.464567, Converter::cssToPoint('10cm'), '', 0.000001); + $this->assertEqualsWithDelta(28.346457, Converter::cssToPoint('10mm'), 0.000001); + $this->assertEqualsWithDelta(283.464567, Converter::cssToPoint('10cm'), 0.000001); $this->assertEquals(40, Converter::cssToPixel('30pt')); $this->assertEquals(1.27, Converter::cssToCm('36pt')); $this->assertEquals(127000, Converter::cssToEmu('10pt')); diff --git a/tests/PhpWord/Shared/DrawingTest.php b/tests/PhpWord/Shared/DrawingTest.php index b7110923d3..49f4266345 100644 --- a/tests/PhpWord/Shared/DrawingTest.php +++ b/tests/PhpWord/Shared/DrawingTest.php @@ -102,7 +102,7 @@ public function testHTML() $this->assertFalse(Drawing::htmlToRGB('0000')); $this->assertFalse(Drawing::htmlToRGB('00000')); - $this->assertInternalType('array', Drawing::htmlToRGB('ABCDEF')); + $this->assertIsArray(Drawing::htmlToRGB('ABCDEF')); $this->assertCount(3, Drawing::htmlToRGB('ABCDEF')); $this->assertEquals(array(0xAB, 0xCD, 0xEF), Drawing::htmlToRGB('ABCDEF')); $this->assertEquals(array(0xAB, 0xCD, 0xEF), Drawing::htmlToRGB('#ABCDEF')); diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index fdf3e37c3c..2037705606 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -607,11 +607,10 @@ public function testParseRemoteLocalImage() /** * Test parsing of remote img that can be found locally - * - * @expectedException \Exception */ public function testCouldNotLoadImage() { + $this->expectException(\Exception::class); $src = 'https://fakedomain.io/images/firefox.png'; $phpWord = new \PhpOffice\PhpWord\PhpWord(); @@ -973,6 +972,6 @@ public function testDontDecodeAlreadyEncodedDoubleQuotes() Html::addHtml($section, $html); $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); - $this->assertInternalType('object', $doc); + $this->assertIsObject($doc); } } diff --git a/tests/PhpWord/Shared/XMLReaderTest.php b/tests/PhpWord/Shared/XMLReaderTest.php index 4d0ee64ca7..3f6775bb4c 100644 --- a/tests/PhpWord/Shared/XMLReaderTest.php +++ b/tests/PhpWord/Shared/XMLReaderTest.php @@ -56,11 +56,10 @@ public function testDomFromZip() /** * Test that read from non existing archive throws exception - * - * @expectedException \Exception */ public function testThrowsExceptionOnNonExistingArchive() { + $this->expectException(\Exception::class); $archiveFile = __DIR__ . '/../_files/xml/readers.zip'; $reader = new XMLReader(); @@ -123,11 +122,10 @@ public function testShouldParseXmlWithCustomNamespace() /** * Test that xpath fails if custom namespace is not registered - * - * @expectedException \InvalidArgumentException */ public function testShouldThowExceptionIfTryingToRegisterNamespaceBeforeReadingDoc() { + $this->expectException(\InvalidArgumentException::class); $reader = new XMLReader(); $reader->registerNamespace('test', 'http://phpword.com/my/custom/namespace'); } diff --git a/tests/PhpWord/Style/AbstractStyleTest.php b/tests/PhpWord/Style/AbstractStyleTest.php index 7ec272bb9b..43952cb41d 100644 --- a/tests/PhpWord/Style/AbstractStyleTest.php +++ b/tests/PhpWord/Style/AbstractStyleTest.php @@ -64,11 +64,10 @@ public function testSetValDefault() /** * Test setEnumVal exception - * - * @expectedException \InvalidArgumentException */ public function testSetValEnumException() { + $this->expectException(\InvalidArgumentException::class); $stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Style\AbstractStyle'); $this->assertEquals('b', self::callProtectedMethod($stub, 'setEnumVal', array('z', array('a', 'b'), 'b'))); diff --git a/tests/PhpWord/Style/ChartTest.php b/tests/PhpWord/Style/ChartTest.php index 9929a8f5a7..e23b891eb5 100644 --- a/tests/PhpWord/Style/ChartTest.php +++ b/tests/PhpWord/Style/ChartTest.php @@ -74,7 +74,7 @@ public function testSetGetColors() { $chart = new Chart(); - $this->assertInternalType('array', $chart->getColors()); + $this->assertIsArray($chart->getColors()); $this->assertEquals(count($chart->getColors()), 0); diff --git a/tests/PhpWord/Style/FontTest.php b/tests/PhpWord/Style/FontTest.php index 84916fc277..fa31f07015 100644 --- a/tests/PhpWord/Style/FontTest.php +++ b/tests/PhpWord/Style/FontTest.php @@ -31,7 +31,7 @@ class FontTest extends \PHPUnit\Framework\TestCase /** * Tear down after each test */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } @@ -45,7 +45,7 @@ public function testInitiation() $this->assertEquals('text', $object->getStyleType()); $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $object->getParagraphStyle()); - $this->assertInternalType('array', $object->getStyleValues()); + $this->assertIsArray($object->getStyleValues()); } /** @@ -171,11 +171,10 @@ public function testLineHeightFloatval() /** * Test line height exception by using nonnumeric value - * - * @expectedException \PhpOffice\PhpWord\Exception\InvalidStyleException */ public function testLineHeightException() { + $this->expectException(\PhpOffice\PhpWord\Exception\InvalidStyleException::class); $object = new Font(); $object->setLineHeight('a'); } diff --git a/tests/PhpWord/Style/ImageTest.php b/tests/PhpWord/Style/ImageTest.php index 1d43d92152..8e272a6bfe 100644 --- a/tests/PhpWord/Style/ImageTest.php +++ b/tests/PhpWord/Style/ImageTest.php @@ -87,11 +87,10 @@ public function testSetStyleValue() /** * Test setWrappingStyle exception - * - * @expectedException \InvalidArgumentException */ public function testSetWrappingStyleException() { + $this->expectException(\InvalidArgumentException::class); $object = new Image(); $object->setWrappingStyle('foo'); } diff --git a/tests/PhpWord/Style/LanguageTest.php b/tests/PhpWord/Style/LanguageTest.php index 3bf516f8ae..3d8ef0b737 100644 --- a/tests/PhpWord/Style/LanguageTest.php +++ b/tests/PhpWord/Style/LanguageTest.php @@ -53,11 +53,10 @@ public function testGetSetProperties() /** * Test throws exception if wrong locale is given - * - * @expectedException \InvalidArgumentException */ public function testWrongLanguage() { + $this->expectException(\InvalidArgumentException::class); $language = new Language(); $language->setLatin('fra'); } diff --git a/tests/PhpWord/Style/PaperTest.php b/tests/PhpWord/Style/PaperTest.php index f8f0070180..66b99d6abc 100644 --- a/tests/PhpWord/Style/PaperTest.php +++ b/tests/PhpWord/Style/PaperTest.php @@ -29,7 +29,7 @@ class PaperTest extends \PHPUnit\Framework\TestCase /** * Tear down after each test */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } @@ -52,8 +52,8 @@ public function testB5Size() $object = new Paper('B5'); $this->assertEquals('B5', $object->getSize()); - $this->assertEquals(9977.9527559055, $object->getWidth(), '', 0.000000001); - $this->assertEquals(14173.228346457, $object->getHeight(), '', 0.000000001); + $this->assertEqualsWithDelta(9977.9527559055, $object->getWidth(), 0.000000001); + $this->assertEqualsWithDelta(14173.228346457, $object->getHeight(), 0.000000001); } /** @@ -65,7 +65,7 @@ public function testFolioSize() $object->setSize('Folio'); $this->assertEquals('Folio', $object->getSize()); - $this->assertEquals(12240, $object->getWidth(), '', 0.1); - $this->assertEquals(18720, $object->getHeight(), '', 0.1); + $this->assertEqualsWithDelta(12240, $object->getWidth(), 0.1); + $this->assertEqualsWithDelta(18720, $object->getHeight(), 0.1); } } diff --git a/tests/PhpWord/Style/ParagraphTest.php b/tests/PhpWord/Style/ParagraphTest.php index 4fa0ef5a70..d9fd96d693 100644 --- a/tests/PhpWord/Style/ParagraphTest.php +++ b/tests/PhpWord/Style/ParagraphTest.php @@ -31,7 +31,7 @@ class ParagraphTest extends \PHPUnit\Framework\TestCase /** * Tear down after each test */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } @@ -177,11 +177,10 @@ public function testLineHeightValidation() /** * Test line height exception by using nonnumeric value - * - * @expectedException \PhpOffice\PhpWord\Exception\InvalidStyleException */ public function testLineHeightException() { + $this->expectException(\PhpOffice\PhpWord\Exception\InvalidStyleException::class); $object = new Paragraph(); $object->setLineHeight('a'); } diff --git a/tests/PhpWord/Style/SectionTest.php b/tests/PhpWord/Style/SectionTest.php index 59d18167cb..1e9741660b 100644 --- a/tests/PhpWord/Style/SectionTest.php +++ b/tests/PhpWord/Style/SectionTest.php @@ -35,14 +35,14 @@ public function testSettingValue() $oSettings = new Section(); $this->assertEquals('portrait', $oSettings->getOrientation()); - $this->assertEquals(Section::DEFAULT_WIDTH, $oSettings->getPageSizeW(), '', 0.000000001); - $this->assertEquals(Section::DEFAULT_HEIGHT, $oSettings->getPageSizeH(), '', 0.000000001); + $this->assertEqualsWithDelta(Section::DEFAULT_WIDTH, $oSettings->getPageSizeW(), 0.000000001); + $this->assertEqualsWithDelta(Section::DEFAULT_HEIGHT, $oSettings->getPageSizeH(), 0.000000001); $this->assertEquals('A4', $oSettings->getPaperSize()); $oSettings->setSettingValue('orientation', 'landscape'); $this->assertEquals('landscape', $oSettings->getOrientation()); - $this->assertEquals(Section::DEFAULT_HEIGHT, $oSettings->getPageSizeW(), '', 0.000000001); - $this->assertEquals(Section::DEFAULT_WIDTH, $oSettings->getPageSizeH(), '', 0.000000001); + $this->assertEqualsWithDelta(Section::DEFAULT_HEIGHT, $oSettings->getPageSizeW(), 0.000000001); + $this->assertEqualsWithDelta(Section::DEFAULT_WIDTH, $oSettings->getPageSizeH(), 0.000000001); $iVal = rand(1, 1000); $oSettings->setSettingValue('borderSize', $iVal); @@ -112,7 +112,7 @@ public function testPageWidth() // Section Settings $oSettings = new Section(); - $this->assertEquals(Section::DEFAULT_WIDTH, $oSettings->getPageSizeW(), '', 0.000000001); + $this->assertEqualsWithDelta(Section::DEFAULT_WIDTH, $oSettings->getPageSizeW(), 0.000000001); $iVal = rand(1, 1000); $oSettings->setSettingValue('pageSizeW', $iVal); $this->assertEquals($iVal, $oSettings->getPageSizeW()); @@ -126,7 +126,7 @@ public function testPageHeight() // Section Settings $oSettings = new Section(); - $this->assertEquals(Section::DEFAULT_HEIGHT, $oSettings->getPageSizeH(), '', 0.000000001); + $this->assertEqualsWithDelta(Section::DEFAULT_HEIGHT, $oSettings->getPageSizeH(), 0.000000001); $iVal = rand(1, 1000); $oSettings->setSettingValue('pageSizeH', $iVal); $this->assertEquals($iVal, $oSettings->getPageSizeH()); @@ -142,8 +142,8 @@ public function testOrientationLandscape() $oSettings->setLandscape(); $this->assertEquals('landscape', $oSettings->getOrientation()); - $this->assertEquals(Section::DEFAULT_HEIGHT, $oSettings->getPageSizeW(), '', 0.000000001); - $this->assertEquals(Section::DEFAULT_WIDTH, $oSettings->getPageSizeH(), '', 0.000000001); + $this->assertEqualsWithDelta(Section::DEFAULT_HEIGHT, $oSettings->getPageSizeW(), 0.000000001); + $this->assertEqualsWithDelta(Section::DEFAULT_WIDTH, $oSettings->getPageSizeH(), 0.000000001); } /** @@ -156,8 +156,8 @@ public function testOrientationPortrait() $oSettings->setPortrait(); $this->assertEquals('portrait', $oSettings->getOrientation()); - $this->assertEquals(Section::DEFAULT_WIDTH, $oSettings->getPageSizeW(), '', 0.000000001); - $this->assertEquals(Section::DEFAULT_HEIGHT, $oSettings->getPageSizeH(), '', 0.000000001); + $this->assertEqualsWithDelta(Section::DEFAULT_WIDTH, $oSettings->getPageSizeW(), 0.000000001); + $this->assertEqualsWithDelta(Section::DEFAULT_HEIGHT, $oSettings->getPageSizeH(), 0.000000001); } /** diff --git a/tests/PhpWord/Style/TextBoxTest.php b/tests/PhpWord/Style/TextBoxTest.php index 803189cd19..d583fc24ba 100644 --- a/tests/PhpWord/Style/TextBoxTest.php +++ b/tests/PhpWord/Style/TextBoxTest.php @@ -96,11 +96,10 @@ public function testSetStyleValue() /** * Test setWrappingStyle exception - * - * @expectedException \InvalidArgumentException */ public function testSetWrappingStyleException() { + $this->expectException(\InvalidArgumentException::class); $object = new TextBox(); $object->setWrappingStyle('foo'); } diff --git a/tests/PhpWord/TemplateProcessorTest.php b/tests/PhpWord/TemplateProcessorTest.php index 391daa2de8..13b6148d5b 100644 --- a/tests/PhpWord/TemplateProcessorTest.php +++ b/tests/PhpWord/TemplateProcessorTest.php @@ -134,12 +134,12 @@ final public function testXslStyleSheetCanBeApplied($actualDocumentFqfn) * XSL stylesheet cannot be applied on failure in setting parameter value. * * @covers ::applyXslStyleSheet - * @expectedException \PhpOffice\PhpWord\Exception\Exception - * @expectedExceptionMessage Could not set values for the given XSL style sheet parameters. * @test */ final public function testXslStyleSheetCanNotBeAppliedOnFailureOfSettingParameterValue() { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); + $this->expectExceptionMessage('Could not set values for the given XSL style sheet parameters.'); // Test is not needed for PHP 8.0, because internally validation throws TypeError exception. if (\PHP_VERSION_ID >= 80000) { $this->markTestSkipped('not needed for PHP 8.0'); @@ -161,12 +161,12 @@ final public function testXslStyleSheetCanNotBeAppliedOnFailureOfSettingParamete * XSL stylesheet can be applied on failure of loading XML from template. * * @covers ::applyXslStyleSheet - * @expectedException \PhpOffice\PhpWord\Exception\Exception - * @expectedExceptionMessage Could not load the given XML document. * @test */ final public function testXslStyleSheetCanNotBeAppliedOnFailureOfLoadingXmlFromTemplate() { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); + $this->expectExceptionMessage('Could not load the given XML document.'); $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/corrupted_main_document_part.docx'); $xslDomDocument = new \DOMDocument(); @@ -261,16 +261,16 @@ public function testCloneRowAndSetValues() ); $templateProcessor->setValue('tableHeader', 'My clonable table'); $templateProcessor->cloneRowAndSetValues('userId', $values); - $this->assertContains('Superman', $templateProcessor->getMainPart()); - $this->assertContains('Metropolis', $templateProcessor->getMainPart()); + $this->assertStringContainsString('Superman', $templateProcessor->getMainPart()); + $this->assertStringContainsString('Metropolis', $templateProcessor->getMainPart()); } /** - * @expectedException \Exception * @test */ public function testCloneNotExistingRowShouldThrowException() { + $this->expectException(\Exception::class); $mainPart = 'text'; $templateProcessor = new TestableTemplateProcesor($mainPart); @@ -384,7 +384,7 @@ public function testSetValues() $templateProcessor = new TestableTemplateProcesor($mainPart); $templateProcessor->setValues(array('firstname' => 'John', 'lastname' => 'Doe')); - $this->assertContains('Hello John Doe', $templateProcessor->getMainPart()); + $this->assertStringContainsString('Hello John Doe', $templateProcessor->getMainPart()); } /** @@ -425,15 +425,15 @@ public function testSetImageValue() } $this->assertNotEmpty($expectedImage, 'Embed image doesn\'t found.'); - $this->assertContains('/word/media/image_rId11_document.jpeg', $expectedContentTypesXml, '[Content_Types].xml missed "/word/media/image5_document.jpeg"'); - $this->assertContains('/word/_rels/header1.xml.rels', $expectedContentTypesXml, '[Content_Types].xml missed "/word/_rels/header1.xml.rels"'); - $this->assertContains('/word/_rels/footer1.xml.rels', $expectedContentTypesXml, '[Content_Types].xml missed "/word/_rels/footer1.xml.rels"'); - $this->assertNotContains('${documentContent}', $expectedMainPartXml, 'word/document.xml has no image.'); - $this->assertNotContains('${headerValue}', $expectedHeaderPartXml, 'word/header1.xml has no image.'); - $this->assertNotContains('${footerValue}', $expectedFooterPartXml, 'word/footer1.xml has no image.'); - $this->assertContains('media/image_rId11_document.jpeg', $expectedDocumentRelationsXml, 'word/_rels/document.xml.rels missed "media/image5_document.jpeg"'); - $this->assertContains('media/image_rId11_document.jpeg', $expectedHeaderRelationsXml, 'word/_rels/header1.xml.rels missed "media/image5_document.jpeg"'); - $this->assertContains('media/image_rId11_document.jpeg', $expectedFooterRelationsXml, 'word/_rels/footer1.xml.rels missed "media/image5_document.jpeg"'); + $this->assertStringContainsString('/word/media/image_rId11_document.jpeg', $expectedContentTypesXml, '[Content_Types].xml missed "/word/media/image5_document.jpeg"'); + $this->assertStringContainsString('/word/_rels/header1.xml.rels', $expectedContentTypesXml, '[Content_Types].xml missed "/word/_rels/header1.xml.rels"'); + $this->assertStringContainsString('/word/_rels/footer1.xml.rels', $expectedContentTypesXml, '[Content_Types].xml missed "/word/_rels/footer1.xml.rels"'); + $this->assertStringNotContainsString('${documentContent}', $expectedMainPartXml, 'word/document.xml has no image.'); + $this->assertStringNotContainsString('${headerValue}', $expectedHeaderPartXml, 'word/header1.xml has no image.'); + $this->assertStringNotContainsString('${footerValue}', $expectedFooterPartXml, 'word/footer1.xml has no image.'); + $this->assertStringContainsString('media/image_rId11_document.jpeg', $expectedDocumentRelationsXml, 'word/_rels/document.xml.rels missed "media/image5_document.jpeg"'); + $this->assertStringContainsString('media/image_rId11_document.jpeg', $expectedHeaderRelationsXml, 'word/_rels/header1.xml.rels missed "media/image5_document.jpeg"'); + $this->assertStringContainsString('media/image_rId11_document.jpeg', $expectedFooterRelationsXml, 'word/_rels/footer1.xml.rels missed "media/image5_document.jpeg"'); unlink($docName); @@ -463,7 +463,7 @@ public function testSetImageValue() } unlink($resultFileName); - $this->assertNotContains('${Test}', $expectedMainPartXml, 'word/document.xml has no image.'); + $this->assertStringNotContainsString('${Test}', $expectedMainPartXml, 'word/document.xml has no image.'); } /** @@ -640,9 +640,9 @@ public function testCloneBlockWithVariables() $templateProcessor = new TestableTemplateProcesor($mainPart); $templateProcessor->cloneBlock('CLONEME', 3, true, true); - $this->assertContains('Address ${address#1}, Street ${street#1}', $templateProcessor->getMainPart()); - $this->assertContains('Address ${address#2}, Street ${street#2}', $templateProcessor->getMainPart()); - $this->assertContains('Address ${address#3}, Street ${street#3}', $templateProcessor->getMainPart()); + $this->assertStringContainsString('Address ${address#1}, Street ${street#1}', $templateProcessor->getMainPart()); + $this->assertStringContainsString('Address ${address#2}, Street ${street#2}', $templateProcessor->getMainPart()); + $this->assertStringContainsString('Address ${address#3}, Street ${street#3}', $templateProcessor->getMainPart()); } public function testCloneBlockWithVariableReplacements() @@ -673,9 +673,9 @@ public function testCloneBlockWithVariableReplacements() $templateProcessor = new TestableTemplateProcesor($mainPart); $templateProcessor->cloneBlock('CLONEME', 0, true, false, $replacements); - $this->assertContains('City: London, Street: Baker Street', $templateProcessor->getMainPart()); - $this->assertContains('City: New York, Street: 5th Avenue', $templateProcessor->getMainPart()); - $this->assertContains('City: Rome, Street: Via della Conciliazione', $templateProcessor->getMainPart()); + $this->assertStringContainsString('City: London, Street: Baker Street', $templateProcessor->getMainPart()); + $this->assertStringContainsString('City: New York, Street: 5th Avenue', $templateProcessor->getMainPart()); + $this->assertStringContainsString('City: Rome, Street: Via della Conciliazione', $templateProcessor->getMainPart()); } /** @@ -846,9 +846,9 @@ public function testShouldMakeFieldsUpdateOnOpen() $templateProcessor = new TestableTemplateProcesor(null, $settingsPart); $templateProcessor->setUpdateFields(true); - $this->assertContains('', $templateProcessor->getSettingsPart()); + $this->assertStringContainsString('', $templateProcessor->getSettingsPart()); $templateProcessor->setUpdateFields(false); - $this->assertContains('', $templateProcessor->getSettingsPart()); + $this->assertStringContainsString('', $templateProcessor->getSettingsPart()); } } diff --git a/tests/PhpWord/Writer/HTML/ElementTest.php b/tests/PhpWord/Writer/HTML/ElementTest.php index 4eb92fe557..b6fde2e56a 100644 --- a/tests/PhpWord/Writer/HTML/ElementTest.php +++ b/tests/PhpWord/Writer/HTML/ElementTest.php @@ -160,7 +160,7 @@ public function testWriteTitleTextRun() $htmlWriter = new HTML($phpWord); $content = $htmlWriter->getContent(); - $this->assertContains($expected, $content); + $this->assertStringContainsString($expected, $content); } /** diff --git a/tests/PhpWord/Writer/HTML/PartTest.php b/tests/PhpWord/Writer/HTML/PartTest.php index f83034143c..15bdcaaa40 100644 --- a/tests/PhpWord/Writer/HTML/PartTest.php +++ b/tests/PhpWord/Writer/HTML/PartTest.php @@ -26,11 +26,10 @@ class PartTest extends \PHPUnit\Framework\TestCase { /** * Test get parent writer exception - * - * @expectedException \PhpOffice\PhpWord\Exception\Exception */ public function testGetParentWriterException() { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); $object = new Body(); $object->getParentWriter(); } diff --git a/tests/PhpWord/Writer/HTMLTest.php b/tests/PhpWord/Writer/HTMLTest.php index 24a8bca371..c4326ff584 100644 --- a/tests/PhpWord/Writer/HTMLTest.php +++ b/tests/PhpWord/Writer/HTMLTest.php @@ -41,12 +41,11 @@ public function testConstruct() /** * Construct with null - * - * @expectedException \PhpOffice\PhpWord\Exception\Exception - * @expectedExceptionMessage No PhpWord assigned. */ public function testConstructWithNull() { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); + $this->expectExceptionMessage('No PhpWord assigned.'); $object = new HTML(); $object->getPhpWord(); } diff --git a/tests/PhpWord/Writer/ODText/Element/ImageTest.php b/tests/PhpWord/Writer/ODText/Element/ImageTest.php index 2e0fdeefc0..7b9b038d24 100644 --- a/tests/PhpWord/Writer/ODText/Element/ImageTest.php +++ b/tests/PhpWord/Writer/ODText/Element/ImageTest.php @@ -30,7 +30,7 @@ class ImageTest extends \PHPUnit\Framework\TestCase /** * Executed after each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/ODText/ElementTest.php b/tests/PhpWord/Writer/ODText/ElementTest.php index 8b82734742..5a2535615b 100644 --- a/tests/PhpWord/Writer/ODText/ElementTest.php +++ b/tests/PhpWord/Writer/ODText/ElementTest.php @@ -30,7 +30,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase /** * Executed after each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/ODText/Part/AbstractPartTest.php b/tests/PhpWord/Writer/ODText/Part/AbstractPartTest.php index 3f0c81293d..9208ce6888 100644 --- a/tests/PhpWord/Writer/ODText/Part/AbstractPartTest.php +++ b/tests/PhpWord/Writer/ODText/Part/AbstractPartTest.php @@ -39,12 +39,11 @@ public function testSetGetParentWriter() /** * covers ::getParentWriter - * - * @expectedException \Exception - * @expectedExceptionMessage No parent WriterInterface assigned. */ public function testSetGetParentWriterNull() { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('No parent WriterInterface assigned.'); $object = $this->getMockForAbstractClass('PhpOffice\\PhpWord\\Writer\\ODText\\Part\\AbstractPart'); $object->getParentWriter(); } diff --git a/tests/PhpWord/Writer/ODText/Part/ContentTest.php b/tests/PhpWord/Writer/ODText/Part/ContentTest.php index 55d1a00e7f..015528d85f 100644 --- a/tests/PhpWord/Writer/ODText/Part/ContentTest.php +++ b/tests/PhpWord/Writer/ODText/Part/ContentTest.php @@ -31,7 +31,7 @@ class ContentTest extends \PHPUnit\Framework\TestCase /** * Executed before each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/ODText/Style/FontTest.php b/tests/PhpWord/Writer/ODText/Style/FontTest.php index 22a7151c98..92ad107adc 100644 --- a/tests/PhpWord/Writer/ODText/Style/FontTest.php +++ b/tests/PhpWord/Writer/ODText/Style/FontTest.php @@ -28,7 +28,7 @@ class FontTest extends \PHPUnit\Framework\TestCase /** * Executed after each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/ODText/Style/ParagraphTest.php b/tests/PhpWord/Writer/ODText/Style/ParagraphTest.php index 9ddb5fe1c3..f18528a4f4 100644 --- a/tests/PhpWord/Writer/ODText/Style/ParagraphTest.php +++ b/tests/PhpWord/Writer/ODText/Style/ParagraphTest.php @@ -29,7 +29,7 @@ class ParagraphTest extends \PHPUnit\Framework\TestCase /** * Executed after each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/ODText/Style/SectionTest.php b/tests/PhpWord/Writer/ODText/Style/SectionTest.php index d471c7f0e1..b93d210a42 100644 --- a/tests/PhpWord/Writer/ODText/Style/SectionTest.php +++ b/tests/PhpWord/Writer/ODText/Style/SectionTest.php @@ -28,7 +28,7 @@ class SectionTest extends \PHPUnit\Framework\TestCase /** * Executed after each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/ODTextTest.php b/tests/PhpWord/Writer/ODTextTest.php index a576a68d60..f24cd2abb0 100644 --- a/tests/PhpWord/Writer/ODTextTest.php +++ b/tests/PhpWord/Writer/ODTextTest.php @@ -51,12 +51,11 @@ public function testConstruct() /** * Construct with null - * - * @expectedException \PhpOffice\PhpWord\Exception\Exception - * @expectedExceptionMessage No PhpWord assigned. */ public function testConstructWithNull() { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); + $this->expectExceptionMessage('No PhpWord assigned.'); $object = new ODText(); $object->getPhpWord(); } @@ -135,11 +134,10 @@ public function testSetGetUseDiskCaching() /** * Use disk caching exception - * - * @expectedException \PhpOffice\PhpWord\Exception\Exception */ public function testSetUseDiskCachingException() { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); $dir = implode(DIRECTORY_SEPARATOR, array(PHPWORD_TESTS_BASE_DIR, 'foo')); $object = new ODText(); diff --git a/tests/PhpWord/Writer/PDFTest.php b/tests/PhpWord/Writer/PDFTest.php index f699385c8c..5eeab099bf 100644 --- a/tests/PhpWord/Writer/PDFTest.php +++ b/tests/PhpWord/Writer/PDFTest.php @@ -48,12 +48,11 @@ public function testConstruct() /** * Test construct exception - * - * @expectedException \PhpOffice\PhpWord\Exception\Exception - * @expectedExceptionMessage PDF rendering library or library path has not been defined. */ public function testConstructException() { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); + $this->expectExceptionMessage('PDF rendering library or library path has not been defined.'); $writer = new PDF(new PhpWord()); $writer->save(); } diff --git a/tests/PhpWord/Writer/RTFTest.php b/tests/PhpWord/Writer/RTFTest.php index 010720bd12..88ede4ad87 100644 --- a/tests/PhpWord/Writer/RTFTest.php +++ b/tests/PhpWord/Writer/RTFTest.php @@ -39,12 +39,11 @@ public function testConstruct() /** * Construct with null - * - * @expectedException \PhpOffice\PhpWord\Exception\Exception - * @expectedExceptionMessage No PhpWord assigned. */ public function testConstructWithNull() { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); + $this->expectExceptionMessage('No PhpWord assigned.'); $object = new RTF(); $object->getPhpWord(); } diff --git a/tests/PhpWord/Writer/Word2007/Element/ChartTest.php b/tests/PhpWord/Writer/Word2007/Element/ChartTest.php index a69838a9a3..26bc0bab2a 100644 --- a/tests/PhpWord/Writer/Word2007/Element/ChartTest.php +++ b/tests/PhpWord/Writer/Word2007/Element/ChartTest.php @@ -31,7 +31,7 @@ class ChartTest extends \PHPUnit\Framework\TestCase /** * Executed before each method of the class */ - public function setUp() + public function setUp(): void { $this->outputEscapingEnabled = Settings::isOutputEscapingEnabled(); } @@ -39,7 +39,7 @@ public function setUp() /** * Executed after each method of the class */ - public function tearDown() + public function tearDown(): void { Settings::setOutputEscapingEnabled($this->outputEscapingEnabled); TestHelperDOCX::clear(); diff --git a/tests/PhpWord/Writer/Word2007/Element/FormFieldTest.php b/tests/PhpWord/Writer/Word2007/Element/FormFieldTest.php index f3ee179037..bc2077b5c0 100644 --- a/tests/PhpWord/Writer/Word2007/Element/FormFieldTest.php +++ b/tests/PhpWord/Writer/Word2007/Element/FormFieldTest.php @@ -28,7 +28,7 @@ class FormFieldTest extends \PHPUnit\Framework\TestCase /** * Executed before each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/Word2007/ElementTest.php b/tests/PhpWord/Writer/Word2007/ElementTest.php index 38b1ba75ab..db6b9a1378 100644 --- a/tests/PhpWord/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Writer/Word2007/ElementTest.php @@ -32,7 +32,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase /** * Executed before each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/Word2007/Part/AbstractPartTest.php b/tests/PhpWord/Writer/Word2007/Part/AbstractPartTest.php index fac94882d2..3934001782 100644 --- a/tests/PhpWord/Writer/Word2007/Part/AbstractPartTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/AbstractPartTest.php @@ -40,12 +40,11 @@ public function testSetGetParentWriter() /** * covers ::getParentWriter - * - * @expectedException \Exception - * @expectedExceptionMessage No parent WriterInterface assigned. */ public function testSetGetParentWriterNull() { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('No parent WriterInterface assigned.'); $object = $this->getMockForAbstractClass('PhpOffice\\PhpWord\\Writer\\Word2007\\Part\\AbstractPart'); $object->getParentWriter(); } diff --git a/tests/PhpWord/Writer/Word2007/Part/CommentsTest.php b/tests/PhpWord/Writer/Word2007/Part/CommentsTest.php index 0233abdf2e..8ecf6abd39 100644 --- a/tests/PhpWord/Writer/Word2007/Part/CommentsTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/CommentsTest.php @@ -30,7 +30,7 @@ class CommentsTest extends \PHPUnit\Framework\TestCase /** * Executed before each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/Word2007/Part/DocumentTest.php b/tests/PhpWord/Writer/Word2007/Part/DocumentTest.php index b35f932770..07161d81de 100644 --- a/tests/PhpWord/Writer/Word2007/Part/DocumentTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/DocumentTest.php @@ -36,7 +36,7 @@ class DocumentTest extends \PHPUnit\Framework\TestCase /** * Executed before each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } @@ -407,7 +407,7 @@ public function testWriteImage() // behind $element = $doc->getElement('/w:document/w:body/w:p[2]/w:r/w:pict/v:shape'); $style = $element->getAttribute('style'); - $this->assertRegExp('/z\-index:\-[0-9]*/', $style); + $this->assertMatchesRegularExpression('/z\-index:\-[0-9]*/', $style); // square $element = $doc->getElement('/w:document/w:body/w:p[4]/w:r/w:pict/v:shape/w10:wrap'); diff --git a/tests/PhpWord/Writer/Word2007/Part/FootnotesTest.php b/tests/PhpWord/Writer/Word2007/Part/FootnotesTest.php index 4b0e94df30..8c6404ed84 100644 --- a/tests/PhpWord/Writer/Word2007/Part/FootnotesTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/FootnotesTest.php @@ -27,7 +27,7 @@ */ class FootnotesTest extends \PHPUnit\Framework\TestCase { - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/Word2007/Part/NumberingTest.php b/tests/PhpWord/Writer/Word2007/Part/NumberingTest.php index fb5a220e88..914d3fa17d 100644 --- a/tests/PhpWord/Writer/Word2007/Part/NumberingTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/NumberingTest.php @@ -34,7 +34,7 @@ class NumberingTest extends \PHPUnit\Framework\TestCase /** * Executed before each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php b/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php index d3c1c1dd35..045976e52b 100644 --- a/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php @@ -35,7 +35,7 @@ class SettingsTest extends \PHPUnit\Framework\TestCase /** * Executed before each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/Word2007/Part/StylesTest.php b/tests/PhpWord/Writer/Word2007/Part/StylesTest.php index 91f371841d..763f546865 100644 --- a/tests/PhpWord/Writer/Word2007/Part/StylesTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/StylesTest.php @@ -34,7 +34,7 @@ class StylesTest extends \PHPUnit\Framework\TestCase /** * Executed before each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/Word2007/PartTest.php b/tests/PhpWord/Writer/Word2007/PartTest.php index 277f61e1be..771b6d82d5 100644 --- a/tests/PhpWord/Writer/Word2007/PartTest.php +++ b/tests/PhpWord/Writer/Word2007/PartTest.php @@ -30,11 +30,11 @@ class PartTest extends \PHPUnit\Framework\TestCase * Test exception when no type or target assigned to a relation * * @covers \PhpOffice\PhpWord\Writer\Word2007\Part\Rels::writeRel - * @expectedException \PhpOffice\PhpWord\Exception\Exception - * @expectedExceptionMessage Invalid parameters passed. */ public function testRelsWriteRelException() { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); + $this->expectExceptionMessage('Invalid parameters passed.'); $object = new RelsPart(); $object->setMedia(array(array('type' => '', 'target' => ''))); $object->write(); diff --git a/tests/PhpWord/Writer/Word2007/Style/FontTest.php b/tests/PhpWord/Writer/Word2007/Style/FontTest.php index 41e52ab027..ae44d94332 100644 --- a/tests/PhpWord/Writer/Word2007/Style/FontTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/FontTest.php @@ -30,7 +30,7 @@ class FontTest extends \PHPUnit\Framework\TestCase /** * Executed before each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/Word2007/Style/ImageTest.php b/tests/PhpWord/Writer/Word2007/Style/ImageTest.php index c2cbfcae05..efeb0f2778 100644 --- a/tests/PhpWord/Writer/Word2007/Style/ImageTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/ImageTest.php @@ -31,7 +31,7 @@ class ImageTest extends \PHPUnit\Framework\TestCase /** * Executed before each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } @@ -63,10 +63,10 @@ public function testWrapping() $this->assertTrue($doc->elementExists($path)); $style = $doc->getElement($path)->getAttribute('style'); $this->assertNotNull($style); - $this->assertContains('mso-wrap-distance-left:10pt;', $style); - $this->assertContains('mso-wrap-distance-right:20pt;', $style); - $this->assertContains('mso-wrap-distance-top:30pt;', $style); - $this->assertContains('mso-wrap-distance-bottom:40pt;', $style); + $this->assertStringContainsString('mso-wrap-distance-left:10pt;', $style); + $this->assertStringContainsString('mso-wrap-distance-right:20pt;', $style); + $this->assertStringContainsString('mso-wrap-distance-top:30pt;', $style); + $this->assertStringContainsString('mso-wrap-distance-bottom:40pt;', $style); } /** @@ -97,9 +97,9 @@ public function testWrappingWithPosition() $this->assertTrue($doc->elementExists($path)); $style = $doc->getElement($path)->getAttribute('style'); $this->assertNotNull($style); - $this->assertContains('mso-wrap-distance-left:10pt;', $style); - $this->assertContains('mso-wrap-distance-right:20pt;', $style); - $this->assertContains('mso-wrap-distance-top:30pt;', $style); - $this->assertContains('mso-wrap-distance-bottom:40pt;', $style); + $this->assertStringContainsString('mso-wrap-distance-left:10pt;', $style); + $this->assertStringContainsString('mso-wrap-distance-right:20pt;', $style); + $this->assertStringContainsString('mso-wrap-distance-top:30pt;', $style); + $this->assertStringContainsString('mso-wrap-distance-bottom:40pt;', $style); } } diff --git a/tests/PhpWord/Writer/Word2007/Style/ParagraphTest.php b/tests/PhpWord/Writer/Word2007/Style/ParagraphTest.php index 843f98807f..119f997ff4 100644 --- a/tests/PhpWord/Writer/Word2007/Style/ParagraphTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/ParagraphTest.php @@ -31,7 +31,7 @@ class ParagraphTest extends \PHPUnit\Framework\TestCase /** * Executed before each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/Word2007/Style/SectionTest.php b/tests/PhpWord/Writer/Word2007/Style/SectionTest.php index 74e1eadd6b..d4909a9dc8 100644 --- a/tests/PhpWord/Writer/Word2007/Style/SectionTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/SectionTest.php @@ -31,7 +31,7 @@ class SectionTest extends \PHPUnit\Framework\TestCase /** * Executed before each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/Word2007/Style/TableTest.php b/tests/PhpWord/Writer/Word2007/Style/TableTest.php index 8e5cb63415..16bb6940cd 100644 --- a/tests/PhpWord/Writer/Word2007/Style/TableTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/TableTest.php @@ -34,7 +34,7 @@ class TableTest extends \PHPUnit\Framework\TestCase /** * Executed before each method of the class */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } diff --git a/tests/PhpWord/Writer/Word2007Test.php b/tests/PhpWord/Writer/Word2007Test.php index 563475b47b..1baf5592f1 100644 --- a/tests/PhpWord/Writer/Word2007Test.php +++ b/tests/PhpWord/Writer/Word2007Test.php @@ -32,7 +32,7 @@ class Word2007Test extends AbstractWebServerEmbeddedTest /** * Tear down after each test */ - public function tearDown() + public function tearDown(): void { TestHelperDOCX::clear(); } @@ -182,11 +182,10 @@ public function testSetGetUseDiskCaching() /** * Use disk caching exception - * - * @expectedException \PhpOffice\PhpWord\Exception\Exception */ public function testSetUseDiskCachingException() { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); $dir = implode(DIRECTORY_SEPARATOR, array(PHPWORD_TESTS_BASE_DIR, 'foo')); $object = new Word2007(); diff --git a/tests/PhpWord/_includes/AbstractWebServerEmbeddedTest.php b/tests/PhpWord/_includes/AbstractWebServerEmbeddedTest.php index bb010aa103..38fa493edb 100644 --- a/tests/PhpWord/_includes/AbstractWebServerEmbeddedTest.php +++ b/tests/PhpWord/_includes/AbstractWebServerEmbeddedTest.php @@ -23,7 +23,7 @@ abstract class AbstractWebServerEmbeddedTest extends \PHPUnit\Framework\TestCase { private static $httpServer; - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { $commandLine = 'php -S localhost:8080 -t tests/PhpWord/_files'; @@ -34,7 +34,7 @@ public static function setUpBeforeClass() } } - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { self::$httpServer->stop(); } diff --git a/tests/PhpWord/_includes/TestHelperDOCX.php b/tests/PhpWord/_includes/TestHelperDOCX.php index d35f0e3fa1..1f8e953a9c 100644 --- a/tests/PhpWord/_includes/TestHelperDOCX.php +++ b/tests/PhpWord/_includes/TestHelperDOCX.php @@ -76,7 +76,7 @@ public static function getDocument(PhpWord $phpWord, $writerName = 'Word2007') */ public static function clear() { - if (file_exists(self::$file)) { + if (self::$file && file_exists(self::$file)) { unlink(self::$file); } if (is_dir(Settings::getTempDir() . '/PhpWord_Unit_Test/')) { From 2bc75771ccdce9accdccf207c754cbcadab52746 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Fri, 16 Sep 2022 11:45:45 +0200 Subject: [PATCH 029/246] Use same code style as PhpSpreadsheet --- .php-cs-fixer.dist.php | 228 ++++++++ .php_cs.dist | 146 ----- samples/Sample_01_SimpleText.php | 39 +- samples/Sample_02_TabStops.php | 13 +- samples/Sample_03_Sections.php | 19 +- samples/Sample_04_Textrun.php | 17 +- samples/Sample_05_Multicolumn.php | 17 +- samples/Sample_06_Footnote.php | 11 +- samples/Sample_07_TemplateCloneRow.php | 37 +- samples/Sample_08_ParagraphPagination.php | 21 +- samples/Sample_09_Tables.php | 49 +- samples/Sample_10_EastAsianFontStyle.php | 5 +- samples/Sample_11_ReadWord2007.php | 1 + samples/Sample_11_ReadWord97.php | 1 + samples/Sample_12_HeaderFooter.php | 7 +- samples/Sample_13_Images.php | 61 ++- samples/Sample_14_ListItem.php | 47 +- samples/Sample_15_Link.php | 5 +- samples/Sample_16_Object.php | 1 + samples/Sample_17_TitleTOC.php | 15 +- samples/Sample_18_Watermark.php | 3 +- samples/Sample_19_TextBreak.php | 9 +- samples/Sample_20_BGColor.php | 7 +- samples/Sample_21_TableRowRules.php | 23 +- samples/Sample_22_CheckBox.php | 1 + samples/Sample_23_TemplateBlock.php | 3 +- samples/Sample_24_ReadODText.php | 1 + samples/Sample_25_TextBox.php | 21 +- samples/Sample_26_Html.php | 3 +- samples/Sample_27_Field.php | 31 +- samples/Sample_28_ReadRTF.php | 1 + samples/Sample_29_Line.php | 53 +- samples/Sample_30_ReadHTML.php | 1 + samples/Sample_31_Shape.php | 81 +-- samples/Sample_32_Chart.php | 43 +- samples/Sample_33_FormField.php | 3 +- samples/Sample_34_SDT.php | 5 +- samples/Sample_35_InternalLink.php | 1 + samples/Sample_36_RTL.php | 15 +- samples/Sample_37_Comments.php | 11 +- samples/Sample_38_Protection.php | 1 + samples/Sample_39_TrackChanges.php | 3 +- samples/Sample_40_TemplateSetComplexValue.php | 13 +- samples/Sample_41_TemplateSetChart.php | 19 +- samples/Sample_Header.php | 11 +- samples/index.php | 22 +- src/PhpWord/Collection/AbstractCollection.php | 20 +- src/PhpWord/Collection/Bookmarks.php | 4 +- src/PhpWord/Collection/Charts.php | 4 +- src/PhpWord/Collection/Comments.php | 4 +- src/PhpWord/Collection/Endnotes.php | 4 +- src/PhpWord/Collection/Footnotes.php | 4 +- src/PhpWord/Collection/Titles.php | 4 +- .../ComplexType/FootnoteProperties.php | 47 +- src/PhpWord/ComplexType/ProofState.php | 30 +- src/PhpWord/ComplexType/TblWidth.php | 2 +- src/PhpWord/ComplexType/TrackChangesView.php | 46 +- src/PhpWord/Element/AbstractContainer.php | 128 ++--- src/PhpWord/Element/AbstractElement.php | 142 +++-- src/PhpWord/Element/Bookmark.php | 12 +- src/PhpWord/Element/Cell.php | 16 +- src/PhpWord/Element/Chart.php | 38 +- src/PhpWord/Element/CheckBox.php | 13 +- src/PhpWord/Element/Comment.php | 33 +- src/PhpWord/Element/Endnote.php | 8 +- src/PhpWord/Element/Field.php | 158 +++--- src/PhpWord/Element/Footer.php | 24 +- src/PhpWord/Element/Footnote.php | 24 +- src/PhpWord/Element/FormField.php | 61 ++- src/PhpWord/Element/Header.php | 7 +- src/PhpWord/Element/Image.php | 117 ++-- src/PhpWord/Element/Line.php | 10 +- src/PhpWord/Element/Link.php | 44 +- src/PhpWord/Element/ListItem.php | 25 +- src/PhpWord/Element/ListItemRun.php | 38 +- src/PhpWord/Element/OLEObject.php | 36 +- src/PhpWord/Element/PageBreak.php | 6 +- src/PhpWord/Element/PreserveText.php | 30 +- src/PhpWord/Element/Row.php | 25 +- src/PhpWord/Element/SDT.php | 51 +- src/PhpWord/Element/Section.php | 64 +-- src/PhpWord/Element/Shape.php | 19 +- src/PhpWord/Element/TOC.php | 34 +- src/PhpWord/Element/Table.php | 40 +- src/PhpWord/Element/Text.php | 45 +- src/PhpWord/Element/TextBox.php | 10 +- src/PhpWord/Element/TextBreak.php | 46 +- src/PhpWord/Element/TextRun.php | 23 +- src/PhpWord/Element/Title.php | 23 +- src/PhpWord/Element/TrackChange.php | 29 +- src/PhpWord/Escaper/AbstractEscaper.php | 2 +- src/PhpWord/Escaper/EscaperInterface.php | 2 +- src/PhpWord/Escaper/RegExp.php | 2 +- src/PhpWord/Escaper/Rtf.php | 7 +- src/PhpWord/Escaper/Xml.php | 4 +- src/PhpWord/Exception/CopyFileException.php | 4 +- .../CreateTemporaryFileException.php | 4 +- src/PhpWord/Exception/Exception.php | 4 +- .../Exception/InvalidImageException.php | 4 +- .../Exception/InvalidObjectException.php | 4 +- .../Exception/InvalidStyleException.php | 4 +- .../UnsupportedImageTypeException.php | 4 +- src/PhpWord/IOFactory.php | 29 +- src/PhpWord/Media.php | 85 +-- src/PhpWord/Metadata/Compatibility.php | 12 +- src/PhpWord/Metadata/DocInfo.php | 159 +++--- src/PhpWord/Metadata/Protection.php | 44 +- src/PhpWord/Metadata/Settings.php | 112 ++-- src/PhpWord/PhpWord.php | 115 ++-- src/PhpWord/Reader/AbstractReader.php | 16 +- src/PhpWord/Reader/HTML.php | 11 +- src/PhpWord/Reader/MsDoc.php | 384 ++++++++----- src/PhpWord/Reader/ODText.php | 23 +- src/PhpWord/Reader/ODText/AbstractPart.php | 5 +- src/PhpWord/Reader/ODText/Content.php | 22 +- src/PhpWord/Reader/ODText/Meta.php | 23 +- src/PhpWord/Reader/RTF.php | 11 +- src/PhpWord/Reader/RTF/Document.php | 130 ++--- src/PhpWord/Reader/ReaderInterface.php | 7 +- src/PhpWord/Reader/Word2007.php | 53 +- src/PhpWord/Reader/Word2007/AbstractPart.php | 319 ++++++----- src/PhpWord/Reader/Word2007/DocPropsApp.php | 12 +- src/PhpWord/Reader/Word2007/DocPropsCore.php | 34 +- .../Reader/Word2007/DocPropsCustom.php | 8 +- src/PhpWord/Reader/Word2007/Document.php | 78 ++- src/PhpWord/Reader/Word2007/Endnotes.php | 8 +- src/PhpWord/Reader/Word2007/Footnotes.php | 20 +- src/PhpWord/Reader/Word2007/Numbering.php | 28 +- src/PhpWord/Reader/Word2007/Settings.php | 67 +-- src/PhpWord/Reader/Word2007/Styles.php | 15 +- src/PhpWord/Settings.php | 103 ++-- src/PhpWord/Shared/AbstractEnum.php | 28 +- src/PhpWord/Shared/Converter.php | 99 ++-- src/PhpWord/Shared/Drawing.php | 55 +- src/PhpWord/Shared/Html.php | 386 +++++++------ .../Shared/Microsoft/PasswordEncoder.php | 104 ++-- src/PhpWord/Shared/Text.php | 58 +- src/PhpWord/Shared/XMLReader.php | 107 ++-- src/PhpWord/Shared/XMLWriter.php | 34 +- src/PhpWord/Shared/ZipArchive.php | 83 +-- src/PhpWord/SimpleType/Border.php | 3 +- src/PhpWord/SimpleType/DocProtect.php | 15 +- src/PhpWord/SimpleType/Jc.php | 3 +- src/PhpWord/SimpleType/JcTable.php | 2 +- src/PhpWord/SimpleType/LineSpacingRule.php | 11 +- src/PhpWord/SimpleType/NumberFormat.php | 3 +- src/PhpWord/SimpleType/TblWidth.php | 5 +- src/PhpWord/SimpleType/TextAlignment.php | 5 +- src/PhpWord/SimpleType/VerticalJc.php | 2 +- src/PhpWord/SimpleType/Zoom.php | 5 +- src/PhpWord/Style.php | 49 +- src/PhpWord/Style/AbstractStyle.php | 99 ++-- src/PhpWord/Style/Border.php | 143 ++--- src/PhpWord/Style/Cell.php | 78 +-- src/PhpWord/Style/Chart.php | 140 ++--- src/PhpWord/Style/Extrusion.php | 26 +- src/PhpWord/Style/Fill.php | 15 +- src/PhpWord/Style/Font.php | 306 ++++++----- src/PhpWord/Style/Frame.php | 178 +++--- src/PhpWord/Style/Image.php | 64 +-- src/PhpWord/Style/Indentation.php | 60 +- src/PhpWord/Style/Language.php | 55 +- src/PhpWord/Style/Line.php | 75 +-- src/PhpWord/Style/LineNumbering.php | 45 +- src/PhpWord/Style/ListItem.php | 108 ++-- src/PhpWord/Style/Numbering.php | 31 +- src/PhpWord/Style/NumberingLevel.php | 101 ++-- src/PhpWord/Style/Outline.php | 91 ++-- src/PhpWord/Style/Paper.php | 43 +- src/PhpWord/Style/Paragraph.php | 240 ++++---- src/PhpWord/Style/Row.php | 33 +- src/PhpWord/Style/Section.php | 199 ++++--- src/PhpWord/Style/Shading.php | 37 +- src/PhpWord/Style/Shadow.php | 22 +- src/PhpWord/Style/Shape.php | 64 ++- src/PhpWord/Style/Spacing.php | 63 ++- src/PhpWord/Style/TOC.php | 35 +- src/PhpWord/Style/Tab.php | 51 +- src/PhpWord/Style/Table.php | 175 +++--- src/PhpWord/Style/TablePosition.php | 122 +++-- src/PhpWord/Style/TextBox.php | 58 +- src/PhpWord/Template.php | 2 +- src/PhpWord/TemplateProcessor.php | 238 ++++---- src/PhpWord/Writer/AbstractWriter.php | 92 ++-- src/PhpWord/Writer/HTML.php | 30 +- .../Writer/HTML/Element/AbstractElement.php | 18 +- src/PhpWord/Writer/HTML/Element/Bookmark.php | 6 +- src/PhpWord/Writer/HTML/Element/Container.php | 10 +- src/PhpWord/Writer/HTML/Element/Endnote.php | 6 +- src/PhpWord/Writer/HTML/Element/Footnote.php | 8 +- src/PhpWord/Writer/HTML/Element/Image.php | 6 +- src/PhpWord/Writer/HTML/Element/Link.php | 6 +- src/PhpWord/Writer/HTML/Element/ListItem.php | 6 +- .../Writer/HTML/Element/ListItemRun.php | 6 +- src/PhpWord/Writer/HTML/Element/PageBreak.php | 6 +- src/PhpWord/Writer/HTML/Element/Table.php | 27 +- src/PhpWord/Writer/HTML/Element/Text.php | 32 +- src/PhpWord/Writer/HTML/Element/TextBreak.php | 6 +- src/PhpWord/Writer/HTML/Element/TextRun.php | 6 +- src/PhpWord/Writer/HTML/Element/Title.php | 6 +- src/PhpWord/Writer/HTML/Part/AbstractPart.php | 7 +- src/PhpWord/Writer/HTML/Part/Body.php | 10 +- src/PhpWord/Writer/HTML/Part/Head.php | 64 +-- .../Writer/HTML/Style/AbstractStyle.php | 26 +- src/PhpWord/Writer/HTML/Style/Font.php | 10 +- src/PhpWord/Writer/HTML/Style/Generic.php | 8 +- src/PhpWord/Writer/HTML/Style/Image.php | 8 +- src/PhpWord/Writer/HTML/Style/Paragraph.php | 18 +- src/PhpWord/Writer/ODText.php | 30 +- .../Writer/ODText/Element/AbstractElement.php | 4 +- .../Writer/ODText/Element/Container.php | 6 +- src/PhpWord/Writer/ODText/Element/Field.php | 12 +- src/PhpWord/Writer/ODText/Element/Image.php | 8 +- src/PhpWord/Writer/ODText/Element/Link.php | 8 +- .../Writer/ODText/Element/PageBreak.php | 8 +- src/PhpWord/Writer/ODText/Element/Table.php | 22 +- src/PhpWord/Writer/ODText/Element/Text.php | 13 +- .../Writer/ODText/Element/TextBreak.php | 8 +- src/PhpWord/Writer/ODText/Element/TextRun.php | 8 +- src/PhpWord/Writer/ODText/Element/Title.php | 11 +- .../Writer/ODText/Part/AbstractPart.php | 16 +- src/PhpWord/Writer/ODText/Part/Content.php | 69 ++- src/PhpWord/Writer/ODText/Part/Manifest.php | 8 +- src/PhpWord/Writer/ODText/Part/Meta.php | 13 +- src/PhpWord/Writer/ODText/Part/Mimetype.php | 6 +- src/PhpWord/Writer/ODText/Part/Styles.php | 43 +- .../Writer/ODText/Style/AbstractStyle.php | 4 +- src/PhpWord/Writer/ODText/Style/Font.php | 6 +- src/PhpWord/Writer/ODText/Style/Image.php | 6 +- src/PhpWord/Writer/ODText/Style/Paragraph.php | 6 +- src/PhpWord/Writer/ODText/Style/Section.php | 6 +- src/PhpWord/Writer/ODText/Style/Table.php | 8 +- src/PhpWord/Writer/PDF.php | 21 +- src/PhpWord/Writer/PDF/AbstractRenderer.php | 50 +- src/PhpWord/Writer/PDF/DomPDF.php | 10 +- src/PhpWord/Writer/PDF/MPDF.php | 12 +- src/PhpWord/Writer/PDF/TCPDF.php | 9 +- src/PhpWord/Writer/RTF.php | 22 +- .../Writer/RTF/Element/AbstractElement.php | 19 +- src/PhpWord/Writer/RTF/Element/Container.php | 6 +- src/PhpWord/Writer/RTF/Element/Field.php | 4 +- src/PhpWord/Writer/RTF/Element/Image.php | 6 +- src/PhpWord/Writer/RTF/Element/Link.php | 6 +- src/PhpWord/Writer/RTF/Element/ListItem.php | 4 +- src/PhpWord/Writer/RTF/Element/PageBreak.php | 6 +- src/PhpWord/Writer/RTF/Element/Table.php | 23 +- src/PhpWord/Writer/RTF/Element/Text.php | 8 +- src/PhpWord/Writer/RTF/Element/TextBreak.php | 6 +- src/PhpWord/Writer/RTF/Element/TextRun.php | 6 +- src/PhpWord/Writer/RTF/Element/Title.php | 10 +- src/PhpWord/Writer/RTF/Part/AbstractPart.php | 6 +- src/PhpWord/Writer/RTF/Part/Document.php | 40 +- src/PhpWord/Writer/RTF/Part/Header.php | 34 +- .../Writer/RTF/Style/AbstractStyle.php | 4 +- src/PhpWord/Writer/RTF/Style/Border.php | 25 +- src/PhpWord/Writer/RTF/Style/Font.php | 11 +- src/PhpWord/Writer/RTF/Style/Indentation.php | 6 +- src/PhpWord/Writer/RTF/Style/Paragraph.php | 30 +- src/PhpWord/Writer/RTF/Style/Section.php | 6 +- src/PhpWord/Writer/RTF/Style/Tab.php | 12 +- src/PhpWord/Writer/Word2007.php | 110 ++-- .../Word2007/Element/AbstractElement.php | 54 +- .../Writer/Word2007/Element/Bookmark.php | 8 +- src/PhpWord/Writer/Word2007/Element/Chart.php | 10 +- .../Writer/Word2007/Element/CheckBox.php | 6 +- .../Writer/Word2007/Element/Container.php | 15 +- .../Writer/Word2007/Element/Endnote.php | 6 +- src/PhpWord/Writer/Word2007/Element/Field.php | 24 +- .../Writer/Word2007/Element/Footnote.php | 8 +- .../Writer/Word2007/Element/FormField.php | 21 +- src/PhpWord/Writer/Word2007/Element/Image.php | 10 +- src/PhpWord/Writer/Word2007/Element/Line.php | 6 +- src/PhpWord/Writer/Word2007/Element/Link.php | 6 +- .../Writer/Word2007/Element/ListItem.php | 6 +- .../Writer/Word2007/Element/ListItemRun.php | 20 +- .../Writer/Word2007/Element/OLEObject.php | 6 +- .../Writer/Word2007/Element/PageBreak.php | 6 +- .../Word2007/Element/ParagraphAlignment.php | 4 +- .../Writer/Word2007/Element/PreserveText.php | 8 +- src/PhpWord/Writer/Word2007/Element/SDT.php | 26 +- src/PhpWord/Writer/Word2007/Element/Shape.php | 47 +- src/PhpWord/Writer/Word2007/Element/TOC.php | 29 +- src/PhpWord/Writer/Word2007/Element/Table.php | 23 +- .../Word2007/Element/TableAlignment.php | 4 +- src/PhpWord/Writer/Word2007/Element/Text.php | 14 +- .../Writer/Word2007/Element/TextBox.php | 6 +- .../Writer/Word2007/Element/TextBreak.php | 6 +- .../Writer/Word2007/Element/TextRun.php | 6 +- src/PhpWord/Writer/Word2007/Element/Title.php | 6 +- .../Writer/Word2007/Part/AbstractPart.php | 23 +- src/PhpWord/Writer/Word2007/Part/Chart.php | 112 ++-- src/PhpWord/Writer/Word2007/Part/Comments.php | 16 +- .../Writer/Word2007/Part/ContentTypes.php | 34 +- .../Writer/Word2007/Part/DocPropsApp.php | 6 +- .../Writer/Word2007/Part/DocPropsCore.php | 6 +- .../Writer/Word2007/Part/DocPropsCustom.php | 15 +- src/PhpWord/Writer/Word2007/Part/Document.php | 18 +- src/PhpWord/Writer/Word2007/Part/Endnotes.php | 12 +- .../Writer/Word2007/Part/FontTable.php | 5 +- src/PhpWord/Writer/Word2007/Part/Footer.php | 13 +- .../Writer/Word2007/Part/Footnotes.php | 28 +- src/PhpWord/Writer/Word2007/Part/Header.php | 6 +- .../Writer/Word2007/Part/Numbering.php | 42 +- src/PhpWord/Writer/Word2007/Part/Rels.php | 35 +- .../Writer/Word2007/Part/RelsDocument.php | 20 +- src/PhpWord/Writer/Word2007/Part/RelsPart.php | 15 +- src/PhpWord/Writer/Word2007/Part/Settings.php | 200 +++---- src/PhpWord/Writer/Word2007/Part/Styles.php | 34 +- src/PhpWord/Writer/Word2007/Part/Theme.php | 21 +- .../Writer/Word2007/Part/WebSettings.php | 10 +- .../Writer/Word2007/Style/AbstractStyle.php | 53 +- src/PhpWord/Writer/Word2007/Style/Cell.php | 24 +- .../Writer/Word2007/Style/Extrusion.php | 6 +- src/PhpWord/Writer/Word2007/Style/Fill.php | 6 +- src/PhpWord/Writer/Word2007/Style/Font.php | 16 +- src/PhpWord/Writer/Word2007/Style/Frame.php | 58 +- src/PhpWord/Writer/Word2007/Style/Image.php | 4 +- .../Writer/Word2007/Style/Indentation.php | 10 +- src/PhpWord/Writer/Word2007/Style/Line.php | 23 +- .../Writer/Word2007/Style/LineNumbering.php | 8 +- .../Writer/Word2007/Style/MarginBorder.php | 37 +- src/PhpWord/Writer/Word2007/Style/Outline.php | 6 +- .../Writer/Word2007/Style/Paragraph.php | 24 +- src/PhpWord/Writer/Word2007/Style/Row.php | 8 +- src/PhpWord/Writer/Word2007/Style/Section.php | 34 +- src/PhpWord/Writer/Word2007/Style/Shading.php | 12 +- src/PhpWord/Writer/Word2007/Style/Shadow.php | 6 +- src/PhpWord/Writer/Word2007/Style/Shape.php | 8 +- src/PhpWord/Writer/Word2007/Style/Spacing.php | 14 +- src/PhpWord/Writer/Word2007/Style/Tab.php | 6 +- src/PhpWord/Writer/Word2007/Style/Table.php | 51 +- .../Writer/Word2007/Style/TablePosition.php | 32 +- src/PhpWord/Writer/Word2007/Style/TextBox.php | 8 +- src/PhpWord/Writer/WriterInterface.php | 6 +- tests/PhpWord/Collection/CollectionTest.php | 18 +- .../ComplexType/FootnotePropertiesTest.php | 36 +- tests/PhpWord/ComplexType/ProofStateTest.php | 26 +- tests/PhpWord/Element/AbstractElementTest.php | 18 +- tests/PhpWord/Element/BookmarkTest.php | 12 +- tests/PhpWord/Element/CellTest.php | 165 +++--- tests/PhpWord/Element/CheckBoxTest.php | 50 +- tests/PhpWord/Element/CommentTest.php | 71 +-- tests/PhpWord/Element/FieldTest.php | 120 ++-- tests/PhpWord/Element/FooterTest.php | 106 ++-- tests/PhpWord/Element/FootnoteTest.php | 64 +-- tests/PhpWord/Element/HeaderTest.php | 155 +++--- tests/PhpWord/Element/ImageTest.php | 194 +++---- tests/PhpWord/Element/LineTest.php | 53 +- tests/PhpWord/Element/LinkTest.php | 53 +- tests/PhpWord/Element/ListItemRunTest.php | 118 ++-- tests/PhpWord/Element/ListItemTest.php | 29 +- tests/PhpWord/Element/ObjectTest.php | 57 +- tests/PhpWord/Element/PageBreakTest.php | 11 +- tests/PhpWord/Element/PreserveTextTest.php | 36 +- tests/PhpWord/Element/RowTest.php | 39 +- tests/PhpWord/Element/SDTTest.php | 40 +- tests/PhpWord/Element/SectionTest.php | 83 +-- tests/PhpWord/Element/TOCTest.php | 54 +- tests/PhpWord/Element/TableTest.php | 63 +-- tests/PhpWord/Element/TextBoxTest.php | 41 +- tests/PhpWord/Element/TextBreakTest.php | 41 +- tests/PhpWord/Element/TextRunTest.php | 122 ++--- tests/PhpWord/Element/TextTest.php | 48 +- tests/PhpWord/Element/TitleTest.php | 31 +- tests/PhpWord/Element/TrackChangeTest.php | 32 +- tests/PhpWord/Escaper/RtfEscaper2Test.php | 28 +- .../Exception/CopyFileExceptionTest.php | 7 +- .../CreateTemporaryFileExceptionTest.php | 7 +- tests/PhpWord/Exception/ExceptionTest.php | 10 +- .../Exception/InvalidImageExceptionTest.php | 10 +- .../Exception/InvalidStyleExceptionTest.php | 10 +- .../UnsupportedImageTypeExceptionTest.php | 10 +- tests/PhpWord/IOFactoryTest.php | 30 +- tests/PhpWord/MediaTest.php | 65 +-- tests/PhpWord/Metadata/DocInfoTest.php | 170 +++--- tests/PhpWord/Metadata/SettingsTest.php | 123 ++--- tests/PhpWord/PhpWordTest.php | 119 ++-- tests/PhpWord/Reader/HTMLTest.php | 18 +- tests/PhpWord/Reader/MsDocTest.php | 36 +- tests/PhpWord/Reader/ODTextTest.php | 11 +- tests/PhpWord/Reader/RTFTest.php | 18 +- tests/PhpWord/Reader/Word2007/ElementTest.php | 132 ++--- tests/PhpWord/Reader/Word2007/PartTest.php | 66 +-- tests/PhpWord/Reader/Word2007/StyleTest.php | 124 ++--- tests/PhpWord/Reader/Word2007Test.php | 39 +- tests/PhpWord/SettingsTest.php | 195 +++---- tests/PhpWord/Shared/ConverterTest.php | 102 ++-- tests/PhpWord/Shared/DrawingTest.php | 108 ++-- tests/PhpWord/Shared/HtmlTest.php | 515 +++++++++--------- .../Shared/Microsoft/PasswordEncoderTest.php | 29 +- tests/PhpWord/Shared/TextTest.php | 74 +-- tests/PhpWord/Shared/XMLReaderTest.php | 79 +-- tests/PhpWord/Shared/XMLWriterTest.php | 18 +- tests/PhpWord/Shared/ZipArchiveTest.php | 38 +- tests/PhpWord/Style/AbstractStyleTest.php | 56 +- tests/PhpWord/Style/CellTest.php | 57 +- tests/PhpWord/Style/ChartTest.php | 139 ++--- tests/PhpWord/Style/FontTest.php | 162 +++--- tests/PhpWord/Style/ImageTest.php | 78 +-- tests/PhpWord/Style/IndentationTest.php | 26 +- tests/PhpWord/Style/LanguageTest.php | 37 +- tests/PhpWord/Style/LineNumberingTest.php | 26 +- tests/PhpWord/Style/LineTest.php | 87 +-- tests/PhpWord/Style/ListItemTest.php | 29 +- tests/PhpWord/Style/NumberingLevelTest.php | 38 +- tests/PhpWord/Style/NumberingTest.php | 28 +- tests/PhpWord/Style/PaperTest.php | 34 +- tests/PhpWord/Style/ParagraphTest.php | 112 ++-- tests/PhpWord/Style/RowTest.php | 35 +- tests/PhpWord/Style/SectionTest.php | 261 ++++----- tests/PhpWord/Style/ShadingTest.php | 24 +- tests/PhpWord/Style/SpacingTest.php | 26 +- tests/PhpWord/Style/TOCTest.php | 24 +- tests/PhpWord/Style/TabTest.php | 24 +- tests/PhpWord/Style/TablePositionTest.php | 42 +- tests/PhpWord/Style/TableTest.php | 156 +++--- tests/PhpWord/Style/TextBoxTest.php | 204 +++---- tests/PhpWord/StyleTest.php | 77 ++- tests/PhpWord/TemplateProcessorTest.php | 334 ++++++------ tests/PhpWord/Writer/HTML/ElementTest.php | 107 ++-- tests/PhpWord/Writer/HTML/PartTest.php | 8 +- tests/PhpWord/Writer/HTML/StyleTest.php | 12 +- tests/PhpWord/Writer/HTMLTest.php | 40 +- .../Writer/ODText/Element/ImageTest.php | 30 +- tests/PhpWord/Writer/ODText/ElementTest.php | 138 ++--- .../Writer/ODText/Part/AbstractPartTest.php | 17 +- .../Writer/ODText/Part/ContentTest.php | 34 +- .../PhpWord/Writer/ODText/Style/FontTest.php | 212 +++---- .../Writer/ODText/Style/ParagraphTest.php | 374 ++++++------- .../Writer/ODText/Style/SectionTest.php | 202 +++---- tests/PhpWord/Writer/ODText/StyleTest.php | 12 +- tests/PhpWord/Writer/ODTextTest.php | 60 +- tests/PhpWord/Writer/PDF/DomPDFTest.php | 22 +- tests/PhpWord/Writer/PDF/MPDFTest.php | 10 +- tests/PhpWord/Writer/PDF/TCPDFTest.php | 10 +- tests/PhpWord/Writer/PDFTest.php | 14 +- tests/PhpWord/Writer/RTF/ElementTest.php | 54 +- tests/PhpWord/Writer/RTF/HeaderFooterTest.php | 40 +- tests/PhpWord/Writer/RTF/StyleTest.php | 48 +- tests/PhpWord/Writer/RTFTest.php | 38 +- .../Writer/Word2007/Element/ChartTest.php | 120 ++-- .../Writer/Word2007/Element/FormFieldTest.php | 34 +- tests/PhpWord/Writer/Word2007/ElementTest.php | 363 ++++++------ .../Writer/Word2007/Part/AbstractPartTest.php | 18 +- .../Writer/Word2007/Part/CommentsTest.php | 23 +- .../Writer/Word2007/Part/DocumentTest.php | 323 +++++------ .../Writer/Word2007/Part/FooterTest.php | 11 +- .../Writer/Word2007/Part/FootnotesTest.php | 15 +- .../Writer/Word2007/Part/HeaderTest.php | 10 +- .../Writer/Word2007/Part/NumberingTest.php | 50 +- .../Writer/Word2007/Part/SettingsTest.php | 188 +++---- .../Writer/Word2007/Part/StylesTest.php | 43 +- tests/PhpWord/Writer/Word2007/PartTest.php | 10 +- .../Writer/Word2007/Style/FontTest.php | 93 ++-- .../Writer/Word2007/Style/ImageTest.php | 79 +-- .../Writer/Word2007/Style/ParagraphTest.php | 43 +- .../Writer/Word2007/Style/SectionTest.php | 19 +- .../Writer/Word2007/Style/TableTest.php | 89 +-- tests/PhpWord/Writer/Word2007/StyleTest.php | 30 +- tests/PhpWord/Writer/Word2007Test.php | 98 ++-- .../PhpWord/_includes/AbstractTestReader.php | 30 +- .../AbstractWebServerEmbeddedTest.php | 2 +- tests/PhpWord/_includes/TestHelperDOCX.php | 22 +- .../_includes/TestableTemplateProcesor.php | 4 +- tests/PhpWord/_includes/XmlDocument.php | 66 ++- tests/bootstrap.php | 6 +- 466 files changed, 10885 insertions(+), 10175 deletions(-) create mode 100644 .php-cs-fixer.dist.php delete mode 100644 .php_cs.dist diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000000..14d58dac68 --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,228 @@ +notName('pclzip.lib.php') + ->notName('OLERead.php') + ->in('samples') + ->in('src') + ->in('tests'); + +$config = new PhpCsFixer\Config(); +$config + ->setRiskyAllowed(true) + ->setFinder($finder) + ->setCacheFile(sys_get_temp_dir() . '/php-cs-fixer' . preg_replace('~\W~', '-', __DIR__)) + ->setRules([ + 'align_multiline_comment' => true, + 'array_indentation' => true, + 'array_syntax' => ['syntax' => 'short'], + 'backtick_to_shell_exec' => true, + 'binary_operator_spaces' => true, + 'blank_line_after_namespace' => true, + 'blank_line_after_opening_tag' => true, + 'blank_line_before_statement' => true, + 'braces' => true, + 'cast_spaces' => true, + 'class_attributes_separation' => ['elements' => ['method' => 'one', 'property' => 'one']], // const are often grouped with other related const + 'class_definition' => false, + 'class_keyword_remove' => false, // ::class keyword gives us better support in IDE + 'combine_consecutive_issets' => true, + 'combine_consecutive_unsets' => true, + 'combine_nested_dirname' => true, + 'comment_to_phpdoc' => false, // interferes with annotations + 'compact_nullable_typehint' => true, + 'concat_space' => ['spacing' => 'one'], + 'constant_case' => true, + 'date_time_immutable' => false, // Break our unit tests + 'declare_equal_normalize' => true, + 'declare_strict_types' => false, // Too early to adopt strict types + 'dir_constant' => true, + 'doctrine_annotation_array_assignment' => true, + 'doctrine_annotation_braces' => true, + 'doctrine_annotation_indentation' => true, + 'doctrine_annotation_spaces' => true, + 'elseif' => true, + 'encoding' => true, + 'ereg_to_preg' => true, + 'escape_implicit_backslashes' => true, + 'explicit_indirect_variable' => false, // I feel it makes the code actually harder to read + 'explicit_string_variable' => false, // I feel it makes the code actually harder to read + 'final_class' => false, // We need non-final classes + 'final_internal_class' => true, + 'final_public_method_for_abstract_class' => false, // We need non-final methods + 'fopen_flag_order' => true, + 'fopen_flags' => true, + 'full_opening_tag' => true, + 'fully_qualified_strict_types' => true, + 'function_declaration' => true, + 'function_to_constant' => true, + 'function_typehint_space' => true, + 'general_phpdoc_annotation_remove' => ['annotations' => ['access', 'category', 'copyright', 'throws']], + 'global_namespace_import' => true, + 'header_comment' => false, // We don't use common header in all our files + 'heredoc_indentation' => false, // Requires PHP >= 7.3 + 'heredoc_to_nowdoc' => false, // Not sure about this one + 'implode_call' => true, + 'include' => true, + 'increment_style' => true, + 'indentation_type' => true, + 'is_null' => true, + 'line_ending' => true, + 'linebreak_after_opening_tag' => true, + 'list_syntax' => ['syntax' => 'short'], + 'logical_operators' => true, + 'lowercase_cast' => true, + 'lowercase_keywords' => true, + 'lowercase_static_reference' => true, + 'magic_constant_casing' => true, + 'magic_method_casing' => true, + 'mb_str_functions' => false, // No, too dangerous to change that + 'method_argument_space' => true, + 'method_chaining_indentation' => true, + 'modernize_types_casting' => true, + 'multiline_comment_opening_closing' => true, + 'multiline_whitespace_before_semicolons' => true, + 'native_constant_invocation' => false, // Micro optimization that look messy + 'native_function_casing' => true, + 'native_function_invocation' => false, // I suppose this would be best, but I am still unconvinced about the visual aspect of it + 'native_function_type_declaration_casing' => true, + 'new_with_braces' => true, + 'no_alias_functions' => true, + 'no_alternative_syntax' => true, + 'no_binary_string' => true, + 'no_blank_lines_after_class_opening' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_blank_lines_before_namespace' => false, // we want 1 blank line before namespace + 'no_break_comment' => true, + 'no_closing_tag' => true, + 'no_empty_comment' => true, + 'no_empty_phpdoc' => true, + 'no_empty_statement' => true, + 'no_extra_blank_lines' => true, + 'no_homoglyph_names' => true, + 'no_leading_import_slash' => true, + 'no_leading_namespace_whitespace' => true, + 'no_mixed_echo_print' => true, + 'no_multiline_whitespace_around_double_arrow' => true, + 'no_null_property_initialization' => true, + 'no_php4_constructor' => true, + 'no_short_bool_cast' => true, + 'echo_tag_syntax' => ['format' => 'long'], + 'no_singleline_whitespace_before_semicolons' => true, + 'no_spaces_after_function_name' => true, + 'no_spaces_around_offset' => true, + 'no_spaces_inside_parenthesis' => true, + 'no_superfluous_elseif' => false, // Might be risky on a huge code base + 'no_superfluous_phpdoc_tags' => ['allow_mixed' => true], + 'no_trailing_comma_in_list_call' => true, + 'no_trailing_comma_in_singleline_array' => true, + 'no_trailing_whitespace' => true, + 'no_trailing_whitespace_in_comment' => true, + 'no_unneeded_control_parentheses' => true, + 'no_unneeded_curly_braces' => true, + 'no_unneeded_final_method' => true, + 'no_unreachable_default_argument_value' => true, + 'no_unset_cast' => true, + 'no_unset_on_property' => true, + 'no_unused_imports' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'no_whitespace_before_comma_in_array' => true, + 'no_whitespace_in_blank_line' => true, + 'non_printable_character' => true, + 'normalize_index_brace' => true, + 'not_operator_with_space' => false, // No we prefer to keep '!' without spaces + 'not_operator_with_successor_space' => false, // idem + 'nullable_type_declaration_for_default_null_value' => true, + 'object_operator_without_whitespace' => true, + 'ordered_class_elements' => false, // We prefer to keep some freedom + 'ordered_imports' => true, + 'ordered_interfaces' => true, + 'php_unit_construct' => true, + 'php_unit_dedicate_assert' => true, + 'php_unit_dedicate_assert_internal_type' => true, + 'php_unit_expectation' => true, + 'php_unit_fqcn_annotation' => true, + 'php_unit_internal_class' => false, // Because tests are excluded from package + 'php_unit_method_casing' => true, + 'php_unit_mock' => true, + 'php_unit_mock_short_will_return' => true, + 'php_unit_namespaced' => true, + 'php_unit_no_expectation_annotation' => true, + 'phpdoc_order_by_value' => ['annotations' => ['covers']], + 'php_unit_set_up_tear_down_visibility' => true, + 'php_unit_size_class' => false, // That seems extra work to maintain for little benefits + 'php_unit_strict' => false, // We sometime actually need assertEquals + 'php_unit_test_annotation' => true, + 'php_unit_test_case_static_method_calls' => ['call_type' => 'self'], + 'php_unit_test_class_requires_covers' => false, // We don't care as much as we should about coverage + 'phpdoc_add_missing_param_annotation' => false, // Don't add things that bring no value + 'phpdoc_align' => false, // Waste of time + 'phpdoc_annotation_without_dot' => true, + 'phpdoc_indent' => true, + //'phpdoc_inline_tag' => true, + 'phpdoc_line_span' => false, // Unfortunately our old comments turn even uglier with this + 'phpdoc_no_access' => true, + 'phpdoc_no_alias_tag' => true, + 'phpdoc_no_empty_return' => true, + 'phpdoc_no_package' => true, + 'phpdoc_no_useless_inheritdoc' => true, + 'phpdoc_order' => true, + 'phpdoc_return_self_reference' => true, + 'phpdoc_scalar' => true, + 'phpdoc_separation' => true, + 'phpdoc_single_line_var_spacing' => true, + 'phpdoc_summary' => true, + 'phpdoc_to_comment' => false, // interferes with annotations + 'phpdoc_to_param_type' => false, // Because experimental, but interesting for one shot use + 'phpdoc_to_return_type' => false, // idem + 'phpdoc_trim' => true, + 'phpdoc_trim_consecutive_blank_line_separation' => true, + 'phpdoc_types' => true, + 'phpdoc_types_order' => true, + 'phpdoc_var_annotation_correct_order' => true, + 'phpdoc_var_without_name' => true, + 'pow_to_exponentiation' => true, + 'protected_to_private' => true, + //'psr0' => true, + //'psr4' => true, + 'random_api_migration' => true, + 'return_assignment' => false, // Sometimes useful for clarity or debug + 'return_type_declaration' => true, + 'self_accessor' => true, + 'self_static_accessor' => true, + 'semicolon_after_instruction' => false, // Buggy in `samples/index.php` + 'set_type_to_cast' => true, + 'short_scalar_cast' => true, + 'simple_to_complex_string_variable' => false, // Would differ from TypeScript without obvious advantages + 'simplified_null_return' => false, // Even if technically correct we prefer to be explicit + 'single_blank_line_at_eof' => true, + 'single_blank_line_before_namespace' => true, + 'single_class_element_per_statement' => true, + 'single_import_per_statement' => true, + 'single_line_after_imports' => true, + 'single_line_comment_style' => true, + 'single_line_throw' => false, // I don't see any reason for having a special case for Exception + 'single_quote' => true, + 'single_trait_insert_per_statement' => true, + 'space_after_semicolon' => true, + 'standardize_increment' => true, + 'standardize_not_equals' => true, + 'static_lambda' => false, // Risky if we can't guarantee nobody use `bindTo()` + 'strict_comparison' => false, // No, too dangerous to change that + 'strict_param' => false, // No, too dangerous to change that + 'string_line_ending' => true, + 'switch_case_semicolon_to_colon' => true, + 'switch_case_space' => true, + 'ternary_operator_spaces' => true, + 'ternary_to_null_coalescing' => true, + 'trailing_comma_in_multiline' => true, + 'trim_array_spaces' => true, + 'unary_operator_spaces' => true, + 'visibility_required' => ['elements' => ['property', 'method']], // not const + 'void_return' => true, + 'whitespace_after_comma_in_array' => true, + 'yoda_style' => false, + ]); + +return $config; diff --git a/.php_cs.dist b/.php_cs.dist deleted file mode 100644 index 895ed80f56..0000000000 --- a/.php_cs.dist +++ /dev/null @@ -1,146 +0,0 @@ -notName('pclzip.lib.php') - ->notName('OLERead.php') - ->in('samples') - ->in('src') - ->in('tests'); - -return PhpCsFixer\Config::create() - ->setRiskyAllowed(true) - ->setFinder($finder) - ->setRules(array( - 'array_syntax' => array('syntax' => 'long'), - 'binary_operator_spaces' => array('align_double_arrow' => true), - 'blank_line_after_namespace' => true, - 'blank_line_after_opening_tag' => false, - 'blank_line_before_return' => true, - 'braces' => true, - 'cast_spaces' => true, - 'class_definition' => true, - 'class_keyword_remove' => false, // ::class keyword gives us beter support in IDE - 'combine_consecutive_unsets' => true, - 'concat_space' => array('spacing' => 'one'), - 'declare_equal_normalize' => true, - 'declare_strict_types' => false, // Too early to adopt strict types - 'dir_constant' => true, - 'elseif' => true, - 'encoding' => true, - 'ereg_to_preg' => true, - 'full_opening_tag' => true, - 'function_declaration' => true, - 'function_typehint_space' => true, - 'general_phpdoc_annotation_remove' => false, // No use for that - 'hash_to_slash_comment' => true, - 'header_comment' => false, // We don't use common header in all our files - 'heredoc_to_nowdoc' => false, // Not sure about this one - 'is_null' => false, // Risky - 'include' => true, - 'indentation_type' => true, - 'line_ending' => true, - 'linebreak_after_opening_tag' => true, - 'lowercase_cast' => true, - 'lowercase_constants' => true, - 'lowercase_keywords' => true, - 'mb_str_functions' => false, // No, too dangerous to change that - 'method_argument_space' => true, - 'method_separation' => true, - 'modernize_types_casting' => true, - 'native_function_casing' => true, - 'native_function_invocation'=> false, // This is risky and seems to be micro-optimization that make code uglier so not worth it, at least for now - 'new_with_braces' => true, - 'no_alias_functions' => true, - 'no_blank_lines_after_class_opening' => true, - 'no_blank_lines_after_phpdoc' => true, - 'no_blank_lines_before_namespace' => false, // we want 1 blank line before namespace - 'no_closing_tag' => true, - 'no_empty_comment' => true, - 'no_empty_phpdoc' => true, - 'no_empty_statement' => true, - 'no_extra_consecutive_blank_lines' => array('break', 'continue', 'extra', 'return', 'throw', 'use', 'useTrait', 'curly_brace_block', 'parenthesis_brace_block', 'square_brace_block'), - 'no_leading_import_slash' => true, - 'no_leading_namespace_whitespace' => true, - 'no_mixed_echo_print' => true, - 'no_multiline_whitespace_around_double_arrow' => true, - 'no_multiline_whitespace_before_semicolons' => true, - 'no_php4_constructor' => true, - 'no_short_bool_cast' => true, - 'no_short_echo_tag' => true, - 'no_singleline_whitespace_before_semicolons' => true, - 'no_spaces_after_function_name' => true, - 'no_spaces_around_offset' => true, - 'no_spaces_inside_parenthesis' => true, - 'no_trailing_comma_in_list_call' => true, - 'no_trailing_comma_in_singleline_array' => true, - 'no_trailing_whitespace' => true, - 'no_trailing_whitespace_in_comment' => true, - 'no_unneeded_control_parentheses' => true, - 'no_unreachable_default_argument_value' => true, - 'no_unused_imports' => true, - 'no_useless_else' => true, - 'no_useless_return' => true, - 'no_whitespace_before_comma_in_array' => true, - 'no_whitespace_in_blank_line' => true, - 'normalize_index_brace' => true, - 'not_operator_with_space' => false, // No we prefer to keep '!' without spaces - 'not_operator_with_successor_space' => false, // idem - 'object_operator_without_whitespace' => true, - 'ordered_class_elements' => false, // We prefer to keep some freedom - 'ordered_imports' => true, - 'php_unit_construct' => true, - 'php_unit_dedicate_assert' => true, - 'php_unit_fqcn_annotation' => true, - 'php_unit_strict' => false, // We sometime actually need assertEquals - 'phpdoc_add_missing_param_annotation' => true, - 'phpdoc_align' => false, // Waste of time - 'phpdoc_annotation_without_dot' => true, - 'phpdoc_indent' => true, - 'phpdoc_inline_tag' => true, - 'phpdoc_no_access' => true, - 'phpdoc_no_alias_tag' => true, - 'phpdoc_no_empty_return' => true, - 'phpdoc_no_package' => true, - 'phpdoc_no_useless_inheritdoc' => true, - 'phpdoc_order' => true, - 'phpdoc_return_self_reference' => true, - 'phpdoc_scalar' => true, - 'phpdoc_separation' => false, - 'phpdoc_single_line_var_spacing' => true, - 'phpdoc_summary' => false, - 'phpdoc_to_comment' => true, - 'phpdoc_trim' => true, - 'phpdoc_types' => true, - 'phpdoc_var_without_name' => true, - 'pow_to_exponentiation' => false, - 'pre_increment' => false, - 'protected_to_private' => true, - 'psr0' => true, - 'psr4' => true, - 'random_api_migration' => false, // This breaks our unit tests - 'return_type_declaration' => true, - 'self_accessor' => true, - 'semicolon_after_instruction' => false, // Buggy in `samples/index.php` - 'short_scalar_cast' => true, - 'silenced_deprecation_error' => true, - 'simplified_null_return' => false, // While technically correct we prefer to be explicit when returning null - 'single_blank_line_at_eof' => true, - 'single_blank_line_before_namespace' => true, - 'single_class_element_per_statement' => true, - 'single_import_per_statement' => true, - 'single_line_after_imports' => true, - 'single_quote' => true, - 'space_after_semicolon' => true, - 'standardize_not_equals' => true, - 'strict_comparison' => false, // No, too dangerous to change that - 'strict_param' => false, // No, too dangerous to change that - 'switch_case_semicolon_to_colon' => true, - 'switch_case_space' => true, - 'ternary_operator_spaces' => true, - 'ternary_to_null_coalescing' => false, // Cannot use that with PHP 5.6 - 'trailing_comma_in_multiline_array' => true, - 'trim_array_spaces' => false, - 'unary_operator_spaces' => true, - 'visibility_required' => true, - 'whitespace_after_comma_in_array' => true, - )); diff --git a/samples/Sample_01_SimpleText.php b/samples/Sample_01_SimpleText.php index 8af44d20aa..e89f7323ba 100644 --- a/samples/Sample_01_SimpleText.php +++ b/samples/Sample_01_SimpleText.php @@ -1,4 +1,5 @@ getSettings()->setThemeFontLang($languageEnGb); $fontStyleName = 'rStyle'; -$phpWord->addFontStyle($fontStyleName, array('bold' => true, 'italic' => true, 'size' => 16, 'allCaps' => true, 'doubleStrikethrough' => true)); +$phpWord->addFontStyle($fontStyleName, ['bold' => true, 'italic' => true, 'size' => 16, 'allCaps' => true, 'doubleStrikethrough' => true]); $paragraphStyleName = 'pStyle'; -$phpWord->addParagraphStyle($paragraphStyleName, array('alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER, 'spaceAfter' => 100)); +$phpWord->addParagraphStyle($paragraphStyleName, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER, 'spaceAfter' => 100]); -$phpWord->addTitleStyle(1, array('bold' => true), array('spaceAfter' => 240)); +$phpWord->addTitleStyle(1, ['bold' => true], ['spaceAfter' => 240]); // New portrait section $section = $phpWord->addSection(); @@ -28,7 +29,7 @@ // $pStyle = new Font(); // $pStyle->setLang() -$section->addText('Ce texte-ci est en français.', array('lang' => \PhpOffice\PhpWord\Style\Language::FR_BE)); +$section->addText('Ce texte-ci est en français.', ['lang' => \PhpOffice\PhpWord\Style\Language::FR_BE]); // Two text break $section->addTextBreak(2); @@ -47,33 +48,33 @@ $textrun = $section->addTextRun(); $textrun->addText('I am inline styled ', $fontStyle); $textrun->addText('with '); -$textrun->addText('color', array('color' => '996699')); +$textrun->addText('color', ['color' => '996699']); $textrun->addText(', '); -$textrun->addText('bold', array('bold' => true)); +$textrun->addText('bold', ['bold' => true]); $textrun->addText(', '); -$textrun->addText('italic', array('italic' => true)); +$textrun->addText('italic', ['italic' => true]); $textrun->addText(', '); -$textrun->addText('underline', array('underline' => 'dash')); +$textrun->addText('underline', ['underline' => 'dash']); $textrun->addText(', '); -$textrun->addText('strikethrough', array('strikethrough' => true)); +$textrun->addText('strikethrough', ['strikethrough' => true]); $textrun->addText(', '); -$textrun->addText('doubleStrikethrough', array('doubleStrikethrough' => true)); +$textrun->addText('doubleStrikethrough', ['doubleStrikethrough' => true]); $textrun->addText(', '); -$textrun->addText('superScript', array('superScript' => true)); +$textrun->addText('superScript', ['superScript' => true]); $textrun->addText(', '); -$textrun->addText('subScript', array('subScript' => true)); +$textrun->addText('subScript', ['subScript' => true]); $textrun->addText(', '); -$textrun->addText('smallCaps', array('smallCaps' => true)); +$textrun->addText('smallCaps', ['smallCaps' => true]); $textrun->addText(', '); -$textrun->addText('allCaps', array('allCaps' => true)); +$textrun->addText('allCaps', ['allCaps' => true]); $textrun->addText(', '); -$textrun->addText('fgColor', array('fgColor' => 'yellow')); +$textrun->addText('fgColor', ['fgColor' => 'yellow']); $textrun->addText(', '); -$textrun->addText('scale', array('scale' => 200)); +$textrun->addText('scale', ['scale' => 200]); $textrun->addText(', '); -$textrun->addText('spacing', array('spacing' => 120)); +$textrun->addText('spacing', ['spacing' => 120]); $textrun->addText(', '); -$textrun->addText('kerning', array('kerning' => 10)); +$textrun->addText('kerning', ['kerning' => 10]); $textrun->addText('. '); // Link @@ -81,7 +82,7 @@ $section->addTextBreak(); // Image -$section->addImage('resources/_earth.jpg', array('width'=>18, 'height'=>18)); +$section->addImage('resources/_earth.jpg', ['width' => 18, 'height' => 18]); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_02_TabStops.php b/samples/Sample_02_TabStops.php index 4f588ee7b8..74a0ed1fa3 100644 --- a/samples/Sample_02_TabStops.php +++ b/samples/Sample_02_TabStops.php @@ -1,4 +1,5 @@ addParagraphStyle( $multipleTabsStyleName, - array( - 'tabs' => array( + [ + 'tabs' => [ new \PhpOffice\PhpWord\Style\Tab('left', 1550), new \PhpOffice\PhpWord\Style\Tab('center', 3200), new \PhpOffice\PhpWord\Style\Tab('right', 5300), - ), - ) + ], + ] ); $rightTabStyleName = 'rightTab'; -$phpWord->addParagraphStyle($rightTabStyleName, array('tabs' => array(new \PhpOffice\PhpWord\Style\Tab('right', 9090)))); +$phpWord->addParagraphStyle($rightTabStyleName, ['tabs' => [new \PhpOffice\PhpWord\Style\Tab('right', 9090)]]); $leftTabStyleName = 'centerTab'; -$phpWord->addParagraphStyle($leftTabStyleName, array('tabs' => array(new \PhpOffice\PhpWord\Style\Tab('center', 4680)))); +$phpWord->addParagraphStyle($leftTabStyleName, ['tabs' => [new \PhpOffice\PhpWord\Style\Tab('center', 4680)]]); // New portrait section $section = $phpWord->addSection(); diff --git a/samples/Sample_03_Sections.php b/samples/Sample_03_Sections.php index 5bb9ecc2e4..b02a277c43 100644 --- a/samples/Sample_03_Sections.php +++ b/samples/Sample_03_Sections.php @@ -1,4 +1,5 @@ addSection(array('borderColor' => '00FF00', 'borderSize' => 12)); +$section = $phpWord->addSection(['borderColor' => '00FF00', 'borderSize' => 12]); $section->addText('I am placed on a default section.'); // New landscape section -$section = $phpWord->addSection(array('orientation' => 'landscape')); +$section = $phpWord->addSection(['orientation' => 'landscape']); $section->addText('I am placed on a landscape section. Every page starting from this section will be landscape style.'); $section->addPageBreak(); $section->addPageBreak(); // New portrait section $section = $phpWord->addSection( - array('paperSize' => 'Folio', 'marginLeft' => 600, 'marginRight' => 600, 'marginTop' => 600, 'marginBottom' => 600) + ['paperSize' => 'Folio', 'marginLeft' => 600, 'marginRight' => 600, 'marginTop' => 600, 'marginBottom' => 600] ); $section->addText('This section uses other margins with folio papersize.'); // The text of this section is vertically centered $section = $phpWord->addSection( - array('vAlign' => VerticalJc::CENTER) + ['vAlign' => VerticalJc::CENTER] ); $section->addText('This section is vertically centered.'); // New portrait section with Header & Footer $section = $phpWord->addSection( - array( - 'marginLeft' => 200, - 'marginRight' => 200, - 'marginTop' => 200, + [ + 'marginLeft' => 200, + 'marginRight' => 200, + 'marginTop' => 200, 'marginBottom' => 200, 'headerHeight' => 50, 'footerHeight' => 50, - ) + ] ); $section->addText('This section and we play with header/footer height.'); $section->addHeader()->addText('Header'); diff --git a/samples/Sample_04_Textrun.php b/samples/Sample_04_Textrun.php index ecd0c88a9f..33af08a5b4 100644 --- a/samples/Sample_04_Textrun.php +++ b/samples/Sample_04_Textrun.php @@ -1,4 +1,5 @@ addParagraphStyle($paragraphStyleName, array('spacing' => 100)); +$phpWord->addParagraphStyle($paragraphStyleName, ['spacing' => 100]); $boldFontStyleName = 'BoldText'; -$phpWord->addFontStyle($boldFontStyleName, array('bold' => true)); +$phpWord->addFontStyle($boldFontStyleName, ['bold' => true]); $coloredFontStyleName = 'ColoredText'; -$phpWord->addFontStyle($coloredFontStyleName, array('color' => 'FF8080', 'bgColor' => 'FFFFCC')); +$phpWord->addFontStyle($coloredFontStyleName, ['color' => 'FF8080', 'bgColor' => 'FFFFCC']); $linkFontStyleName = 'NLink'; -$phpWord->addLinkStyle($linkFontStyleName, array('color' => '0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE)); +$phpWord->addLinkStyle($linkFontStyleName, ['color' => '0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE]); // New portrait section $section = $phpWord->addSection(); @@ -26,21 +27,21 @@ $textrun->addText('Each textrun can contain native text, link elements or an image.'); $textrun->addText(' No break is placed after adding an element.', $boldFontStyleName); $textrun->addText(' Both '); -$textrun->addText('superscript', array('superScript' => true)); +$textrun->addText('superscript', ['superScript' => true]); $textrun->addText(' and '); -$textrun->addText('subscript', array('subScript' => true)); +$textrun->addText('subscript', ['subScript' => true]); $textrun->addText(' are also available.'); $textrun->addText(' All elements are placed inside a paragraph with the optionally given paragraph style.', $coloredFontStyleName); $textrun->addText(' Sample Link: '); $textrun->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub', $linkFontStyleName); $textrun->addText(' Sample Image: '); -$textrun->addImage('resources/_earth.jpg', array('width' => 18, 'height' => 18)); +$textrun->addImage('resources/_earth.jpg', ['width' => 18, 'height' => 18]); $textrun->addText(' Sample Object: '); $textrun->addObject('resources/_sheet.xls'); $textrun->addText(' Here is some more text. '); $textrun = $section->addTextRun(); -$textrun->addText('This text is not visible.', array('hidden' => true)); +$textrun->addText('This text is not visible.', ['hidden' => true]); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_05_Multicolumn.php b/samples/Sample_05_Multicolumn.php index f7cefa58d3..093dd60424 100644 --- a/samples/Sample_05_Multicolumn.php +++ b/samples/Sample_05_Multicolumn.php @@ -1,4 +1,5 @@ addSection( - array( - 'colsNum' => 2, + [ + 'colsNum' => 2, 'colsSpace' => 1440, 'breakType' => 'continuous', - ) + ] ); $section->addText("Two columns, one inch (1440 twips) spacing. {$filler}"); // Normal -$section = $phpWord->addSection(array('breakType' => 'continuous')); +$section = $phpWord->addSection(['breakType' => 'continuous']); $section->addText("Normal paragraph again. {$filler}"); // Three columns $section = $phpWord->addSection( - array( - 'colsNum' => 3, + [ + 'colsNum' => 3, 'colsSpace' => 720, 'breakType' => 'continuous', - ) + ] ); $section->addText("Three columns, half inch (720 twips) spacing. {$filler}"); // Normal -$section = $phpWord->addSection(array('breakType' => 'continuous')); +$section = $phpWord->addSection(['breakType' => 'continuous']); $section->addText("Normal paragraph again. {$filler}"); // Save file diff --git a/samples/Sample_06_Footnote.php b/samples/Sample_06_Footnote.php index 19d6a52462..f3c369b342 100644 --- a/samples/Sample_06_Footnote.php +++ b/samples/Sample_06_Footnote.php @@ -1,4 +1,5 @@ addParagraphStyle($paragraphStyleName, array('spacing' => 100)); +$phpWord->addParagraphStyle($paragraphStyleName, ['spacing' => 100]); $boldFontStyleName = 'BoldText'; -$phpWord->addFontStyle($boldFontStyleName, array('bold' => true)); +$phpWord->addFontStyle($boldFontStyleName, ['bold' => true]); $coloredFontStyleName = 'ColoredText'; -$phpWord->addFontStyle($coloredFontStyleName, array('color' => 'FF8080', 'bgColor' => 'FFFFCC')); +$phpWord->addFontStyle($coloredFontStyleName, ['color' => 'FF8080', 'bgColor' => 'FFFFCC']); $linkFontStyleName = 'NLink'; -$phpWord->addLinkStyle($linkFontStyleName, array('color' => '0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE)); +$phpWord->addLinkStyle($linkFontStyleName, ['color' => '0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE]); // New portrait section $section = $phpWord->addSection(); @@ -38,7 +39,7 @@ $footnote->addText('links like '); $footnote->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub', $linkFontStyleName); $footnote->addText(', image like '); -$footnote->addImage('resources/_earth.jpg', array('width' => 18, 'height' => 18)); +$footnote->addImage('resources/_earth.jpg', ['width' => 18, 'height' => 18]); $footnote->addText(', or object like '); $footnote->addObject('resources/_sheet.xls'); $footnote->addText('But you can only put footnote in section, not in header or footer.'); diff --git a/samples/Sample_07_TemplateCloneRow.php b/samples/Sample_07_TemplateCloneRow.php index 42c53269e8..a921569f64 100644 --- a/samples/Sample_07_TemplateCloneRow.php +++ b/samples/Sample_07_TemplateCloneRow.php @@ -1,4 +1,5 @@ setValue('rowNumber#10', '10'); // Table with a spanned cell -$values = array( - array( - 'userId' => 1, +$values = [ + [ + 'userId' => 1, 'userFirstName' => 'James', - 'userName' => 'Taylor', - 'userPhone' => '+1 428 889 773', - ), - array( - 'userId' => 2, + 'userName' => 'Taylor', + 'userPhone' => '+1 428 889 773', + ], + [ + 'userId' => 2, 'userFirstName' => 'Robert', - 'userName' => 'Bell', - 'userPhone' => '+1 428 889 774', - ), - array( - 'userId' => 3, + 'userName' => 'Bell', + 'userPhone' => '+1 428 889 774', + ], + [ + 'userId' => 3, 'userFirstName' => 'Michael', - 'userName' => 'Ray', - 'userPhone' => '+1 428 889 775', - ), -); + 'userName' => 'Ray', + 'userPhone' => '+1 428 889 775', + ], +]; $templateProcessor->cloneRowAndSetValues('userId', $values); @@ -80,7 +81,7 @@ echo date('H:i:s'), ' Saving the result document...', EOL; $templateProcessor->saveAs('results/Sample_07_TemplateCloneRow.docx'); -echo getEndingNotes(array('Word2007' => 'docx'), 'results/Sample_07_TemplateCloneRow.docx'); +echo getEndingNotes(['Word2007' => 'docx'], 'results/Sample_07_TemplateCloneRow.docx'); if (!CLI) { include_once 'Sample_Footer.php'; } diff --git a/samples/Sample_08_ParagraphPagination.php b/samples/Sample_08_ParagraphPagination.php index 3c21b138fc..f343366a84 100644 --- a/samples/Sample_08_ParagraphPagination.php +++ b/samples/Sample_08_ParagraphPagination.php @@ -1,15 +1,16 @@ setDefaultParagraphStyle( - array( - 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::BOTH, + [ + 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::BOTH, 'spaceAfter' => \PhpOffice\PhpWord\Shared\Converter::pointToTwip(12), - 'spacing' => 120, - ) + 'spacing' => 120, + ] ); // New section @@ -19,8 +20,8 @@ 'Below are the samples on how to control your paragraph ' . 'pagination. See "Line and Page Break" tab on paragraph properties ' . 'window to see the attribute set by these controls.', - array('bold' => true), - array('space' => array('before' => 360, 'after' => 480)) + ['bold' => true], + ['space' => ['before' => 360, 'after' => 480]] ); $section->addText( @@ -30,7 +31,7 @@ . 'itself at the bottom of a page. Set this option to "false" if you want ' . 'to disable this automatic control.', null, - array('widowControl' => false, 'indentation' => array('left' => 240, 'right' => 120)) + ['widowControl' => false, 'indentation' => ['left' => 240, 'right' => 120]] ); $section->addText( @@ -39,7 +40,7 @@ . 'breaks between paragraphs. Set this option to "true" if you do not want ' . 'your paragraph to be separated with the next paragraph.', null, - array('keepNext' => true, 'indentation' => array('firstLine' => 240)) + ['keepNext' => true, 'indentation' => ['firstLine' => 240]] ); $section->addText( @@ -48,7 +49,7 @@ . 'break within a paragraph. Set this option to "true" if you do not want ' . 'all lines of your paragraph to be in the same page.', null, - array('keepLines' => true, 'indentation' => array('left' => 240, 'hanging' => 240)) + ['keepLines' => true, 'indentation' => ['left' => 240, 'hanging' => 240]] ); $section->addText('Keep scrolling. More below.'); @@ -59,7 +60,7 @@ . 'your paragraph into the next page. This option is most useful for ' . 'heading styles.', null, - array('pageBreakBefore' => true) + ['pageBreakBefore' => true] ); // Save file diff --git a/samples/Sample_09_Tables.php b/samples/Sample_09_Tables.php index 3115543865..f1b67c9ecc 100644 --- a/samples/Sample_09_Tables.php +++ b/samples/Sample_09_Tables.php @@ -1,4 +1,5 @@ addSection(); -$header = array('size' => 16, 'bold' => true); +$header = ['size' => 16, 'bold' => true]; // 1. Basic table @@ -17,9 +18,9 @@ $section->addText('Basic table', $header); $table = $section->addTable(); -for ($r = 1; $r <= $rows; $r++) { +for ($r = 1; $r <= $rows; ++$r) { $table->addRow(); - for ($c = 1; $c <= $cols; $c++) { + for ($c = 1; $c <= $cols; ++$c) { $table->addCell(1750)->addText("Row {$r}, Cell {$c}"); } } @@ -30,11 +31,11 @@ $section->addText('Fancy table', $header); $fancyTableStyleName = 'Fancy Table'; -$fancyTableStyle = array('borderSize' => 6, 'borderColor' => '006699', 'cellMargin' => 80, 'alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER, 'cellSpacing' => 50); -$fancyTableFirstRowStyle = array('borderBottomSize' => 18, 'borderBottomColor' => '0000FF', 'bgColor' => '66BBFF'); -$fancyTableCellStyle = array('valign' => 'center'); -$fancyTableCellBtlrStyle = array('valign' => 'center', 'textDirection' => \PhpOffice\PhpWord\Style\Cell::TEXT_DIR_BTLR); -$fancyTableFontStyle = array('bold' => true); +$fancyTableStyle = ['borderSize' => 6, 'borderColor' => '006699', 'cellMargin' => 80, 'alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER, 'cellSpacing' => 50]; +$fancyTableFirstRowStyle = ['borderBottomSize' => 18, 'borderBottomColor' => '0000FF', 'bgColor' => '66BBFF']; +$fancyTableCellStyle = ['valign' => 'center']; +$fancyTableCellBtlrStyle = ['valign' => 'center', 'textDirection' => \PhpOffice\PhpWord\Style\Cell::TEXT_DIR_BTLR]; +$fancyTableFontStyle = ['bold' => true]; $phpWord->addTableStyle($fancyTableStyleName, $fancyTableStyle, $fancyTableFirstRowStyle); $table = $section->addTable($fancyTableStyleName); $table->addRow(900); @@ -43,7 +44,7 @@ $table->addCell(2000, $fancyTableCellStyle)->addText('Row 3', $fancyTableFontStyle); $table->addCell(2000, $fancyTableCellStyle)->addText('Row 4', $fancyTableFontStyle); $table->addCell(500, $fancyTableCellBtlrStyle)->addText('Row 5', $fancyTableFontStyle); -for ($i = 1; $i <= 8; $i++) { +for ($i = 1; $i <= 8; ++$i) { $table->addRow(); $table->addCell(2000)->addText("Cell {$i}"); $table->addCell(2000)->addText("Cell {$i}"); @@ -65,12 +66,12 @@ $section->addPageBreak(); $section->addText('Table with colspan and rowspan', $header); -$fancyTableStyle = array('borderSize' => 6, 'borderColor' => '999999'); -$cellRowSpan = array('vMerge' => 'restart', 'valign' => 'center', 'bgColor' => 'FFFF00'); -$cellRowContinue = array('vMerge' => 'continue'); -$cellColSpan = array('gridSpan' => 2, 'valign' => 'center'); -$cellHCentered = array('alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER); -$cellVCentered = array('valign' => 'center'); +$fancyTableStyle = ['borderSize' => 6, 'borderColor' => '999999']; +$cellRowSpan = ['vMerge' => 'restart', 'valign' => 'center', 'bgColor' => 'FFFF00']; +$cellRowContinue = ['vMerge' => 'continue']; +$cellColSpan = ['gridSpan' => 2, 'valign' => 'center']; +$cellHCentered = ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]; +$cellVCentered = ['valign' => 'center']; $spanTableStyleName = 'Colspan Rowspan'; $phpWord->addTableStyle($spanTableStyleName, $fancyTableStyle); @@ -111,22 +112,22 @@ $section->addPageBreak(); $section->addText('Table with colspan and rowspan', $header); -$styleTable = array('borderSize' => 6, 'borderColor' => '999999'); +$styleTable = ['borderSize' => 6, 'borderColor' => '999999']; $phpWord->addTableStyle('Colspan Rowspan', $styleTable); $table = $section->addTable('Colspan Rowspan'); $row = $table->addRow(); -$row->addCell(1000, array('vMerge' => 'restart'))->addText('A'); -$row->addCell(1000, array('gridSpan' => 2, 'vMerge' => 'restart'))->addText('B'); +$row->addCell(1000, ['vMerge' => 'restart'])->addText('A'); +$row->addCell(1000, ['gridSpan' => 2, 'vMerge' => 'restart'])->addText('B'); $row->addCell(1000)->addText('1'); $row = $table->addRow(); -$row->addCell(1000, array('vMerge' => 'continue')); -$row->addCell(1000, array('vMerge' => 'continue', 'gridSpan' => 2)); +$row->addCell(1000, ['vMerge' => 'continue']); +$row->addCell(1000, ['vMerge' => 'continue', 'gridSpan' => 2]); $row->addCell(1000)->addText('2'); $row = $table->addRow(); -$row->addCell(1000, array('vMerge' => 'continue')); +$row->addCell(1000, ['vMerge' => 'continue']); $row->addCell(1000)->addText('C'); $row->addCell(1000)->addText('D'); $row->addCell(1000)->addText('3'); @@ -136,10 +137,10 @@ $section->addTextBreak(2); $section->addText('Nested table in a centered and 50% width table.', $header); -$table = $section->addTable(array('width' => 50 * 50, 'unit' => 'pct', 'alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER)); +$table = $section->addTable(['width' => 50 * 50, 'unit' => 'pct', 'alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER]); $cell = $table->addRow()->addCell(); $cell->addText('This cell contains nested table.'); -$innerCell = $cell->addTable(array('alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER))->addRow()->addCell(); +$innerCell = $cell->addTable(['alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER])->addRow()->addCell(); $innerCell->addText('Inside nested table'); // 6. Table with floating position @@ -147,7 +148,7 @@ $section->addTextBreak(2); $section->addText('Table with floating positioning.', $header); -$table = $section->addTable(array('borderSize' => 6, 'borderColor' => '999999', 'position' => array('vertAnchor' => TablePosition::VANCHOR_TEXT, 'bottomFromText' => Converter::cmToTwip(1)))); +$table = $section->addTable(['borderSize' => 6, 'borderColor' => '999999', 'position' => ['vertAnchor' => TablePosition::VANCHOR_TEXT, 'bottomFromText' => Converter::cmToTwip(1)]]); $cell = $table->addRow()->addCell(); $cell->addText('This is a single cell.'); diff --git a/samples/Sample_10_EastAsianFontStyle.php b/samples/Sample_10_EastAsianFontStyle.php index 87345ae0e8..c8a6ec3a5e 100644 --- a/samples/Sample_10_EastAsianFontStyle.php +++ b/samples/Sample_10_EastAsianFontStyle.php @@ -1,13 +1,14 @@ addSection(); -$header = array('size' => 16, 'bold' => true); +$header = ['size' => 16, 'bold' => true]; //1.Use EastAisa FontStyle -$section->addText('中文楷体样式测试', array('name' => '楷体', 'size' => 16, 'color' => '1B2232', 'lang' => array('latin' => 'en-US', 'eastAsia' => 'zh-CN'))); +$section->addText('中文楷体样式测试', ['name' => '楷体', 'size' => 16, 'color' => '1B2232', 'lang' => ['latin' => 'en-US', 'eastAsia' => 'zh-CN']]); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_11_ReadWord2007.php b/samples/Sample_11_ReadWord2007.php index c0b54c7a49..313cc00797 100644 --- a/samples/Sample_11_ReadWord2007.php +++ b/samples/Sample_11_ReadWord2007.php @@ -1,4 +1,5 @@ addTextRun(); $textrun->addText('This is the header with '); $textrun->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub'); -$table->addCell(4500)->addImage('resources/PhpWord.png', array('width' => 80, 'height' => 80, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::END)); +$table->addCell(4500)->addImage('resources/PhpWord.png', ['width' => 80, 'height' => 80, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::END]); // Add header for all other pages $subsequent = $section->addHeader(); $subsequent->addText('Subsequent pages in Section 1 will Have this!'); -$subsequent->addImage('resources/_mars.jpg', array('width' => 80, 'height' => 80)); +$subsequent->addImage('resources/_mars.jpg', ['width' => 80, 'height' => 80]); // Add footer $footer = $section->addFooter(); -$footer->addPreserveText('Page {PAGE} of {NUMPAGES}.', null, array('alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER)); +$footer->addPreserveText('Page {PAGE} of {NUMPAGES}.', null, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $footer->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub'); // Write some text diff --git a/samples/Sample_13_Images.php b/samples/Sample_13_Images.php index f7be3be969..30b9cae949 100644 --- a/samples/Sample_13_Images.php +++ b/samples/Sample_13_Images.php @@ -1,4 +1,5 @@ addText('Local image with styles:'); -$section->addImage('resources/_earth.jpg', array('width' => 210, 'height' => 210, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER)); +$section->addImage('resources/_earth.jpg', ['width' => 210, 'height' => 210, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); // Remote image printSeparator($section); @@ -33,21 +34,21 @@ //Wrapping style printSeparator($section); $text = str_repeat('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ', 2); -$wrappingStyles = array('inline', 'behind', 'infront', 'square', 'tight'); +$wrappingStyles = ['inline', 'behind', 'infront', 'square', 'tight']; foreach ($wrappingStyles as $wrappingStyle) { $section->addText("Wrapping style {$wrappingStyle}"); $section->addImage( 'resources/_earth.jpg', - array( - 'positioning' => 'relative', - 'marginTop' => -1, - 'marginLeft' => 1, - 'width' => 80, - 'height' => 80, - 'wrappingStyle' => $wrappingStyle, - 'wrapDistanceRight' => Converter::cmToPoint(1), + [ + 'positioning' => 'relative', + 'marginTop' => -1, + 'marginLeft' => 1, + 'width' => 80, + 'height' => 80, + 'wrappingStyle' => $wrappingStyle, + 'wrapDistanceRight' => Converter::cmToPoint(1), 'wrapDistanceBottom' => Converter::cmToPoint(1), - ) + ] ); $section->addText($text); printSeparator($section); @@ -57,16 +58,16 @@ $section->addText('Absolute positioning: see top right corner of page'); $section->addImage( 'resources/_mars.jpg', - array( - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), - 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_ABSOLUTE, - 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_RIGHT, + [ + 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), + 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), + 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_ABSOLUTE, + 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_RIGHT, 'posHorizontalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_PAGE, - 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_PAGE, - 'marginLeft' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(15.5), - 'marginTop' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(1.55), - ) + 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_PAGE, + 'marginLeft' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(15.5), + 'marginTop' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(1.55), + ] ); //Relative positioning @@ -75,21 +76,21 @@ $section->addText('Vertical position top relative to line'); $section->addImage( 'resources/_mars.jpg', - array( - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), - 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE, - 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_CENTER, + [ + 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), + 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), + 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE, + 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_CENTER, 'posHorizontalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_COLUMN, - 'posVertical' => \PhpOffice\PhpWord\Style\Image::POSITION_VERTICAL_TOP, - 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_LINE, - ) + 'posVertical' => \PhpOffice\PhpWord\Style\Image::POSITION_VERTICAL_TOP, + 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_LINE, + ] ); -function printSeparator(Section $section) +function printSeparator(Section $section): void { $section->addTextBreak(); - $lineStyle = array('weight' => 0.2, 'width' => 150, 'height' => 0, 'align' => 'center'); + $lineStyle = ['weight' => 0.2, 'width' => 150, 'height' => 0, 'align' => 'center']; $section->addLine($lineStyle); $section->addTextBreak(2); } diff --git a/samples/Sample_14_ListItem.php b/samples/Sample_14_ListItem.php index f40e9f6fb9..3b509f3577 100644 --- a/samples/Sample_14_ListItem.php +++ b/samples/Sample_14_ListItem.php @@ -1,4 +1,5 @@ addFontStyle($fontStyleName, array('color' => 'FF0000')); +$phpWord->addFontStyle($fontStyleName, ['color' => 'FF0000']); $paragraphStyleName = 'P-Style'; -$phpWord->addParagraphStyle($paragraphStyleName, array('spaceAfter' => 95)); +$phpWord->addParagraphStyle($paragraphStyleName, ['spaceAfter' => 95]); $multilevelNumberingStyleName = 'multilevel'; $phpWord->addNumberingStyle( $multilevelNumberingStyleName, - array( - 'type' => 'multilevel', - 'levels' => array( - array('format' => 'decimal', 'text' => '%1.', 'left' => 360, 'hanging' => 360, 'tabPos' => 360), - array('format' => 'upperLetter', 'text' => '%2.', 'left' => 720, 'hanging' => 360, 'tabPos' => 720), - ), - ) + [ + 'type' => 'multilevel', + 'levels' => [ + ['format' => 'decimal', 'text' => '%1.', 'left' => 360, 'hanging' => 360, 'tabPos' => 360], + ['format' => 'upperLetter', 'text' => '%2.', 'left' => 720, 'hanging' => 360, 'tabPos' => 720], + ], + ] ); -$predefinedMultilevelStyle = array('listType' => \PhpOffice\PhpWord\Style\ListItem::TYPE_NUMBER_NESTED); +$predefinedMultilevelStyle = ['listType' => \PhpOffice\PhpWord\Style\ListItem::TYPE_NUMBER_NESTED]; // New section $section = $phpWord->addSection(); @@ -63,32 +64,32 @@ $section->addText('List with inline formatting.'); $listItemRun = $section->addListItemRun(); $listItemRun->addText('List item 1'); -$listItemRun->addText(' in bold', array('bold' => true)); +$listItemRun->addText(' in bold', ['bold' => true]); $listItemRun = $section->addListItemRun(1, $predefinedMultilevelStyle, $paragraphStyleName); $listItemRun->addText('List item 2'); -$listItemRun->addText(' in italic', array('italic' => true)); +$listItemRun->addText(' in italic', ['italic' => true]); $footnote = $listItemRun->addFootnote(); $footnote->addText('this is a footnote on a list item'); $listItemRun = $section->addListItemRun(); $listItemRun->addText('List item 3'); -$listItemRun->addText(' underlined', array('underline' => 'dash')); +$listItemRun->addText(' underlined', ['underline' => 'dash']); $section->addTextBreak(2); // Numbered heading $headingNumberingStyleName = 'headingNumbering'; $phpWord->addNumberingStyle( $headingNumberingStyleName, - array('type' => 'multilevel', - 'levels' => array( - array('pStyle' => 'Heading1', 'format' => 'decimal', 'text' => '%1'), - array('pStyle' => 'Heading2', 'format' => 'decimal', 'text' => '%1.%2'), - array('pStyle' => 'Heading3', 'format' => 'decimal', 'text' => '%1.%2.%3'), - ), - ) + ['type' => 'multilevel', + 'levels' => [ + ['pStyle' => 'Heading1', 'format' => 'decimal', 'text' => '%1'], + ['pStyle' => 'Heading2', 'format' => 'decimal', 'text' => '%1.%2'], + ['pStyle' => 'Heading3', 'format' => 'decimal', 'text' => '%1.%2.%3'], + ], + ] ); -$phpWord->addTitleStyle(1, array('size' => 16), array('numStyle' => $headingNumberingStyleName, 'numLevel' => 0)); -$phpWord->addTitleStyle(2, array('size' => 14), array('numStyle' => $headingNumberingStyleName, 'numLevel' => 1)); -$phpWord->addTitleStyle(3, array('size' => 12), array('numStyle' => $headingNumberingStyleName, 'numLevel' => 2)); +$phpWord->addTitleStyle(1, ['size' => 16], ['numStyle' => $headingNumberingStyleName, 'numLevel' => 0]); +$phpWord->addTitleStyle(2, ['size' => 14], ['numStyle' => $headingNumberingStyleName, 'numLevel' => 1]); +$phpWord->addTitleStyle(3, ['size' => 12], ['numStyle' => $headingNumberingStyleName, 'numLevel' => 2]); $section->addTitle('Heading 1', 1); $section->addTitle('Heading 2', 2); diff --git a/samples/Sample_15_Link.php b/samples/Sample_15_Link.php index 86c7973bc1..faef305962 100644 --- a/samples/Sample_15_Link.php +++ b/samples/Sample_15_Link.php @@ -1,4 +1,5 @@ addLinkStyle($linkFontStyleName, array('bold' => true, 'color' => '808000')); +$phpWord->addLinkStyle($linkFontStyleName, ['bold' => true, 'color' => '808000']); // New section $section = $phpWord->addSection(); @@ -16,7 +17,7 @@ $section->addLink( 'https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub', - array('color' => '0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE) + ['color' => '0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE] ); $section->addTextBreak(2); $section->addLink('http://www.bing.com/', null, $linkFontStyleName); diff --git a/samples/Sample_16_Object.php b/samples/Sample_16_Object.php index c4db7f6106..b68fb1675b 100644 --- a/samples/Sample_16_Object.php +++ b/samples/Sample_16_Object.php @@ -1,4 +1,5 @@ addSection(); // Define styles -$fontStyle12 = array('spaceAfter' => 60, 'size' => 12); -$fontStyle10 = array('size' => 10); -$phpWord->addTitleStyle(null, array('size' => 22, 'bold' => true)); -$phpWord->addTitleStyle(1, array('size' => 20, 'color' => '333333', 'bold' => true)); -$phpWord->addTitleStyle(2, array('size' => 16, 'color' => '666666')); -$phpWord->addTitleStyle(3, array('size' => 14, 'italic' => true)); -$phpWord->addTitleStyle(4, array('size' => 12)); +$fontStyle12 = ['spaceAfter' => 60, 'size' => 12]; +$fontStyle10 = ['size' => 10]; +$phpWord->addTitleStyle(null, ['size' => 22, 'bold' => true]); +$phpWord->addTitleStyle(1, ['size' => 20, 'color' => '333333', 'bold' => true]); +$phpWord->addTitleStyle(2, ['size' => 16, 'color' => '666666']); +$phpWord->addTitleStyle(3, ['size' => 14, 'italic' => true]); +$phpWord->addTitleStyle(4, ['size' => 12]); // Add text elements $section->addTitle('Table of contents 1', 0); diff --git a/samples/Sample_18_Watermark.php b/samples/Sample_18_Watermark.php index dbab2b7f26..aebb369023 100644 --- a/samples/Sample_18_Watermark.php +++ b/samples/Sample_18_Watermark.php @@ -1,4 +1,5 @@ addSection(); $header = $section->addHeader(); -$header->addWatermark('resources/_earth.jpg', array('marginTop' => 200, 'marginLeft' => 55)); +$header->addWatermark('resources/_earth.jpg', ['marginTop' => 200, 'marginLeft' => 55]); $section->addText('The header reference to the current section includes a watermark image.'); // Save file diff --git a/samples/Sample_19_TextBreak.php b/samples/Sample_19_TextBreak.php index 17e2b1cbd7..45c79beeb6 100644 --- a/samples/Sample_19_TextBreak.php +++ b/samples/Sample_19_TextBreak.php @@ -1,4 +1,5 @@ 24); +$fontStyle24 = ['size' => 24]; -$paragraphStyle24 = array('spacing' => 240, 'size' => 24); +$paragraphStyle24 = ['spacing' => 240, 'size' => 24]; $fontStyleName = 'fontStyle'; -$phpWord->addFontStyle($fontStyleName, array('size' => 9)); +$phpWord->addFontStyle($fontStyleName, ['size' => 9]); $paragraphStyleName = 'paragraphStyle'; -$phpWord->addParagraphStyle($paragraphStyleName, array('spacing' => 480)); +$phpWord->addParagraphStyle($paragraphStyleName, ['spacing' => 480]); // New section $section = $phpWord->addSection(); diff --git a/samples/Sample_20_BGColor.php b/samples/Sample_20_BGColor.php index 628ae8902e..915a824171 100644 --- a/samples/Sample_20_BGColor.php +++ b/samples/Sample_20_BGColor.php @@ -1,4 +1,5 @@ addText( 'This is some text highlighted using fgColor (limited to 15 colors)', - array('fgColor' => \PhpOffice\PhpWord\Style\Font::FGCOLOR_YELLOW) + ['fgColor' => \PhpOffice\PhpWord\Style\Font::FGCOLOR_YELLOW] ); -$section->addText('This one uses bgColor and is using hex value (0xfbbb10)', array('bgColor' => 'fbbb10')); -$section->addText('Compatible with font colors', array('color' => '0000ff', 'bgColor' => 'fbbb10')); +$section->addText('This one uses bgColor and is using hex value (0xfbbb10)', ['bgColor' => 'fbbb10']); +$section->addText('Compatible with font colors', ['color' => '0000ff', 'bgColor' => 'fbbb10']); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_21_TableRowRules.php b/samples/Sample_21_TableRowRules.php index ca33de3bcd..42fc2d92a5 100644 --- a/samples/Sample_21_TableRowRules.php +++ b/samples/Sample_21_TableRowRules.php @@ -1,4 +1,5 @@ addTable(array('cellMargin' => 0, 'cellMarginRight' => 0, 'cellMarginBottom' => 0, 'cellMarginLeft' => 0)); +$table1 = $section->addTable(['cellMargin' => 0, 'cellMarginRight' => 0, 'cellMarginBottom' => 0, 'cellMarginLeft' => 0]); $table1->addRow(3750); -$cell1 = $table1->addCell(null, array('valign' => 'top', 'borderSize' => 30, 'borderColor' => 'ff0000')); -$cell1->addImage('./resources/_earth.jpg', array('width' => 250, 'height' => 250, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER)); +$cell1 = $table1->addCell(null, ['valign' => 'top', 'borderSize' => 30, 'borderColor' => 'ff0000']); +$cell1->addImage('./resources/_earth.jpg', ['width' => 250, 'height' => 250, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $section->addTextBreak(); $section->addText("But if we set the rowStyle 'exactHeight' to true, the real row height is used, removing the textbreak:"); $table2 = $section->addTable( - array( - 'cellMargin' => 0, - 'cellMarginRight' => 0, + [ + 'cellMargin' => 0, + 'cellMarginRight' => 0, 'cellMarginBottom' => 0, - 'cellMarginLeft' => 0, - ) + 'cellMarginLeft' => 0, + ] ); -$table2->addRow(3750, array('exactHeight' => true)); -$cell2 = $table2->addCell(null, array('valign' => 'top', 'borderSize' => 30, 'borderColor' => '00ff00')); -$cell2->addImage('./resources/_earth.jpg', array('width' => 250, 'height' => 250, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER)); +$table2->addRow(3750, ['exactHeight' => true]); +$cell2 = $table2->addCell(null, ['valign' => 'top', 'borderSize' => 30, 'borderColor' => '00ff00']); +$cell2->addImage('./resources/_earth.jpg', ['width' => 250, 'height' => 250, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $section->addTextBreak(); $section->addText('In this example, image is 250px height. Rows are calculated in twips, and 1px = 15twips.'); diff --git a/samples/Sample_22_CheckBox.php b/samples/Sample_22_CheckBox.php index 5a2ac3e2cc..33d4e39c66 100644 --- a/samples/Sample_22_CheckBox.php +++ b/samples/Sample_22_CheckBox.php @@ -1,4 +1,5 @@ saveAs('results/Sample_23_TemplateBlock.docx'); -echo getEndingNotes(array('Word2007' => 'docx'), 'Sample_23_TemplateBlock'); +echo getEndingNotes(['Word2007' => 'docx'], 'Sample_23_TemplateBlock'); if (!CLI) { include_once 'Sample_Footer.php'; } diff --git a/samples/Sample_24_ReadODText.php b/samples/Sample_24_ReadODText.php index 42df23ae2b..73c110203e 100644 --- a/samples/Sample_24_ReadODText.php +++ b/samples/Sample_24_ReadODText.php @@ -1,4 +1,5 @@ addTextBox( - array( - 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER, - 'width' => 400, - 'height' => 150, - 'borderSize' => 1, + [ + 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER, + 'width' => 400, + 'height' => 150, + 'borderSize' => 1, 'borderColor' => '#FF0000', - ) + ] ); $textbox->addText('Text box content in section.'); $textbox->addText('Another line.'); @@ -26,19 +27,19 @@ // Inside table $section->addTextBreak(2); $cell = $section->addTable()->addRow()->addCell(300); -$textbox = $cell->addTextBox(array('borderSize' => 1, 'borderColor' => '#0000FF', 'innerMargin' => 100)); +$textbox = $cell->addTextBox(['borderSize' => 1, 'borderColor' => '#0000FF', 'innerMargin' => 100]); $textbox->addText('Textbox inside table'); // Inside header with textrun $header = $section->addHeader(); -$textbox = $header->addTextBox(array('width' => 600, 'borderSize' => 1, 'borderColor' => '#00FF00')); +$textbox = $header->addTextBox(['width' => 600, 'borderSize' => 1, 'borderColor' => '#00FF00']); $textrun = $textbox->addTextRun(); $textrun->addText('TextBox in header. TextBox can contain a TextRun '); -$textrun->addText('with bold text', array('bold' => true)); +$textrun->addText('with bold text', ['bold' => true]); $textrun->addText(', '); $textrun->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub'); $textrun->addText(', and image '); -$textrun->addImage('resources/_earth.jpg', array('width' => 18, 'height' => 18)); +$textrun->addImage('resources/_earth.jpg', ['width' => 18, 'height' => 18]); $textrun->addText('.'); // Save file diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index 6bd926fe5b..84468faaa5 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -1,10 +1,11 @@ addParagraphStyle('Heading2', array('alignment' => 'center')); +$phpWord->addParagraphStyle('Heading2', ['alignment' => 'center']); $section = $phpWord->addSection(); $html = '

Adding element via HTML

'; diff --git a/samples/Sample_27_Field.php b/samples/Sample_27_Field.php index 4e7a5b2264..d250946169 100644 --- a/samples/Sample_27_Field.php +++ b/samples/Sample_27_Field.php @@ -1,4 +1,5 @@ 14)); +PhpOffice\PhpWord\Style::addTitleStyle(1, ['size' => 14]); // New section $section = $phpWord->addSection(); @@ -15,53 +16,53 @@ // Add Field elements // See Element/Field.php for all options $section->addText('Date field:'); -$section->addField('DATE', array('dateformat' => 'dddd d MMMM yyyy H:mm:ss'), array('PreserveFormat')); +$section->addField('DATE', ['dateformat' => 'dddd d MMMM yyyy H:mm:ss'], ['PreserveFormat']); $section->addText('Style Ref field:'); -$section->addField('STYLEREF', array('StyleIdentifier' => 'Heading 1')); +$section->addField('STYLEREF', ['StyleIdentifier' => 'Heading 1']); $section->addText('Page field:'); -$section->addField('PAGE', array('format' => 'Arabic')); +$section->addField('PAGE', ['format' => 'Arabic']); $section->addText('Number of pages field:'); -$section->addField('NUMPAGES', array('numformat' => '0,00', 'format' => 'Arabic'), array('PreserveFormat')); +$section->addField('NUMPAGES', ['numformat' => '0,00', 'format' => 'Arabic'], ['PreserveFormat']); $section->addTextBreak(); $textrun = $section->addTextRun(); $textrun->addText('An index field is '); -$textrun->addField('XE', array(), array('Italic'), 'My first index'); +$textrun->addField('XE', [], ['Italic'], 'My first index'); $textrun->addText('here:'); $indexEntryText = new TextRun(); $indexEntryText->addText('My '); -$indexEntryText->addText('bold index', array('bold' => true)); +$indexEntryText->addText('bold index', ['bold' => true]); $indexEntryText->addText(' entry'); $textrun = $section->addTextRun(); $textrun->addText('A complex index field is '); -$textrun->addField('XE', array(), array('Bold'), $indexEntryText); +$textrun->addField('XE', [], ['Bold'], $indexEntryText); $textrun->addText('here:'); $section->addText('The actual index:'); -$section->addField('INDEX', array(), array('\\e " "'), 'right click to update the index'); +$section->addField('INDEX', [], ['\\e " "'], 'right click to update the index'); -$textrun = $section->addTextRun(array('alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER)); +$textrun = $section->addTextRun(['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $textrun->addText('This is the date of lunar calendar '); -$textrun->addField('DATE', array('dateformat' => 'd-M-yyyy H:mm:ss'), array('PreserveFormat', 'LunarCalendar')); +$textrun->addField('DATE', ['dateformat' => 'd-M-yyyy H:mm:ss'], ['PreserveFormat', 'LunarCalendar']); $textrun->addText(' written in a textrun.'); $section->addTextBreak(); $macroText = new TextRun(); -$macroText->addText('Double click', array('bold' => true)); +$macroText->addText('Double click', ['bold' => true]); $macroText->addText(' to '); -$macroText->addText('zoom to 100%', array('italic' => true)); +$macroText->addText('zoom to 100%', ['italic' => true]); $section->addText('A macro button with styled text:'); -$section->addField('MACROBUTTON', array('macroname' => 'Zoom100'), array(), $macroText); +$section->addField('MACROBUTTON', ['macroname' => 'Zoom100'], [], $macroText); $section->addTextBreak(); $section->addText('A macro button with simple text:'); -$section->addField('MACROBUTTON', array('macroname' => 'Zoom100'), array(), 'double click to zoom'); +$section->addField('MACROBUTTON', ['macroname' => 'Zoom100'], [], 'double click to zoom'); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_28_ReadRTF.php b/samples/Sample_28_ReadRTF.php index 76ac3d48bb..43b859ac28 100644 --- a/samples/Sample_28_ReadRTF.php +++ b/samples/Sample_28_ReadRTF.php @@ -1,4 +1,5 @@ addText('Horizontal Line (Inline style):'); $section->addLine( - array( - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(4), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), + [ + 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(4), + 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), 'positioning' => 'absolute', - ) + ] ); $section->addText('Vertical Line (Inline style):'); $section->addLine( - array( - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(1), + [ + 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), + 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(1), 'positioning' => 'absolute', - ) + ] ); // Two text break $section->addTextBreak(1); $section->addText('Positioned Line (red):'); $section->addLine( - array( - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(4), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(1), - 'positioning' => 'absolute', + [ + 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(4), + 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(1), + 'positioning' => 'absolute', 'posHorizontalRel' => 'page', - 'posVerticalRel' => 'page', - 'marginLeft' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(10), - 'marginTop' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(8), - 'wrappingStyle' => \PhpOffice\PhpWord\Style\Image::WRAPPING_STYLE_SQUARE, - 'color' => 'red', - ) + 'posVerticalRel' => 'page', + 'marginLeft' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(10), + 'marginTop' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(8), + 'wrappingStyle' => \PhpOffice\PhpWord\Style\Image::WRAPPING_STYLE_SQUARE, + 'color' => 'red', + ] ); $section->addText('Horizontal Formatted Line'); $section->addLine( - array( - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(15), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), + [ + 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(15), + 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), 'positioning' => 'absolute', - 'beginArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_BLOCK, - 'endArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_OVAL, - 'dash' => \PhpOffice\PhpWord\Style\Line::DASH_STYLE_LONG_DASH_DOT_DOT, - 'weight' => 10, - ) + 'beginArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_BLOCK, + 'endArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_OVAL, + 'dash' => \PhpOffice\PhpWord\Style\Line::DASH_STYLE_LONG_DASH_DOT_DOT, + 'weight' => 10, + ] ); // Save file diff --git a/samples/Sample_30_ReadHTML.php b/samples/Sample_30_ReadHTML.php index 029f8c8cfd..8698fe639a 100644 --- a/samples/Sample_30_ReadHTML.php +++ b/samples/Sample_30_ReadHTML.php @@ -1,4 +1,5 @@ addSection(); // Define styles -$phpWord->addTitleStyle(1, array('size' => 14, 'bold' => true)); +$phpWord->addTitleStyle(1, ['size' => 14, 'bold' => true]); // Arc $section->addTitle('Arc', 1); $section->addShape( 'arc', - array( - 'points' => '-90 20', - 'frame' => array('width' => 120, 'height' => 120), - 'outline' => array('color' => '#333333', 'weight' => 2, 'startArrow' => 'oval', 'endArrow' => 'open'), - ) + [ + 'points' => '-90 20', + 'frame' => ['width' => 120, 'height' => 120], + 'outline' => ['color' => '#333333', 'weight' => 2, 'startArrow' => 'oval', 'endArrow' => 'open'], + ] ); // Curve $section->addTitle('Curve', 1); $section->addShape( 'curve', - array( - 'points' => '1,100 200,1 1,50 200,50', + [ + 'points' => '1,100 200,1 1,50 200,50', 'connector' => 'elbow', - 'outline' => array( - 'color' => '#66cc00', - 'weight' => 2, - 'dash' => 'dash', + 'outline' => [ + 'color' => '#66cc00', + 'weight' => 2, + 'dash' => 'dash', 'startArrow' => 'diamond', - 'endArrow' => 'block', - ), - ) + 'endArrow' => 'block', + ], + ] ); // Line $section->addTitle('Line', 1); $section->addShape( 'line', - array( - 'points' => '1,1 150,30', - 'outline' => array( - 'color' => '#cc00ff', - 'line' => 'thickThin', - 'weight' => 3, + [ + 'points' => '1,1 150,30', + 'outline' => [ + 'color' => '#cc00ff', + 'line' => 'thickThin', + 'weight' => 3, 'startArrow' => 'oval', - 'endArrow' => 'classic', - ), - ) + 'endArrow' => 'classic', + ], + ] ); // Polyline $section->addTitle('Polyline', 1); $section->addShape( 'polyline', - array( - 'points' => '1,30 20,10 55,20 75,10 100,40 115,50, 120,15 200,50', - 'outline' => array('color' => '#cc6666', 'weight' => 2, 'startArrow' => 'none', 'endArrow' => 'classic'), - ) + [ + 'points' => '1,30 20,10 55,20 75,10 100,40 115,50, 120,15 200,50', + 'outline' => ['color' => '#cc6666', 'weight' => 2, 'startArrow' => 'none', 'endArrow' => 'classic'], + ] ); // Rectangle $section->addTitle('Rectangle', 1); $section->addShape( 'rect', - array( + [ 'roundness' => 0.2, - 'frame' => array('width' => 100, 'height' => 100, 'left' => 1, 'top' => 1), - 'fill' => array('color' => '#FFCC33'), - 'outline' => array('color' => '#990000', 'weight' => 1), - 'shadow' => array(), - ) + 'frame' => ['width' => 100, 'height' => 100, 'left' => 1, 'top' => 1], + 'fill' => ['color' => '#FFCC33'], + 'outline' => ['color' => '#990000', 'weight' => 1], + 'shadow' => [], + ] ); // Oval $section->addTitle('Oval', 1); $section->addShape( 'oval', - array( - 'frame' => array('width' => 100, 'height' => 70, 'left' => 1, 'top' => 1), - 'fill' => array('color' => '#33CC99'), - 'outline' => array('color' => '#333333', 'weight' => 2), - 'extrusion' => array(), - ) + [ + 'frame' => ['width' => 100, 'height' => 70, 'left' => 1, 'top' => 1], + 'fill' => ['color' => '#33CC99'], + 'outline' => ['color' => '#333333', 'weight' => 2], + 'extrusion' => [], + ] ); // Save file diff --git a/samples/Sample_32_Chart.php b/samples/Sample_32_Chart.php index bfb9ffe86b..7e99984e41 100644 --- a/samples/Sample_32_Chart.php +++ b/samples/Sample_32_Chart.php @@ -1,4 +1,5 @@ addTitleStyle(1, array('size' => 14, 'bold' => true), array('keepNext' => true, 'spaceBefore' => 240)); -$phpWord->addTitleStyle(2, array('size' => 14, 'bold' => true), array('keepNext' => true, 'spaceBefore' => 240)); +$phpWord->addTitleStyle(1, ['size' => 14, 'bold' => true], ['keepNext' => true, 'spaceBefore' => 240]); +$phpWord->addTitleStyle(2, ['size' => 14, 'bold' => true], ['keepNext' => true, 'spaceBefore' => 240]); // 2D charts $section = $phpWord->addSection(); $section->addTitle('2D charts', 1); -$section = $phpWord->addSection(array('colsNum' => 2, 'breakType' => 'continuous')); +$section = $phpWord->addSection(['colsNum' => 2, 'breakType' => 'continuous']); -$chartTypes = array('pie', 'doughnut', 'bar', 'column', 'line', 'area', 'scatter', 'radar', 'stacked_bar', 'percent_stacked_bar', 'stacked_column', 'percent_stacked_column'); -$twoSeries = array('bar', 'column', 'line', 'area', 'scatter', 'radar', 'stacked_bar', 'percent_stacked_bar', 'stacked_column', 'percent_stacked_column'); -$threeSeries = array('bar', 'line'); -$categories = array('A', 'B', 'C', 'D', 'E'); -$series1 = array(1, 3, 2, 5, 4); -$series2 = array(3, 1, 7, 2, 6); -$series3 = array(8, 3, 2, 5, 4); +$chartTypes = ['pie', 'doughnut', 'bar', 'column', 'line', 'area', 'scatter', 'radar', 'stacked_bar', 'percent_stacked_bar', 'stacked_column', 'percent_stacked_column']; +$twoSeries = ['bar', 'column', 'line', 'area', 'scatter', 'radar', 'stacked_bar', 'percent_stacked_bar', 'stacked_column', 'percent_stacked_column']; +$threeSeries = ['bar', 'line']; +$categories = ['A', 'B', 'C', 'D', 'E']; +$series1 = [1, 3, 2, 5, 4]; +$series2 = [3, 1, 7, 2, 6]; +$series3 = [8, 3, 2, 5, 4]; $showGridLines = false; $showAxisLabels = false; $showLegend = true; @@ -48,20 +49,20 @@ } // 3D charts -$section = $phpWord->addSection(array('breakType' => 'continuous')); +$section = $phpWord->addSection(['breakType' => 'continuous']); $section->addTitle('3D charts', 1); -$section = $phpWord->addSection(array('colsNum' => 2, 'breakType' => 'continuous')); +$section = $phpWord->addSection(['colsNum' => 2, 'breakType' => 'continuous']); -$chartTypes = array('pie', 'bar', 'column', 'line', 'area'); -$multiSeries = array('bar', 'column', 'line', 'area'); -$style = array( - 'width' => Converter::cmToEmu(5), - 'height' => Converter::cmToEmu(4), - '3d' => true, +$chartTypes = ['pie', 'bar', 'column', 'line', 'area']; +$multiSeries = ['bar', 'column', 'line', 'area']; +$style = [ + 'width' => Converter::cmToEmu(5), + 'height' => Converter::cmToEmu(4), + '3d' => true, 'showAxisLabels' => $showAxisLabels, - 'showGridX' => $showGridLines, - 'showGridY' => $showGridLines, -); + 'showGridX' => $showGridLines, + 'showGridY' => $showGridLines, +]; foreach ($chartTypes as $chartType) { $section->addTitle(ucfirst($chartType), 2); $chart = $section->addChart($chartType, $categories, $series1, $style); diff --git a/samples/Sample_33_FormField.php b/samples/Sample_33_FormField.php index a855d42a02..61abc415cc 100644 --- a/samples/Sample_33_FormField.php +++ b/samples/Sample_33_FormField.php @@ -1,4 +1,5 @@ addText(', checkbox '); $textrun->addFormField('checkbox')->setDefault(true); $textrun->addText(', or dropdown '); -$textrun->addFormField('dropdown')->setEntries(array('Choice 1', 'Choice 2', 'Choice 3')); +$textrun->addFormField('dropdown')->setEntries(['Choice 1', 'Choice 2', 'Choice 3']); $textrun->addText('. You have to set document protection to "forms" to enable dropdown.'); $section->addText('They can also be added as a stand alone paragraph.'); diff --git a/samples/Sample_34_SDT.php b/samples/Sample_34_SDT.php index f9077a1a44..c1722b5b5c 100644 --- a/samples/Sample_34_SDT.php +++ b/samples/Sample_34_SDT.php @@ -1,4 +1,5 @@ addTextRun(); $textrun->addText('Combobox: '); -$textrun->addSDT('comboBox')->setListItems(array('1' => 'Choice 1', '2' => 'Choice 2')); +$textrun->addSDT('comboBox')->setListItems(['1' => 'Choice 1', '2' => 'Choice 2']); $textrun = $section->addTextRun(); $textrun->addText('Date: '); @@ -24,7 +25,7 @@ $textrun = $section->addTextRun(); $textrun->addText('Drop down list: '); -$textrun->addSDT('dropDownList')->setListItems(array('1' => 'Choice 1', '2' => 'Choice 2'))->setValue('Choice 1'); +$textrun->addSDT('dropDownList')->setListItems(['1' => 'Choice 1', '2' => 'Choice 2'])->setValue('Choice 1'); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_35_InternalLink.php b/samples/Sample_35_InternalLink.php index 5ab7d9b4d9..e59c353001 100644 --- a/samples/Sample_35_InternalLink.php +++ b/samples/Sample_35_InternalLink.php @@ -1,4 +1,5 @@ addTextRun(); $textrun->addText('This is a Left to Right paragraph.'); -$textrun = $section->addTextRun(array('alignment' => \PhpOffice\PhpWord\SimpleType\Jc::END)); -$textrun->addText('سلام این یک پاراگراف راست به چپ است', array('rtl' => true)); +$textrun = $section->addTextRun(['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::END]); +$textrun->addText('سلام این یک پاراگراف راست به چپ است', ['rtl' => true]); $section->addText('Table visually presented as RTL'); -$style = array('rtl' => true, 'size' => 12); -$tableStyle = array('borderSize' => 6, 'borderColor' => '000000', 'width' => 5000, 'unit' => \PhpOffice\PhpWord\SimpleType\TblWidth::PERCENT, 'bidiVisual' => true); +$style = ['rtl' => true, 'size' => 12]; +$tableStyle = ['borderSize' => 6, 'borderColor' => '000000', 'width' => 5000, 'unit' => \PhpOffice\PhpWord\SimpleType\TblWidth::PERCENT, 'bidiVisual' => true]; $table = $section->addTable($tableStyle); -$cellHCentered = array('alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER); -$cellHEnd = array('alignment' => \PhpOffice\PhpWord\SimpleType\Jc::END); -$cellVCentered = array('valign' => \PhpOffice\PhpWord\Style\Cell::VALIGN_CENTER); +$cellHCentered = ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]; +$cellHEnd = ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::END]; +$cellVCentered = ['valign' => \PhpOffice\PhpWord\Style\Cell::VALIGN_CENTER]; //Vidually bidirectinal table $table->addRow(); diff --git a/samples/Sample_37_Comments.php b/samples/Sample_37_Comments.php index 268739bc67..79647478e8 100644 --- a/samples/Sample_37_Comments.php +++ b/samples/Sample_37_Comments.php @@ -1,4 +1,5 @@ addText('Test', array('bold' => true)); +$comment->addText('Test', ['bold' => true]); $phpWord->addComment($comment); $section = $phpWord->addSection(); @@ -27,9 +28,9 @@ $textrunWithEnd = $section->addTextRun(); $textrunWithEnd->addText('This '); -$textToStartOn = $textrunWithEnd->addText('is', array('bold' => true)); +$textToStartOn = $textrunWithEnd->addText('is', ['bold' => true]); $textToStartOn->setCommentRangeStart($commentWithStartAndEnd); -$textrunWithEnd->addText(' another', array('italic' => true)); +$textrunWithEnd->addText(' another', ['italic' => true]); $textToEndOn = $textrunWithEnd->addText(' test'); $textToEndOn->setCommentRangeEnd($commentWithStartAndEnd); @@ -39,7 +40,7 @@ $commentOnImage = new \PhpOffice\PhpWord\Element\Comment('Mr Smart', new \DateTime()); $imageComment = $commentOnImage->addTextRun(); $imageComment->addText('Hey, Mars does look '); -$imageComment->addText('red', array('color' => 'FF0000')); +$imageComment->addText('red', ['color' => 'FF0000']); $phpWord->addComment($commentOnImage); $image = $section->addImage('resources/_mars.jpg'); $image->setCommentRangeStart($commentOnImage); @@ -50,7 +51,7 @@ $anotherText = $section->addText('another text'); $comment1 = new \PhpOffice\PhpWord\Element\Comment('Authors name', new \DateTime(), 'my_initials'); -$comment1->addText('Test', array('bold' => true)); +$comment1->addText('Test', ['bold' => true]); $comment1->setStartElement($anotherText); $comment1->setEndElement($anotherText); $phpWord->addComment($comment1); diff --git a/samples/Sample_38_Protection.php b/samples/Sample_38_Protection.php index ee2b460b2f..9f61538096 100644 --- a/samples/Sample_38_Protection.php +++ b/samples/Sample_38_Protection.php @@ -1,4 +1,5 @@ addText('Hello World! Time to '); -$text = $textRun->addText('wake ', array('bold' => true)); +$text = $textRun->addText('wake ', ['bold' => true]); $text->setChangeInfo(TrackChange::INSERTED, 'Fred', time() - 1800); $text = $textRun->addText('up'); diff --git a/samples/Sample_40_TemplateSetComplexValue.php b/samples/Sample_40_TemplateSetComplexValue.php index 094823f784..38ecb3f7ae 100644 --- a/samples/Sample_40_TemplateSetComplexValue.php +++ b/samples/Sample_40_TemplateSetComplexValue.php @@ -1,4 +1,5 @@ addText('This title has been set ', array('bold' => true, 'italic' => true, 'color' => 'blue')); -$title->addText('dynamically', array('bold' => true, 'italic' => true, 'color' => 'red', 'underline' => 'single')); +$title->addText('This title has been set ', ['bold' => true, 'italic' => true, 'color' => 'blue']); +$title->addText('dynamically', ['bold' => true, 'italic' => true, 'color' => 'red', 'underline' => 'single']); $templateProcessor->setComplexBlock('title', $title); $inline = new TextRun(); -$inline->addText('by a red italic text', array('italic' => true, 'color' => 'red')); +$inline->addText('by a red italic text', ['italic' => true, 'color' => 'red']); $templateProcessor->setComplexValue('inline', $inline); -$table = new Table(array('borderSize' => 12, 'borderColor' => 'green', 'width' => 6000, 'unit' => TblWidth::TWIP)); +$table = new Table(['borderSize' => 12, 'borderColor' => 'green', 'width' => 6000, 'unit' => TblWidth::TWIP]); $table->addRow(); $table->addCell(150)->addText('Cell A1'); $table->addCell(150)->addText('Cell A2'); @@ -30,7 +31,7 @@ $table->addCell(150)->addText('Cell B3'); $templateProcessor->setComplexBlock('table', $table); -$field = new Field('DATE', array('dateformat' => 'dddd d MMMM yyyy H:mm:ss'), array('PreserveFormat')); +$field = new Field('DATE', ['dateformat' => 'dddd d MMMM yyyy H:mm:ss'], ['PreserveFormat']); $templateProcessor->setComplexValue('field', $field); // $link = new Link('https://github.com/PHPOffice/PHPWord'); @@ -39,7 +40,7 @@ echo date('H:i:s'), ' Saving the result document...', EOL; $templateProcessor->saveAs('results/Sample_40_TemplateSetComplexValue.docx'); -echo getEndingNotes(array('Word2007' => 'docx'), 'results/Sample_40_TemplateSetComplexValue.docx'); +echo getEndingNotes(['Word2007' => 'docx'], 'results/Sample_40_TemplateSetComplexValue.docx'); if (!CLI) { include_once 'Sample_Footer.php'; } diff --git a/samples/Sample_41_TemplateSetChart.php b/samples/Sample_41_TemplateSetChart.php index 2b017d7f7c..88eb2ccbd9 100644 --- a/samples/Sample_41_TemplateSetChart.php +++ b/samples/Sample_41_TemplateSetChart.php @@ -1,4 +1,5 @@ setHeight(Converter::inchToEmu(3)); $templateProcessor->setChart("chart{$i}", $chart); - $i++; + ++$i; } echo date('H:i:s'), ' Saving the result document...', EOL; $templateProcessor->saveAs('results/Sample_41_TemplateSetChart.docx'); -echo getEndingNotes(array('Word2007' => 'docx'), 'results/Sample_41_TemplateSetChart.docx'); +echo getEndingNotes(['Word2007' => 'docx'], 'results/Sample_41_TemplateSetChart.docx'); if (!CLI) { include_once 'Sample_Footer.php'; } diff --git a/samples/Sample_Header.php b/samples/Sample_Header.php index f0fc626627..53674b7914 100644 --- a/samples/Sample_Header.php +++ b/samples/Sample_Header.php @@ -19,7 +19,7 @@ } // Set writers -$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf', 'HTML' => 'html', 'PDF' => 'pdf'); +$writers = ['Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf', 'HTML' => 'html', 'PDF' => 'pdf']; // Set PDF renderer if (null === Settings::getPdfRendererPath()) { @@ -43,7 +43,7 @@ // Populate samples $files = ''; if ($handle = opendir('.')) { - $sampleFiles = array(); + $sampleFiles = []; while (false !== ($sampleFile = readdir($handle))) { $sampleFiles[] = $sampleFile; } @@ -59,7 +59,7 @@ } /** - * Write documents + * Write documents. * * @param \PhpOffice\PhpWord\PhpWord $phpWord * @param string $filename @@ -89,10 +89,11 @@ function write($phpWord, $filename, $writers) } /** - * Get ending notes + * Get ending notes. * * @param array $writers * @param mixed $filename + * * @return string */ function getEndingNotes($writers, $filename) @@ -114,7 +115,7 @@ function getEndingNotes($writers, $filename) $result .= '

 

'; $result .= '

Results: '; foreach ($types as $type) { - if (!is_null($type)) { + if (null !== $type) { $resultFile = 'results/' . SCRIPT_FILENAME . '.' . $type; if (file_exists($resultFile)) { $result .= "{$type} "; diff --git a/samples/index.php b/samples/index.php index d539cd620d..c47deebe46 100644 --- a/samples/index.php +++ b/samples/index.php @@ -3,15 +3,15 @@ use PhpOffice\PhpWord\Settings; -$requirements = array( - 'php' => array('PHP 7.4', version_compare(PHP_VERSION, '7.4', '>=')), - 'xml' => array('PHP extension XML', extension_loaded('xml')), - 'temp' => array('Temp folder "' . Settings::getTempDir() . '" is writable', is_writable(Settings::getTempDir())), - 'zip' => array('PHP extension ZipArchive (optional)', extension_loaded('zip')), - 'gd' => array('PHP extension GD (optional)', extension_loaded('gd')), - 'xmlw' => array('PHP extension XMLWriter (optional)', extension_loaded('xmlwriter')), - 'xsl' => array('PHP extension XSL (optional)', extension_loaded('xsl')), -); +$requirements = [ + 'php' => ['PHP 7.4', version_compare(PHP_VERSION, '7.4', '>=')], + 'xml' => ['PHP extension XML', extension_loaded('xml')], + 'temp' => ['Temp folder "' . Settings::getTempDir() . '" is writable', is_writable(Settings::getTempDir())], + 'zip' => ['PHP extension ZipArchive (optional)', extension_loaded('zip')], + 'gd' => ['PHP extension GD (optional)', extension_loaded('gd')], + 'xmlw' => ['PHP extension XMLWriter (optional)', extension_loaded('xmlwriter')], + 'xsl' => ['PHP extension XSL (optional)', extension_loaded('xsl')], +]; if (!CLI) { ?>

@@ -28,7 +28,7 @@ echo '

Requirement check:

'; echo '
    '; foreach ($requirements as $key => $value) { - list($label, $result) = $value; + [$label, $result] = $value; $status = $result ? 'passed' : 'failed'; echo "
  • {$label} ... {$status}
  • "; } @@ -37,7 +37,7 @@ } else { echo 'Requirement check:' . PHP_EOL; foreach ($requirements as $key => $value) { - list($label, $result) = $value; + [$label, $result] = $value; $label = strip_tags($label); $status = $result ? '32m passed' : '31m failed'; echo "{$label} ... \033[{$status}\033[0m" . PHP_EOL; diff --git a/src/PhpWord/Collection/AbstractCollection.php b/src/PhpWord/Collection/AbstractCollection.php index 899ec28756..225b361566 100644 --- a/src/PhpWord/Collection/AbstractCollection.php +++ b/src/PhpWord/Collection/AbstractCollection.php @@ -11,28 +11,28 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Collection; /** - * Collection abstract class + * Collection abstract class. * * @since 0.10.0 */ abstract class AbstractCollection { /** - * Items + * Items. * * @var \PhpOffice\PhpWord\Element\AbstractContainer[] */ - private $items = array(); + private $items = []; /** - * Get items + * Get items. * * @return \PhpOffice\PhpWord\Element\AbstractContainer[] */ @@ -42,9 +42,10 @@ public function getItems() } /** - * Get item by index + * Get item by index. * * @param int $index + * * @return \PhpOffice\PhpWord\Element\AbstractContainer */ public function getItem($index) @@ -62,7 +63,7 @@ public function getItem($index) * @param int $index * @param \PhpOffice\PhpWord\Element\AbstractContainer $item */ - public function setItem($index, $item) + public function setItem($index, $item): void { if (array_key_exists($index, $this->items)) { $this->items[$index] = $item; @@ -70,9 +71,10 @@ public function setItem($index, $item) } /** - * Add new item + * Add new item. * * @param \PhpOffice\PhpWord\Element\AbstractContainer $item + * * @return int */ public function addItem($item) @@ -84,7 +86,7 @@ public function addItem($item) } /** - * Get item count + * Get item count. * * @return int */ diff --git a/src/PhpWord/Collection/Bookmarks.php b/src/PhpWord/Collection/Bookmarks.php index b5ffd5f40a..e7d9b4a384 100644 --- a/src/PhpWord/Collection/Bookmarks.php +++ b/src/PhpWord/Collection/Bookmarks.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Collection; /** - * Bookmarks collection + * Bookmarks collection. * * @since 0.12.0 */ diff --git a/src/PhpWord/Collection/Charts.php b/src/PhpWord/Collection/Charts.php index aa807d1e58..bb63a13962 100644 --- a/src/PhpWord/Collection/Charts.php +++ b/src/PhpWord/Collection/Charts.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Collection; /** - * Charts collection + * Charts collection. * * @since 0.12.0 */ diff --git a/src/PhpWord/Collection/Comments.php b/src/PhpWord/Collection/Comments.php index b6c02d392f..8c6b577d7e 100644 --- a/src/PhpWord/Collection/Comments.php +++ b/src/PhpWord/Collection/Comments.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Collection; /** - * Comments collection + * Comments collection. * * @since 0.12.0 */ diff --git a/src/PhpWord/Collection/Endnotes.php b/src/PhpWord/Collection/Endnotes.php index db01b408db..362b25881d 100644 --- a/src/PhpWord/Collection/Endnotes.php +++ b/src/PhpWord/Collection/Endnotes.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Collection; /** - * Endnotes collection + * Endnotes collection. * * @since 0.10.0 */ diff --git a/src/PhpWord/Collection/Footnotes.php b/src/PhpWord/Collection/Footnotes.php index a0a31ca494..76eae3eab3 100644 --- a/src/PhpWord/Collection/Footnotes.php +++ b/src/PhpWord/Collection/Footnotes.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Collection; /** - * Footnotes collection + * Footnotes collection. * * @since 0.10.0 */ diff --git a/src/PhpWord/Collection/Titles.php b/src/PhpWord/Collection/Titles.php index 1ea58ec0d6..7b795771e8 100644 --- a/src/PhpWord/Collection/Titles.php +++ b/src/PhpWord/Collection/Titles.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Collection; /** - * Titles collection + * Titles collection. * * @since 0.10.0 */ diff --git a/src/PhpWord/ComplexType/FootnoteProperties.php b/src/PhpWord/ComplexType/FootnoteProperties.php index e42c9f9d40..2e7743ca08 100644 --- a/src/PhpWord/ComplexType/FootnoteProperties.php +++ b/src/PhpWord/ComplexType/FootnoteProperties.php @@ -11,16 +11,17 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\ComplexType; +use InvalidArgumentException; use PhpOffice\PhpWord\SimpleType\NumberFormat; /** - * Footnote properties + * Footnote properties. * * @see http://www.datypic.com/sc/ooxml/e-w_footnotePr-1.html */ @@ -36,35 +37,35 @@ final class FootnoteProperties const POSITION_DOC_END = 'docEnd'; /** - * Footnote Positioning Location + * Footnote Positioning Location. * * @var string */ private $pos; /** - * Footnote Numbering Format w:numFmt, one of PhpOffice\PhpWord\SimpleType\NumberFormat + * Footnote Numbering Format w:numFmt, one of PhpOffice\PhpWord\SimpleType\NumberFormat. * * @var string */ private $numFmt; /** - * Footnote and Endnote Numbering Starting Value + * Footnote and Endnote Numbering Starting Value. * * @var float */ private $numStart; /** - * Footnote and Endnote Numbering Restart Location + * Footnote and Endnote Numbering Restart Location. * * @var string */ private $numRestart; /** - * Get the Footnote Positioning Location + * Get the Footnote Positioning Location. * * @return string */ @@ -74,32 +75,32 @@ public function getPos() } /** - * Set the Footnote Positioning Location (pageBottom, beneathText, sectEnd, docEnd) + * Set the Footnote Positioning Location (pageBottom, beneathText, sectEnd, docEnd). * * @param string $pos - * @throws \InvalidArgumentException + * * @return self */ public function setPos($pos) { - $position = array( + $position = [ self::POSITION_PAGE_BOTTOM, self::POSITION_BENEATH_TEXT, self::POSITION_SECTION_END, self::POSITION_DOC_END, - ); + ]; if (in_array($pos, $position)) { $this->pos = $pos; } else { - throw new \InvalidArgumentException('Invalid value, on of ' . implode(', ', $position) . ' possible'); + throw new InvalidArgumentException('Invalid value, on of ' . implode(', ', $position) . ' possible'); } return $this; } /** - * Get the Footnote Numbering Format + * Get the Footnote Numbering Format. * * @return string */ @@ -109,9 +110,10 @@ public function getNumFmt() } /** - * Set the Footnote Numbering Format + * Set the Footnote Numbering Format. * * @param string $numFmt One of NumberFormat + * * @return self */ public function setNumFmt($numFmt) @@ -123,7 +125,7 @@ public function setNumFmt($numFmt) } /** - * Get the Footnote Numbering Format + * Get the Footnote Numbering Format. * * @return float */ @@ -133,9 +135,10 @@ public function getNumStart() } /** - * Set the Footnote Numbering Format + * Set the Footnote Numbering Format. * * @param float $numStart + * * @return self */ public function setNumStart($numStart) @@ -146,7 +149,7 @@ public function setNumStart($numStart) } /** - * Get the Footnote and Endnote Numbering Starting Value + * Get the Footnote and Endnote Numbering Starting Value. * * @return string */ @@ -156,24 +159,24 @@ public function getNumRestart() } /** - * Set the Footnote and Endnote Numbering Starting Value (continuous, eachSect, eachPage) + * Set the Footnote and Endnote Numbering Starting Value (continuous, eachSect, eachPage). * * @param string $numRestart - * @throws \InvalidArgumentException + * * @return self */ public function setNumRestart($numRestart) { - $restartNumbers = array( + $restartNumbers = [ self::RESTART_NUMBER_CONTINUOUS, self::RESTART_NUMBER_EACH_SECTION, self::RESTART_NUMBER_EACH_PAGE, - ); + ]; if (in_array($numRestart, $restartNumbers)) { $this->numRestart = $numRestart; } else { - throw new \InvalidArgumentException('Invalid value, on of ' . implode(', ', $restartNumbers) . ' possible'); + throw new InvalidArgumentException('Invalid value, on of ' . implode(', ', $restartNumbers) . ' possible'); } return $this; diff --git a/src/PhpWord/ComplexType/ProofState.php b/src/PhpWord/ComplexType/ProofState.php index 4f8dafe3aa..37039cb84e 100644 --- a/src/PhpWord/ComplexType/ProofState.php +++ b/src/PhpWord/ComplexType/ProofState.php @@ -11,48 +11,50 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\ComplexType; +use InvalidArgumentException; + /** - * Spelling and Grammatical Checking State + * Spelling and Grammatical Checking State. * * @see http://www.datypic.com/sc/ooxml/e-w_proofState-1.html */ final class ProofState { /** - * Check Completed + * Check Completed. */ const CLEAN = 'clean'; /** - * Check Not Completed + * Check Not Completed. */ const DIRTY = 'dirty'; /** - * Spell Checking State + * Spell Checking State. * * @var string */ private $spelling; /** - * Grammatical Checking State + * Grammatical Checking State. * * @var string */ private $grammar; /** - * Set the Spell Checking State (dirty or clean) + * Set the Spell Checking State (dirty or clean). * * @param string $spelling - * @throws \InvalidArgumentException + * * @return self */ public function setSpelling($spelling) @@ -60,14 +62,14 @@ public function setSpelling($spelling) if ($spelling == self::CLEAN || $spelling == self::DIRTY) { $this->spelling = $spelling; } else { - throw new \InvalidArgumentException('Invalid value, dirty or clean possible'); + throw new InvalidArgumentException('Invalid value, dirty or clean possible'); } return $this; } /** - * Get the Spell Checking State + * Get the Spell Checking State. * * @return string */ @@ -77,10 +79,10 @@ public function getSpelling() } /** - * Set the Grammatical Checking State (dirty or clean) + * Set the Grammatical Checking State (dirty or clean). * * @param string $grammar - * @throws \InvalidArgumentException + * * @return self */ public function setGrammar($grammar) @@ -88,14 +90,14 @@ public function setGrammar($grammar) if ($grammar == self::CLEAN || $grammar == self::DIRTY) { $this->grammar = $grammar; } else { - throw new \InvalidArgumentException('Invalid value, dirty or clean possible'); + throw new InvalidArgumentException('Invalid value, dirty or clean possible'); } return $this; } /** - * Get the Grammatical Checking State + * Get the Grammatical Checking State. * * @return string */ diff --git a/src/PhpWord/ComplexType/TblWidth.php b/src/PhpWord/ComplexType/TblWidth.php index 0d1a2419a7..6a9368f464 100644 --- a/src/PhpWord/ComplexType/TblWidth.php +++ b/src/PhpWord/ComplexType/TblWidth.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/ComplexType/TrackChangesView.php b/src/PhpWord/ComplexType/TrackChangesView.php index 92ea05eab3..170c56033c 100644 --- a/src/PhpWord/ComplexType/TrackChangesView.php +++ b/src/PhpWord/ComplexType/TrackChangesView.php @@ -11,56 +11,56 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\ComplexType; /** - * Visibility of Annotation Types + * Visibility of Annotation Types. * * @see http://www.datypic.com/sc/ooxml/e-w_revisionView-1.html */ final class TrackChangesView { /** - * Display Visual Indicator Of Markup Area + * Display Visual Indicator Of Markup Area. * * @var bool */ private $markup; /** - * Display Comments + * Display Comments. * * @var bool */ private $comments; /** - * Display Content Revisions + * Display Content Revisions. * * @var bool */ private $insDel; /** - * Display Formatting Revisions + * Display Formatting Revisions. * * @var bool */ private $formatting; /** - * Display Ink Annotations + * Display Ink Annotations. * * @var bool */ private $inkAnnotations; /** - * Get Display Visual Indicator Of Markup Area + * Get Display Visual Indicator Of Markup Area. * * @return bool True if markup is shown */ @@ -70,18 +70,18 @@ public function hasMarkup() } /** - * Set Display Visual Indicator Of Markup Area + * Set Display Visual Indicator Of Markup Area. * * @param bool $markup * Set to true to show markup */ - public function setMarkup($markup) + public function setMarkup($markup): void { $this->markup = $markup === null ? true : $markup; } /** - * Get Display Comments + * Get Display Comments. * * @return bool True if comments are shown */ @@ -91,18 +91,18 @@ public function hasComments() } /** - * Set Display Comments + * Set Display Comments. * * @param bool $comments * Set to true to show comments */ - public function setComments($comments) + public function setComments($comments): void { $this->comments = $comments === null ? true : $comments; } /** - * Get Display Content Revisions + * Get Display Content Revisions. * * @return bool True if content revisions are shown */ @@ -112,18 +112,18 @@ public function hasInsDel() } /** - * Set Display Content Revisions + * Set Display Content Revisions. * * @param bool $insDel * Set to true to show content revisions */ - public function setInsDel($insDel) + public function setInsDel($insDel): void { $this->insDel = $insDel === null ? true : $insDel; } /** - * Get Display Formatting Revisions + * Get Display Formatting Revisions. * * @return bool True if formatting revisions are shown */ @@ -133,18 +133,18 @@ public function hasFormatting() } /** - * Set Display Formatting Revisions + * Set Display Formatting Revisions. * - * @param bool|null $formatting + * @param null|bool $formatting * Set to true to show formatting revisions */ - public function setFormatting($formatting = null) + public function setFormatting($formatting = null): void { $this->formatting = $formatting === null ? true : $formatting; } /** - * Get Display Ink Annotations + * Get Display Ink Annotations. * * @return bool True if ink annotations are shown */ @@ -154,12 +154,12 @@ public function hasInkAnnotations() } /** - * Set Display Ink Annotations + * Set Display Ink Annotations. * * @param bool $inkAnnotations * Set to true to show ink annotations */ - public function setInkAnnotations($inkAnnotations) + public function setInkAnnotations($inkAnnotations): void { $this->inkAnnotations = $inkAnnotations === null ? true : $inkAnnotations; } diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index 6a1ed93013..92838cddfa 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -11,14 +11,17 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Element; +use BadMethodCallException; +use ReflectionClass; + /** - * Container abstract class + * Container abstract class. * * @method Text addText(string $text, mixed $fStyle = null, mixed $pStyle = null) * @method TextRun addTextRun(mixed $pStyle = null) @@ -44,7 +47,6 @@ * @method Chart addChart(string $type, array $categories, array $values, array $style = null, $seriesName = null) * @method FormField addFormField(string $type, mixed $fStyle = null, mixed $pStyle = null) * @method SDT addSDT(string $type) - * * @method \PhpOffice\PhpWord\Element\OLEObject addObject(string $source, mixed $style = null) deprecated, use addOLEObject instead * * @since 0.10.0 @@ -52,21 +54,21 @@ abstract class AbstractContainer extends AbstractElement { /** - * Elements collection + * Elements collection. * * @var \PhpOffice\PhpWord\Element\AbstractElement[] */ - protected $elements = array(); + protected $elements = []; /** - * Container type Section|Header|Footer|Footnote|Endnote|Cell|TextRun|TextBox|ListItemRun|TrackChange + * Container type Section|Header|Footer|Footnote|Endnote|Cell|TextRun|TextBox|ListItemRun|TrackChange. * * @var string */ protected $container; /** - * Magic method to catch all 'addElement' variation + * Magic method to catch all 'addElement' variation. * * This removes addText, addTextRun, etc. When adding new element, we have to * add the model in the class docblock with `@method`. @@ -75,18 +77,19 @@ abstract class AbstractContainer extends AbstractElement * * @param mixed $function * @param mixed $args + * * @return \PhpOffice\PhpWord\Element\AbstractElement */ public function __call($function, $args) { - $elements = array( + $elements = [ 'Text', 'TextRun', 'Bookmark', 'Link', 'PreserveText', 'TextBreak', 'ListItem', 'ListItemRun', 'Table', 'Image', 'Object', 'OLEObject', 'Footnote', 'Endnote', 'CheckBox', 'TextBox', 'Field', 'Line', 'Shape', 'Title', 'TOC', 'PageBreak', 'Chart', 'FormField', 'SDT', 'Comment', - ); - $functions = array(); + ]; + $functions = []; foreach ($elements as $element) { $functions['add' . strtolower($element)] = $element == 'Object' ? 'OLEObject' : $element; } @@ -99,18 +102,18 @@ public function __call($function, $args) // Special case for TextBreak // @todo Remove the `$count` parameter in 1.0.0 to make this element similiar to other elements? if ($element == 'TextBreak') { - list($count, $fontStyle, $paragraphStyle) = array_pad($args, 3, null); + [$count, $fontStyle, $paragraphStyle] = array_pad($args, 3, null); if ($count === null) { $count = 1; } - for ($i = 1; $i <= $count; $i++) { + for ($i = 1; $i <= $count; ++$i) { $this->addElement($element, $fontStyle, $paragraphStyle); } } else { // All other elements array_unshift($args, $element); // Prepend element name to the beginning of args array - return call_user_func_array(array($this, 'addElement'), $args); + return call_user_func_array([$this, 'addElement'], $args); } } @@ -118,11 +121,12 @@ public function __call($function, $args) } /** - * Add element + * Add element. * * Each element has different number of parameters passed * * @param string $elementName + * * @return \PhpOffice\PhpWord\Element\AbstractElement */ protected function addElement($elementName) @@ -132,13 +136,13 @@ protected function addElement($elementName) // Get arguments $args = func_get_args(); - $withoutP = in_array($this->container, array('TextRun', 'Footnote', 'Endnote', 'ListItemRun', 'Field')); + $withoutP = in_array($this->container, ['TextRun', 'Footnote', 'Endnote', 'ListItemRun', 'Field']); if ($withoutP && ($elementName == 'Text' || $elementName == 'PreserveText')) { $args[3] = null; // Remove paragraph style for texts in textrun } // Create element using reflection - $reflection = new \ReflectionClass($elementClass); + $reflection = new ReflectionClass($elementClass); $elementArgs = $args; array_shift($elementArgs); // Shift the $elementName off the beginning of array @@ -156,7 +160,7 @@ protected function addElement($elementName) } /** - * Get all elements + * Get all elements. * * @return \PhpOffice\PhpWord\Element\AbstractElement[] */ @@ -166,10 +170,11 @@ public function getElements() } /** - * Returns the element at the requested position + * Returns the element at the requested position. * * @param int $index - * @return \PhpOffice\PhpWord\Element\AbstractElement|null + * + * @return null|\PhpOffice\PhpWord\Element\AbstractElement */ public function getElement($index) { @@ -181,11 +186,11 @@ public function getElement($index) } /** - * Removes the element at requested index + * Removes the element at requested index. * * @param int|\PhpOffice\PhpWord\Element\AbstractElement $toRemove */ - public function removeElement($toRemove) + public function removeElement($toRemove): void { if (is_int($toRemove) && array_key_exists($toRemove, $this->elements)) { unset($this->elements[$toRemove]); @@ -201,7 +206,7 @@ public function removeElement($toRemove) } /** - * Count elements + * Count elements. * * @return int */ @@ -211,59 +216,58 @@ public function countElements() } /** - * Check if a method is allowed for the current container + * Check if a method is allowed for the current container. * * @param string $method * - * @throws \BadMethodCallException * @return bool */ private function checkValidity($method) { - $generalContainers = array( + $generalContainers = [ 'Section', 'Header', 'Footer', 'Footnote', 'Endnote', 'Cell', 'TextRun', 'TextBox', 'ListItemRun', 'TrackChange', - ); + ]; - $validContainers = array( - 'Text' => $generalContainers, - 'Bookmark' => $generalContainers, - 'Link' => $generalContainers, - 'TextBreak' => $generalContainers, - 'Image' => $generalContainers, - 'OLEObject' => $generalContainers, - 'Field' => $generalContainers, - 'Line' => $generalContainers, - 'Shape' => $generalContainers, - 'FormField' => $generalContainers, - 'SDT' => $generalContainers, - 'TrackChange' => $generalContainers, - 'TextRun' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox', 'TrackChange', 'ListItemRun'), - 'ListItem' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), - 'ListItemRun' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), - 'Table' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), - 'CheckBox' => array('Section', 'Header', 'Footer', 'Cell', 'TextRun'), - 'TextBox' => array('Section', 'Header', 'Footer', 'Cell'), - 'Footnote' => array('Section', 'TextRun', 'Cell', 'ListItemRun'), - 'Endnote' => array('Section', 'TextRun', 'Cell'), - 'PreserveText' => array('Section', 'Header', 'Footer', 'Cell'), - 'Title' => array('Section', 'Cell'), - 'TOC' => array('Section'), - 'PageBreak' => array('Section'), - 'Chart' => array('Section', 'Cell'), - ); + $validContainers = [ + 'Text' => $generalContainers, + 'Bookmark' => $generalContainers, + 'Link' => $generalContainers, + 'TextBreak' => $generalContainers, + 'Image' => $generalContainers, + 'OLEObject' => $generalContainers, + 'Field' => $generalContainers, + 'Line' => $generalContainers, + 'Shape' => $generalContainers, + 'FormField' => $generalContainers, + 'SDT' => $generalContainers, + 'TrackChange' => $generalContainers, + 'TextRun' => ['Section', 'Header', 'Footer', 'Cell', 'TextBox', 'TrackChange', 'ListItemRun'], + 'ListItem' => ['Section', 'Header', 'Footer', 'Cell', 'TextBox'], + 'ListItemRun' => ['Section', 'Header', 'Footer', 'Cell', 'TextBox'], + 'Table' => ['Section', 'Header', 'Footer', 'Cell', 'TextBox'], + 'CheckBox' => ['Section', 'Header', 'Footer', 'Cell', 'TextRun'], + 'TextBox' => ['Section', 'Header', 'Footer', 'Cell'], + 'Footnote' => ['Section', 'TextRun', 'Cell', 'ListItemRun'], + 'Endnote' => ['Section', 'TextRun', 'Cell'], + 'PreserveText' => ['Section', 'Header', 'Footer', 'Cell'], + 'Title' => ['Section', 'Cell'], + 'TOC' => ['Section'], + 'PageBreak' => ['Section'], + 'Chart' => ['Section', 'Cell'], + ]; // Special condition, e.g. preservetext can only exists in cell when // the cell is located in header or footer - $validSubcontainers = array( - 'PreserveText' => array(array('Cell'), array('Header', 'Footer', 'Section')), - 'Footnote' => array(array('Cell', 'TextRun'), array('Section')), - 'Endnote' => array(array('Cell', 'TextRun'), array('Section')), - ); + $validSubcontainers = [ + 'PreserveText' => [['Cell'], ['Header', 'Footer', 'Section']], + 'Footnote' => [['Cell', 'TextRun'], ['Section']], + 'Endnote' => [['Cell', 'TextRun'], ['Section']], + ]; // Check if a method is valid for current container if (isset($validContainers[$method])) { if (!in_array($this->container, $validContainers[$method])) { - throw new \BadMethodCallException("Cannot add {$method} in {$this->container}."); + throw new BadMethodCallException("Cannot add {$method} in {$this->container}."); } } @@ -274,7 +278,7 @@ private function checkValidity($method) $allowedDocParts = $rules[1]; foreach ($containers as $container) { if ($this->container == $container && !in_array($this->getDocPart(), $allowedDocParts)) { - throw new \BadMethodCallException("Cannot add {$method} in {$this->container}."); + throw new BadMethodCallException("Cannot add {$method} in {$this->container}."); } } } @@ -283,7 +287,7 @@ private function checkValidity($method) } /** - * Create textrun element + * Create textrun element. * * @deprecated 0.10.0 * @@ -299,7 +303,7 @@ public function createTextRun($paragraphStyle = null) } /** - * Create footnote element + * Create footnote element. * * @deprecated 0.10.0 * diff --git a/src/PhpWord/Element/AbstractElement.php b/src/PhpWord/Element/AbstractElement.php index 46372b71db..3b59d06cd4 100644 --- a/src/PhpWord/Element/AbstractElement.php +++ b/src/PhpWord/Element/AbstractElement.php @@ -11,38 +11,40 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Element; +use DateTime; +use InvalidArgumentException; use PhpOffice\PhpWord\Media; use PhpOffice\PhpWord\PhpWord; /** - * Element abstract class + * Element abstract class. * * @since 0.10.0 */ abstract class AbstractElement { /** - * PhpWord object + * PhpWord object. * * @var \PhpOffice\PhpWord\PhpWord */ protected $phpWord; /** - * Section Id + * Section Id. * * @var int */ protected $sectionId; /** - * Document part type: Section|Header|Footer|Footnote|Endnote + * Document part type: Section|Header|Footer|Footnote|Endnote. * * Used by textrun and cell container to determine where the element is * located because it will affect the availability of other element, @@ -53,7 +55,7 @@ abstract class AbstractElement protected $docPart = 'Section'; /** - * Document part Id + * Document part Id. * * For header and footer, this will be = ($sectionId - 1) * 3 + $index * because the max number of header/footer in every page is 3, i.e. @@ -64,28 +66,28 @@ abstract class AbstractElement protected $docPartId = 1; /** - * Index of element in the elements collection (start with 1) + * Index of element in the elements collection (start with 1). * * @var int */ protected $elementIndex = 1; /** - * Unique Id for element + * Unique Id for element. * * @var string */ protected $elementId; /** - * Relation Id + * Relation Id. * * @var int */ protected $relationId; /** - * Depth of table container nested level; Primarily used for RTF writer/reader + * Depth of table container nested level; Primarily used for RTF writer/reader. * * 0 = Not in a table; 1 = in a table; 2 = in a table inside another table, etc. * @@ -94,56 +96,56 @@ abstract class AbstractElement private $nestedLevel = 0; /** - * A reference to the parent + * A reference to the parent. * - * @var AbstractElement|null + * @var null|AbstractElement */ private $parent; /** - * changed element info + * changed element info. * * @var TrackChange */ private $trackChange; /** - * Parent container type + * Parent container type. * * @var string */ private $parentContainer; /** - * Has media relation flag; true for Link, Image, and Object + * Has media relation flag; true for Link, Image, and Object. * * @var bool */ protected $mediaRelation = false; /** - * Is part of collection; true for Title, Footnote, Endnote, Chart, and Comment + * Is part of collection; true for Title, Footnote, Endnote, Chart, and Comment. * * @var bool */ protected $collectionRelation = false; /** - * The start position for the linked comment + * The start position for the linked comment. * * @var Comment */ protected $commentRangeStart; /** - * The end position for the linked comment + * The end position for the linked comment. * * @var Comment */ protected $commentRangeEnd; /** - * Get PhpWord + * Get PhpWord. * * @return \PhpOffice\PhpWord\PhpWord */ @@ -157,13 +159,13 @@ public function getPhpWord() * * @param \PhpOffice\PhpWord\PhpWord $phpWord */ - public function setPhpWord(PhpWord $phpWord = null) + public function setPhpWord(?PhpWord $phpWord = null): void { $this->phpWord = $phpWord; } /** - * Get section number + * Get section number. * * @return int */ @@ -178,14 +180,14 @@ public function getSectionId() * @param string $docPart * @param int $docPartId */ - public function setDocPart($docPart, $docPartId = 1) + public function setDocPart($docPart, $docPartId = 1): void { $this->docPart = $docPart; $this->docPartId = $docPartId; } /** - * Get doc part + * Get doc part. * * @return string */ @@ -195,7 +197,7 @@ public function getDocPart() } /** - * Get doc part Id + * Get doc part Id. * * @return int */ @@ -205,7 +207,7 @@ public function getDocPartId() } /** - * Return media element (image, object, link) container name + * Return media element (image, object, link) container name. * * @return string section|headerx|footerx|footnote|endnote */ @@ -220,7 +222,7 @@ private function getMediaPart() } /** - * Get element index + * Get element index. * * @return int */ @@ -234,13 +236,13 @@ public function getElementIndex() * * @param int $value */ - public function setElementIndex($value) + public function setElementIndex($value): void { $this->elementIndex = $value; } /** - * Get element unique ID + * Get element unique ID. * * @return string */ @@ -252,13 +254,13 @@ public function getElementId() /** * Set element unique ID from 6 first digit of md5. */ - public function setElementId() + public function setElementId(): void { - $this->elementId = substr(md5(rand()), 0, 6); + $this->elementId = substr(md5(mt_rand()), 0, 6); } /** - * Get relation Id + * Get relation Id. * * @return int */ @@ -272,13 +274,13 @@ public function getRelationId() * * @param int $value */ - public function setRelationId($value) + public function setRelationId($value): void { $this->relationId = $value; } /** - * Get nested level + * Get nested level. * * @return int */ @@ -288,7 +290,7 @@ public function getNestedLevel() } /** - * Get comment start + * Get comment start. * * @return Comment */ @@ -298,21 +300,19 @@ public function getCommentRangeStart() } /** - * Set comment start - * - * @param Comment $value + * Set comment start. */ - public function setCommentRangeStart(Comment $value) + public function setCommentRangeStart(Comment $value): void { if ($this instanceof Comment) { - throw new \InvalidArgumentException('Cannot set a Comment on a Comment'); + throw new InvalidArgumentException('Cannot set a Comment on a Comment'); } $this->commentRangeStart = $value; $this->commentRangeStart->setStartElement($this); } /** - * Get comment end + * Get comment end. * * @return Comment */ @@ -322,23 +322,21 @@ public function getCommentRangeEnd() } /** - * Set comment end - * - * @param Comment $value + * Set comment end. */ - public function setCommentRangeEnd(Comment $value) + public function setCommentRangeEnd(Comment $value): void { if ($this instanceof Comment) { - throw new \InvalidArgumentException('Cannot set a Comment on a Comment'); + throw new InvalidArgumentException('Cannot set a Comment on a Comment'); } $this->commentRangeEnd = $value; $this->commentRangeEnd->setEndElement($this); } /** - * Get parent element + * Get parent element. * - * @return AbstractElement|null + * @return null|AbstractElement */ public function getParent() { @@ -346,13 +344,13 @@ public function getParent() } /** - * Set parent container + * Set parent container. * * Passed parameter should be a container, except for Table (contain Row) and Row (contain Cell) * * @param \PhpOffice\PhpWord\Element\AbstractElement $container */ - public function setParentContainer(self $container) + public function setParentContainer(self $container): void { $this->parentContainer = substr(get_class($container), strrpos(get_class($container), '\\') + 1); $this->parent = $container; @@ -360,7 +358,7 @@ public function setParentContainer(self $container) // Set nested level $this->nestedLevel = $container->getNestedLevel(); if ($this->parentContainer == 'Cell') { - $this->nestedLevel++; + ++$this->nestedLevel; } // Set phpword @@ -376,18 +374,18 @@ public function setParentContainer(self $container) } /** - * Set relation Id for media elements (link, image, object; legacy of OOXML) + * Set relation Id for media elements (link, image, object; legacy of OOXML). * * - Image element needs to be passed to Media object * - Icon needs to be set for Object element */ - private function setMediaRelation() + private function setMediaRelation(): void { if (!$this instanceof Link && !$this instanceof Image && !$this instanceof OLEObject) { return; } - $elementName = substr(get_class($this), strrpos(get_class($this), '\\') + 1); + $elementName = substr(static::class, strrpos(static::class, '\\') + 1); if ($elementName == 'OLEObject') { $elementName = 'Object'; } @@ -410,10 +408,10 @@ private function setMediaRelation() /** * Set relation Id for elements that will be registered in the Collection subnamespaces. */ - private function setCollectionRelation() + private function setCollectionRelation(): void { if ($this->collectionRelation === true && $this->phpWord instanceof PhpWord) { - $elementName = substr(get_class($this), strrpos(get_class($this), '\\') + 1); + $elementName = substr(static::class, strrpos(static::class, '\\') + 1); $addMethod = "add{$elementName}"; $rId = $this->phpWord->$addMethod($this); $this->setRelationId($rId); @@ -421,7 +419,7 @@ private function setCollectionRelation() } /** - * Check if element is located in Section doc part (as opposed to Header/Footer) + * Check if element is located in Section doc part (as opposed to Header/Footer). * * @return bool */ @@ -431,16 +429,17 @@ public function isInSection() } /** - * Set new style value + * Set new style value. * * @param mixed $styleObject Style object * @param mixed $styleValue Style value * @param bool $returnObject Always return object + * * @return mixed */ protected function setNewStyle($styleObject, $styleValue = null, $returnObject = false) { - if (!is_null($styleValue) && is_array($styleValue)) { + if (null !== $styleValue && is_array($styleValue)) { $styleObject->setStyleByArray($styleValue); $style = $styleObject; } else { @@ -451,17 +450,15 @@ protected function setNewStyle($styleObject, $styleValue = null, $returnObject = } /** - * Sets the trackChange information - * - * @param TrackChange $trackChange + * Sets the trackChange information. */ - public function setTrackChange(TrackChange $trackChange) + public function setTrackChange(TrackChange $trackChange): void { $this->trackChange = $trackChange; } /** - * Gets the trackChange information + * Gets the trackChange information. * * @return TrackChange */ @@ -471,33 +468,32 @@ public function getTrackChange() } /** - * Set changed + * Set changed. * * @param string $type INSERTED|DELETED * @param string $author - * @param null|int|\DateTime $date allways in UTC + * @param null|DateTime|int $date allways in UTC */ - public function setChangeInfo($type, $author, $date = null) + public function setChangeInfo($type, $author, $date = null): void { $this->trackChange = new TrackChange($type, $author, $date); } /** - * Set enum value + * Set enum value. * - * @param string|null $value + * @param null|string $value * @param string[] $enum - * @param string|null $default + * @param null|string $default * - * @throws \InvalidArgumentException - * @return string|null + * @return null|string * * @todo Merge with the same method in AbstractStyle */ - protected function setEnumVal($value = null, $enum = array(), $default = null) + protected function setEnumVal($value = null, $enum = [], $default = null) { if ($value !== null && trim($value) != '' && !empty($enum) && !in_array($value, $enum)) { - throw new \InvalidArgumentException("Invalid style value: {$value}"); + throw new InvalidArgumentException("Invalid style value: {$value}"); } elseif ($value === null || trim($value) == '') { $value = $default; } diff --git a/src/PhpWord/Element/Bookmark.php b/src/PhpWord/Element/Bookmark.php index 856f68600b..4fe3d0f067 100644 --- a/src/PhpWord/Element/Bookmark.php +++ b/src/PhpWord/Element/Bookmark.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,26 +20,26 @@ use PhpOffice\PhpWord\Shared\Text as SharedText; /** - * Bookmark element + * Bookmark element. */ class Bookmark extends AbstractElement { /** - * Bookmark Name + * Bookmark Name. * * @var string */ private $name; /** - * Is part of collection + * Is part of collection. * * @var bool */ protected $collectionRelation = true; /** - * Create a new Bookmark Element + * Create a new Bookmark Element. * * @param string $name */ @@ -49,7 +49,7 @@ public function __construct($name = '') } /** - * Get Bookmark name + * Get Bookmark name. * * @return string */ diff --git a/src/PhpWord/Element/Cell.php b/src/PhpWord/Element/Cell.php index 68f5df6255..f07d246d5d 100644 --- a/src/PhpWord/Element/Cell.php +++ b/src/PhpWord/Element/Cell.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,7 +20,7 @@ use PhpOffice\PhpWord\Style\Cell as CellStyle; /** - * Table cell element + * Table cell element. */ class Cell extends AbstractContainer { @@ -30,21 +30,21 @@ class Cell extends AbstractContainer protected $container = 'Cell'; /** - * Cell width + * Cell width. * * @var int */ - private $width = null; + private $width; /** - * Cell style + * Cell style. * * @var \PhpOffice\PhpWord\Style\Cell */ private $style; /** - * Create new instance + * Create new instance. * * @param int $width * @param array|\PhpOffice\PhpWord\Style\Cell $style @@ -56,7 +56,7 @@ public function __construct($width = null, $style = null) } /** - * Get cell style + * Get cell style. * * @return \PhpOffice\PhpWord\Style\Cell */ @@ -66,7 +66,7 @@ public function getStyle() } /** - * Get cell width + * Get cell width. * * @return int */ diff --git a/src/PhpWord/Element/Chart.php b/src/PhpWord/Element/Chart.php index 92152c877d..f2277c4476 100644 --- a/src/PhpWord/Element/Chart.php +++ b/src/PhpWord/Element/Chart.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,42 +20,42 @@ use PhpOffice\PhpWord\Style\Chart as ChartStyle; /** - * Chart element + * Chart element. * * @since 0.12.0 */ class Chart extends AbstractElement { /** - * Is part of collection + * Is part of collection. * * @var bool */ protected $collectionRelation = true; /** - * Type + * Type. * * @var string */ private $type = 'pie'; /** - * Series + * Series. * * @var array */ - private $series = array(); + private $series = []; /** - * Chart style + * Chart style. * * @var \PhpOffice\PhpWord\Style\Chart */ private $style; /** - * Create new instance + * Create new instance. * * @param string $type * @param array $categories @@ -71,7 +71,7 @@ public function __construct($type, $categories, $values, $style = null, $seriesN } /** - * Get type + * Get type. * * @return string */ @@ -85,30 +85,30 @@ public function getType() * * @param string $value */ - public function setType($value) + public function setType($value): void { - $enum = array('pie', 'doughnut', 'line', 'bar', 'stacked_bar', 'percent_stacked_bar', 'column', 'stacked_column', 'percent_stacked_column', 'area', 'radar', 'scatter'); + $enum = ['pie', 'doughnut', 'line', 'bar', 'stacked_bar', 'percent_stacked_bar', 'column', 'stacked_column', 'percent_stacked_column', 'area', 'radar', 'scatter']; $this->type = $this->setEnumVal($value, $enum, 'pie'); } /** - * Add series + * Add series. * * @param array $categories * @param array $values * @param null|mixed $name */ - public function addSeries($categories, $values, $name = null) + public function addSeries($categories, $values, $name = null): void { - $this->series[] = array( + $this->series[] = [ 'categories' => $categories, - 'values' => $values, - 'name' => $name, - ); + 'values' => $values, + 'name' => $name, + ]; } /** - * Get series + * Get series. * * @return array */ @@ -118,7 +118,7 @@ public function getSeries() } /** - * Get chart style + * Get chart style. * * @return \PhpOffice\PhpWord\Style\Chart */ diff --git a/src/PhpWord/Element/CheckBox.php b/src/PhpWord/Element/CheckBox.php index beabf8a0a8..80b17a87c7 100644 --- a/src/PhpWord/Element/CheckBox.php +++ b/src/PhpWord/Element/CheckBox.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,21 +20,21 @@ use PhpOffice\PhpWord\Shared\Text as SharedText; /** - * Check box element + * Check box element. * * @since 0.10.0 */ class CheckBox extends Text { /** - * Name content + * Name content. * * @var string */ private $name; /** - * Create new instance + * Create new instance. * * @param string $name * @param string $text @@ -48,9 +48,10 @@ public function __construct($name = null, $text = null, $fontStyle = null, $para } /** - * Set name content + * Set name content. * * @param string $name + * * @return self */ public function setName($name) @@ -61,7 +62,7 @@ public function setName($name) } /** - * Get name content + * Get name content. * * @return string */ diff --git a/src/PhpWord/Element/Comment.php b/src/PhpWord/Element/Comment.php index 96ad15ef4e..6972f82379 100644 --- a/src/PhpWord/Element/Comment.php +++ b/src/PhpWord/Element/Comment.php @@ -11,51 +11,54 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Element; +use DateTime; + /** - * Comment element + * Comment element. + * * @see http://datypic.com/sc/ooxml/t-w_CT_Comment.html */ class Comment extends TrackChange { /** - * Initials + * Initials. * * @var string */ private $initials; /** - * The Element where this comment starts + * The Element where this comment starts. * * @var AbstractElement */ private $startElement; /** - * The Element where this comment ends + * The Element where this comment ends. * * @var AbstractElement */ private $endElement; /** - * Is part of collection + * Is part of collection. * * @var bool */ protected $collectionRelation = true; /** - * Create a new Comment Element + * Create a new Comment Element. * * @param string $author - * @param null|\DateTime $date + * @param null|DateTime $date * @param string $initials */ public function __construct($author, $date = null, $initials = null) @@ -65,7 +68,7 @@ public function __construct($author, $date = null, $initials = null) } /** - * Get Initials + * Get Initials. * * @return string */ @@ -75,11 +78,11 @@ public function getInitials() } /** - * Sets the element where this comment starts + * Sets the element where this comment starts. * * @param \PhpOffice\PhpWord\Element\AbstractElement $value */ - public function setStartElement(AbstractElement $value) + public function setStartElement(AbstractElement $value): void { $this->startElement = $value; if ($value->getCommentRangeStart() == null) { @@ -88,7 +91,7 @@ public function setStartElement(AbstractElement $value) } /** - * Get the element where this comment starts + * Get the element where this comment starts. * * @return \PhpOffice\PhpWord\Element\AbstractElement */ @@ -98,11 +101,11 @@ public function getStartElement() } /** - * Sets the element where this comment ends + * Sets the element where this comment ends. * * @param \PhpOffice\PhpWord\Element\AbstractElement $value */ - public function setEndElement(AbstractElement $value) + public function setEndElement(AbstractElement $value): void { $this->endElement = $value; if ($value->getCommentRangeEnd() == null) { @@ -111,7 +114,7 @@ public function setEndElement(AbstractElement $value) } /** - * Get the element where this comment ends + * Get the element where this comment ends. * * @return \PhpOffice\PhpWord\Element\AbstractElement */ diff --git a/src/PhpWord/Element/Endnote.php b/src/PhpWord/Element/Endnote.php index b962719502..2888fdebc3 100644 --- a/src/PhpWord/Element/Endnote.php +++ b/src/PhpWord/Element/Endnote.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Element; /** - * Endnote element + * Endnote element. * * @since 0.10.0 */ @@ -30,9 +30,9 @@ class Endnote extends Footnote protected $container = 'Endnote'; /** - * Create new instance + * Create new instance. * - * @param string|array|\PhpOffice\PhpWord\Style\Paragraph $paragraphStyle + * @param array|\PhpOffice\PhpWord\Style\Paragraph|string $paragraphStyle */ public function __construct($paragraphStyle = null) { diff --git a/src/PhpWord/Element/Field.php b/src/PhpWord/Element/Field.php index 3d1503fe22..a912f3ca22 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -11,16 +11,17 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Element; +use InvalidArgumentException; use PhpOffice\PhpWord\Style\Font; /** - * Field element + * Field element. * * @since 0.11.0 * @see http://www.schemacentral.com/sc/ooxml/t-w_CT_SimpleField.html @@ -29,103 +30,104 @@ class Field extends AbstractElement { /** * Field properties and options. Depending on type, a field can have different properties - * and options + * and options. * * @var array */ - protected $fieldsArray = array( - 'PAGE' => array( - 'properties' => array( - 'format' => array('Arabic', 'ArabicDash', 'alphabetic', 'ALPHABETIC', 'roman', 'ROMAN'), - ), - 'options' => array('PreserveFormat'), - ), - 'NUMPAGES' => array( - 'properties' => array( - 'format' => array('Arabic', 'ArabicDash', 'CardText', 'DollarText', 'Ordinal', 'OrdText', - 'alphabetic', 'ALPHABETIC', 'roman', 'ROMAN', 'Caps', 'FirstCap', 'Lower', 'Upper', ), - 'numformat' => array('0', '0,00', '#.##0', '#.##0,00', '€ #.##0,00(€ #.##0,00)', '0%', '0,00%'), - ), - 'options' => array('PreserveFormat'), - ), - 'DATE' => array( - 'properties' => array( - 'dateformat' => array( - /* Generic formats */ + protected $fieldsArray = [ + 'PAGE' => [ + 'properties' => [ + 'format' => ['Arabic', 'ArabicDash', 'alphabetic', 'ALPHABETIC', 'roman', 'ROMAN'], + ], + 'options' => ['PreserveFormat'], + ], + 'NUMPAGES' => [ + 'properties' => [ + 'format' => ['Arabic', 'ArabicDash', 'CardText', 'DollarText', 'Ordinal', 'OrdText', + 'alphabetic', 'ALPHABETIC', 'roman', 'ROMAN', 'Caps', 'FirstCap', 'Lower', 'Upper', ], + 'numformat' => ['0', '0,00', '#.##0', '#.##0,00', '€ #.##0,00(€ #.##0,00)', '0%', '0,00%'], + ], + 'options' => ['PreserveFormat'], + ], + 'DATE' => [ + 'properties' => [ + 'dateformat' => [ + // Generic formats 'yyyy-MM-dd', 'yyyy-MM', 'MMM-yy', 'MMM-yyyy', 'h:mm am/pm', 'h:mm:ss am/pm', 'HH:mm', 'HH:mm:ss', - /* Day-Month-Year formats */ + // Day-Month-Year formats 'dddd d MMMM yyyy', 'd MMMM yyyy', 'd-MMM-yy', 'd MMM. yy', 'd-M-yy', 'd-M-yy h:mm', 'd-M-yy h:mm:ss', 'd-M-yy h:mm am/pm', 'd-M-yy h:mm:ss am/pm', 'd-M-yy HH:mm', 'd-M-yy HH:mm:ss', 'd/M/yy', 'd/M/yy h:mm', 'd/M/yy h:mm:ss', 'd/M/yy h:mm am/pm', 'd/M/yy h:mm:ss am/pm', 'd/M/yy HH:mm', 'd/M/yy HH:mm:ss', 'd-M-yyyy', 'd-M-yyyy h:mm', 'd-M-yyyy h:mm:ss', 'd-M-yyyy h:mm am/pm', 'd-M-yyyy h:mm:ss am/pm', 'd-M-yyyy HH:mm', 'd-M-yyyy HH:mm:ss', 'd/M/yyyy', 'd/M/yyyy h:mm', 'd/M/yyyy h:mm:ss', 'd/M/yyyy h:mm am/pm', 'd/M/yyyy h:mm:ss am/pm', 'd/M/yyyy HH:mm', 'd/M/yyyy HH:mm:ss', - /* Month-Day-Year formats */ + // Month-Day-Year formats 'dddd, MMMM d yyyy', 'MMMM d yyyy', 'MMM-d-yy', 'MMM. d yy', 'M-d-yy', 'M-d-yy h:mm', 'M-d-yy h:mm:ss', 'M-d-yy h:mm am/pm', 'M-d-yy h:mm:ss am/pm', 'M-d-yy HH:mm', 'M-d-yy HH:mm:ss', 'M/d/yy', 'M/d/yy h:mm', 'M/d/yy h:mm:ss', 'M/d/yy h:mm am/pm', 'M/d/yy h:mm:ss am/pm', 'M/d/yy HH:mm', 'M/d/yy HH:mm:ss', 'M-d-yyyy', 'M-d-yyyy h:mm', 'M-d-yyyy h:mm:ss', 'M-d-yyyy h:mm am/pm', 'M-d-yyyy h:mm:ss am/pm', 'M-d-yyyy HH:mm', 'M-d-yyyy HH:mm:ss', 'M/d/yyyy', 'M/d/yyyy h:mm', 'M/d/yyyy h:mm:ss', 'M/d/yyyy h:mm am/pm', 'M/d/yyyy h:mm:ss am/pm', 'M/d/yyyy HH:mm', 'M/d/yyyy HH:mm:ss', - ), - ), - 'options' => array('PreserveFormat', 'LunarCalendar', 'SakaEraCalendar', 'LastUsedFormat'), - ), - 'MACROBUTTON' => array( - 'properties' => array('macroname' => ''), - ), - 'XE' => array( - 'properties' => array(), - 'options' => array('Bold', 'Italic'), - ), - 'INDEX' => array( - 'properties' => array(), - 'options' => array('PreserveFormat'), - ), - 'STYLEREF' => array( - 'properties' => array('StyleIdentifier' => ''), - 'options' => array('PreserveFormat'), - ), - ); + ], + ], + 'options' => ['PreserveFormat', 'LunarCalendar', 'SakaEraCalendar', 'LastUsedFormat'], + ], + 'MACROBUTTON' => [ + 'properties' => ['macroname' => ''], + ], + 'XE' => [ + 'properties' => [], + 'options' => ['Bold', 'Italic'], + ], + 'INDEX' => [ + 'properties' => [], + 'options' => ['PreserveFormat'], + ], + 'STYLEREF' => [ + 'properties' => ['StyleIdentifier' => ''], + 'options' => ['PreserveFormat'], + ], + ]; /** - * Field type + * Field type. * * @var string */ protected $type; /** - * Field text + * Field text. * - * @var TextRun|string + * @var string|TextRun */ protected $text; /** - * Field properties + * Field properties. * * @var array */ - protected $properties = array(); + protected $properties = []; /** - * Field options + * Field options. * * @var array */ - protected $options = array(); + protected $options = []; /** - * Font style + * Font style. * - * @var string|\PhpOffice\PhpWord\Style\Font + * @var \PhpOffice\PhpWord\Style\Font|string */ protected $fontStyle; /** - * Set Font style + * Set Font style. + * + * @param array|\PhpOffice\PhpWord\Style\Font|string $style * - * @param string|array|\PhpOffice\PhpWord\Style\Font $style - * @return string|\PhpOffice\PhpWord\Style\Font + * @return \PhpOffice\PhpWord\Style\Font|string */ public function setFontStyle($style = null) { @@ -144,9 +146,9 @@ public function setFontStyle($style = null) } /** - * Get Font style + * Get Font style. * - * @return string|\PhpOffice\PhpWord\Style\Font + * @return \PhpOffice\PhpWord\Style\Font|string */ public function getFontStyle() { @@ -154,15 +156,15 @@ public function getFontStyle() } /** - * Create a new Field Element + * Create a new Field Element. * * @param string $type * @param array $properties * @param array $options - * @param TextRun|string|null $text - * @param string|array|\PhpOffice\PhpWord\Style\Font $fontStyle + * @param null|string|TextRun $text + * @param array|\PhpOffice\PhpWord\Style\Font|string $fontStyle */ - public function __construct($type = null, $properties = array(), $options = array(), $text = null, $fontStyle = null) + public function __construct($type = null, $properties = [], $options = [], $text = null, $fontStyle = null) { $this->setType($type); $this->setProperties($properties); @@ -172,11 +174,10 @@ public function __construct($type = null, $properties = array(), $options = arra } /** - * Set Field type + * Set Field type. * * @param string $type * - * @throws \InvalidArgumentException * @return string */ public function setType($type = null) @@ -185,7 +186,7 @@ public function setType($type = null) if (isset($this->fieldsArray[$type])) { $this->type = $type; } else { - throw new \InvalidArgumentException("Invalid type '$type'"); + throw new InvalidArgumentException("Invalid type '$type'"); } } @@ -193,7 +194,7 @@ public function setType($type = null) } /** - * Get Field type + * Get Field type. * * @return string */ @@ -203,19 +204,18 @@ public function getType() } /** - * Set Field properties + * Set Field properties. * * @param array $properties * - * @throws \InvalidArgumentException * @return self */ - public function setProperties($properties = array()) + public function setProperties($properties = []) { if (is_array($properties)) { foreach (array_keys($properties) as $propkey) { if (!(isset($this->fieldsArray[$this->type]['properties'][$propkey]))) { - throw new \InvalidArgumentException("Invalid property '$propkey'"); + throw new InvalidArgumentException("Invalid property '$propkey'"); } } $this->properties = array_merge($this->properties, $properties); @@ -225,7 +225,7 @@ public function setProperties($properties = array()) } /** - * Get Field properties + * Get Field properties. * * @return array */ @@ -235,19 +235,18 @@ public function getProperties() } /** - * Set Field options + * Set Field options. * * @param array $options * - * @throws \InvalidArgumentException * @return self */ - public function setOptions($options = array()) + public function setOptions($options = []) { if (is_array($options)) { foreach (array_keys($options) as $optionkey) { if (!(isset($this->fieldsArray[$this->type]['options'][$optionkey])) && substr($optionkey, 0, 1) !== '\\') { - throw new \InvalidArgumentException("Invalid option '$optionkey', possible values are " . implode(', ', $this->fieldsArray[$this->type]['options'])); + throw new InvalidArgumentException("Invalid option '$optionkey', possible values are " . implode(', ', $this->fieldsArray[$this->type]['options'])); } } $this->options = array_merge($this->options, $options); @@ -257,7 +256,7 @@ public function setOptions($options = array()) } /** - * Get Field properties + * Get Field properties. * * @return array */ @@ -267,11 +266,10 @@ public function getOptions() } /** - * Set Field text + * Set Field text. * * @param string|TextRun $text * - * @throws \InvalidArgumentException * @return null|string|TextRun */ public function setText($text = null) @@ -280,7 +278,7 @@ public function setText($text = null) if (is_string($text) || $text instanceof TextRun) { $this->text = $text; } else { - throw new \InvalidArgumentException('Invalid text'); + throw new InvalidArgumentException('Invalid text'); } } @@ -288,7 +286,7 @@ public function setText($text = null) } /** - * Get Field text + * Get Field text. * * @return string|TextRun */ diff --git a/src/PhpWord/Element/Footer.php b/src/PhpWord/Element/Footer.php index 0290d7c1de..a9c48f7714 100644 --- a/src/PhpWord/Element/Footer.php +++ b/src/PhpWord/Element/Footer.php @@ -11,21 +11,22 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Element; /** - * Footer element + * Footer element. */ class Footer extends AbstractContainer { /** - * Header/footer types constants + * Header/footer types constants. * * @var string + * * @see http://www.datypic.com/sc/ooxml/t-w_ST_HdrFtr.html Header or Footer Type */ const AUTO = 'default'; // default and odd pages @@ -38,14 +39,14 @@ class Footer extends AbstractContainer protected $container = 'Footer'; /** - * Header type + * Header type. * * @var string */ protected $type = self::AUTO; /** - * Create new instance + * Create new instance. * * @param int $sectionId * @param int $containerId @@ -65,18 +66,19 @@ public function __construct($sectionId, $containerId = 1, $type = self::AUTO) * * @param string $value */ - public function setType($value = self::AUTO) + public function setType($value = self::AUTO): void { - if (!in_array($value, array(self::AUTO, self::FIRST, self::EVEN))) { + if (!in_array($value, [self::AUTO, self::FIRST, self::EVEN])) { $value = self::AUTO; } $this->type = $value; } /** - * Get type + * Get type. * * @return string + * * @since 0.10.0 */ public function getType() @@ -85,7 +87,7 @@ public function getType() } /** - * Reset type to default + * Reset type to default. * * @return string */ @@ -95,7 +97,7 @@ public function resetType() } /** - * First page only header + * First page only header. * * @return string */ @@ -105,7 +107,7 @@ public function firstPage() } /** - * Even numbered pages only + * Even numbered pages only. * * @return string */ diff --git a/src/PhpWord/Element/Footnote.php b/src/PhpWord/Element/Footnote.php index 90aabccca9..291a44db76 100644 --- a/src/PhpWord/Element/Footnote.php +++ b/src/PhpWord/Element/Footnote.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -27,23 +27,23 @@ class Footnote extends AbstractContainer protected $container = 'Footnote'; /** - * Paragraph style + * Paragraph style. * - * @var string|\PhpOffice\PhpWord\Style\Paragraph + * @var \PhpOffice\PhpWord\Style\Paragraph|string */ protected $paragraphStyle; /** - * Is part of collection + * Is part of collection. * * @var bool */ protected $collectionRelation = true; /** - * Create new instance + * Create new instance. * - * @param string|array|\PhpOffice\PhpWord\Style\Paragraph $paragraphStyle + * @param array|\PhpOffice\PhpWord\Style\Paragraph|string $paragraphStyle */ public function __construct($paragraphStyle = null) { @@ -52,9 +52,9 @@ public function __construct($paragraphStyle = null) } /** - * Get paragraph style + * Get paragraph style. * - * @return string|\PhpOffice\PhpWord\Style\Paragraph + * @return \PhpOffice\PhpWord\Style\Paragraph|string */ public function getParagraphStyle() { @@ -62,9 +62,10 @@ public function getParagraphStyle() } /** - * Get Footnote Reference ID + * Get Footnote Reference ID. * * @deprecated 0.10.0 + * * @codeCoverageIgnore * * @return int @@ -75,14 +76,15 @@ public function getReferenceId() } /** - * Set Footnote Reference ID + * Set Footnote Reference ID. * * @deprecated 0.10.0 + * * @codeCoverageIgnore * * @param int $rId */ - public function setReferenceId($rId) + public function setReferenceId($rId): void { $this->setRelationId($rId); } diff --git a/src/PhpWord/Element/FormField.php b/src/PhpWord/Element/FormField.php index f937df59c4..23cded7229 100644 --- a/src/PhpWord/Element/FormField.php +++ b/src/PhpWord/Element/FormField.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Element; /** - * Form field element + * Form field element. * * @since 0.12.0 * @see http://www.datypic.com/sc/ooxml/t-w_CT_FFData.html @@ -26,46 +26,46 @@ class FormField extends Text { /** - * Form field type: textinput|checkbox|dropdown + * Form field type: textinput|checkbox|dropdown. * * @var string */ private $type = 'textinput'; /** - * Form field name + * Form field name. * - * @var string|bool|int + * @var bool|int|string */ private $name; /** - * Default value + * Default value. * * - TextInput: string * - CheckBox: bool * - DropDown: int Index of entries (zero based) * - * @var string|bool|int + * @var bool|int|string */ private $default; /** - * Value + * Value. * - * @var string|bool|int + * @var bool|int|string */ private $value; /** - * Dropdown entries + * Dropdown entries. * * @var array */ - private $entries = array(); + private $entries = []; /** - * Create new instance + * Create new instance. * * @param string $type * @param mixed $fontStyle @@ -78,7 +78,7 @@ public function __construct($type, $fontStyle = null, $paragraphStyle = null) } /** - * Get type + * Get type. * * @return string */ @@ -88,21 +88,22 @@ public function getType() } /** - * Set type + * Set type. * * @param string $value + * * @return self */ public function setType($value) { - $enum = array('textinput', 'checkbox', 'dropdown'); + $enum = ['textinput', 'checkbox', 'dropdown']; $this->type = $this->setEnumVal($value, $enum, $this->type); return $this; } /** - * Get name + * Get name. * * @return string */ @@ -112,9 +113,10 @@ public function getName() } /** - * Set name + * Set name. + * + * @param bool|int|string $value * - * @param string|bool|int $value * @return self */ public function setName($value) @@ -125,9 +127,9 @@ public function setName($value) } /** - * Get default + * Get default. * - * @return string|bool|int + * @return bool|int|string */ public function getDefault() { @@ -135,9 +137,10 @@ public function getDefault() } /** - * Set default + * Set default. + * + * @param bool|int|string $value * - * @param string|bool|int $value * @return self */ public function setDefault($value) @@ -148,9 +151,9 @@ public function setDefault($value) } /** - * Get value + * Get value. * - * @return string|bool|int + * @return bool|int|string */ public function getValue() { @@ -158,9 +161,10 @@ public function getValue() } /** - * Set value + * Set value. + * + * @param bool|int|string $value * - * @param string|bool|int $value * @return self */ public function setValue($value) @@ -171,7 +175,7 @@ public function setValue($value) } /** - * Get entries + * Get entries. * * @return array */ @@ -181,9 +185,10 @@ public function getEntries() } /** - * Set entries + * Set entries. * * @param array $value + * * @return self */ public function setEntries($value) diff --git a/src/PhpWord/Element/Header.php b/src/PhpWord/Element/Header.php index 8a01946ea9..9a87241609 100644 --- a/src/PhpWord/Element/Header.php +++ b/src/PhpWord/Element/Header.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Element; /** - * Header element + * Header element. */ class Header extends Footer { @@ -28,10 +28,11 @@ class Header extends Footer protected $container = 'Header'; /** - * Add a Watermark Element + * Add a Watermark Element. * * @param string $src * @param mixed $style + * * @return Image */ public function addWatermark($src, $style = null) diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php index d53da182f5..dd532a4b2f 100644 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -25,12 +25,12 @@ use PhpOffice\PhpWord\Style\Image as ImageStyle; /** - * Image element + * Image element. */ class Image extends AbstractElement { /** - * Image source type constants + * Image source type constants. */ const SOURCE_LOCAL = 'local'; // Local images const SOURCE_GD = 'gd'; // Generated using GD @@ -38,106 +38,103 @@ class Image extends AbstractElement const SOURCE_STRING = 'string'; // Image from string /** - * Image source + * Image source. * * @var string */ private $source; /** - * Source type: local|gd|archive + * Source type: local|gd|archive. * * @var string */ private $sourceType; /** - * Image style + * Image style. * * @var ImageStyle */ private $style; /** - * Is watermark + * Is watermark. * * @var bool */ private $watermark; /** - * Name of image + * Name of image. * * @var string */ private $name; /** - * Image type + * Image type. * * @var string */ private $imageType; /** - * Image create function + * Image create function. * * @var string */ private $imageCreateFunc; /** - * Image function + * Image function. * * @var string */ private $imageFunc; /** - * Image extension + * Image extension. * * @var string */ private $imageExtension; /** - * Is memory image + * Is memory image. * * @var bool */ private $memoryImage; /** - * Image target file name + * Image target file name. * * @var string */ private $target; /** - * Image media index + * Image media index. * * @var int */ private $mediaIndex; /** - * Has media relation flag; true for Link, Image, and Object + * Has media relation flag; true for Link, Image, and Object. * * @var bool */ protected $mediaRelation = true; /** - * Create new image element + * Create new image element. * * @param string $source * @param mixed $style * @param bool $watermark * @param string $name - * - * @throws \PhpOffice\PhpWord\Exception\InvalidImageException - * @throws \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException */ public function __construct($source, $style = null, $watermark = false, $name = null) { @@ -150,7 +147,7 @@ public function __construct($source, $style = null, $watermark = false, $name = } /** - * Get Image style + * Get Image style. * * @return ImageStyle */ @@ -160,7 +157,7 @@ public function getStyle() } /** - * Get image source + * Get image source. * * @return string */ @@ -170,7 +167,7 @@ public function getSource() } /** - * Get image source type + * Get image source type. * * @return string */ @@ -180,17 +177,17 @@ public function getSourceType() } /** - * Sets the image name + * Sets the image name. * * @param string $value */ - public function setName($value) + public function setName($value): void { $this->name = $value; } /** - * Get image name + * Get image name. * * @return null|string */ @@ -200,7 +197,7 @@ public function getName() } /** - * Get image media ID + * Get image media ID. * * @return string */ @@ -210,7 +207,7 @@ public function getMediaId() } /** - * Get is watermark + * Get is watermark. * * @return bool */ @@ -220,17 +217,17 @@ public function isWatermark() } /** - * Set is watermark + * Set is watermark. * * @param bool $value */ - public function setIsWatermark($value) + public function setIsWatermark($value): void { $this->watermark = $value; } /** - * Get image type + * Get image type. * * @return string */ @@ -240,7 +237,7 @@ public function getImageType() } /** - * Get image create function + * Get image create function. * * @return string */ @@ -250,7 +247,7 @@ public function getImageCreateFunction() } /** - * Get image function + * Get image function. * * @return string */ @@ -260,7 +257,7 @@ public function getImageFunction() } /** - * Get image extension + * Get image extension. * * @return string */ @@ -270,7 +267,7 @@ public function getImageExtension() } /** - * Get is memory image + * Get is memory image. * * @return bool */ @@ -280,7 +277,7 @@ public function isMemImage() } /** - * Get target file name + * Get target file name. * * @return string */ @@ -294,13 +291,13 @@ public function getTarget() * * @param string $value */ - public function setTarget($value) + public function setTarget($value): void { $this->target = $value; } /** - * Get media index + * Get media index. * * @return int */ @@ -314,16 +311,18 @@ public function getMediaIndex() * * @param int $value */ - public function setMediaIndex($value) + public function setMediaIndex($value): void { $this->mediaIndex = $value; } /** - * Get image string data + * Get image string data. * * @param bool $base64 - * @return string|null + * + * @return null|string + * * @since 0.11.0 */ public function getImageStringData($base64 = false) @@ -338,7 +337,7 @@ public function getImageStringData($base64 = false) // Return null if not found if ($this->sourceType == self::SOURCE_ARCHIVE) { $source = substr($source, 6); - list($zipFilename, $imageFilename) = explode('#', $source); + [$zipFilename, $imageFilename] = explode('#', $source); $zip = new ZipArchive(); if ($zip->open($zipFilename) !== false) { @@ -398,11 +397,8 @@ public function getImageStringData($base64 = false) /** * Check memory image, supported type, image functions, and proportional width/height. - * - * @throws \PhpOffice\PhpWord\Exception\InvalidImageException - * @throws \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException */ - private function checkImage() + private function checkImage(): void { $this->setSourceType(); @@ -417,12 +413,12 @@ private function checkImage() if (!is_array($imageData)) { throw new InvalidImageException(sprintf('Invalid image: %s', $this->source)); } - list($actualWidth, $actualHeight, $imageType) = $imageData; + [$actualWidth, $actualHeight, $imageType] = $imageData; // Check image type support - $supportedTypes = array(IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_PNG); + $supportedTypes = [IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_PNG]; if ($this->sourceType != self::SOURCE_GD && $this->sourceType != self::SOURCE_STRING) { - $supportedTypes = array_merge($supportedTypes, array(IMAGETYPE_BMP, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM)); + $supportedTypes = array_merge($supportedTypes, [IMAGETYPE_BMP, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM]); } if (!in_array($imageType, $supportedTypes)) { throw new UnsupportedImageTypeException(); @@ -437,7 +433,7 @@ private function checkImage() /** * Set source type. */ - private function setSourceType() + private function setSourceType(): void { if (stripos(strrev($this->source), strrev('.php')) === 0) { $this->memoryImage = true; @@ -464,21 +460,19 @@ private function setSourceType() } /** - * Get image size from archive + * Get image size from archive. * * @since 0.12.0 Throws CreateTemporaryFileException. * * @param string $source * - * @throws \PhpOffice\PhpWord\Exception\CreateTemporaryFileException - * - * @return array|null + * @return null|array */ private function getArchiveImageSize($source) { $imageData = null; $source = substr($source, 6); - list($zipFilename, $imageFilename) = explode('#', $source); + [$zipFilename, $imageFilename] = explode('#', $source); $tempFilename = tempnam(Settings::getTempDir(), 'PHPWordImage'); if (false === $tempFilename) { @@ -504,32 +498,37 @@ private function getArchiveImageSize($source) /** * Set image functions and extensions. */ - private function setFunctions() + private function setFunctions(): void { switch ($this->imageType) { case 'image/png': $this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefrompng'; $this->imageFunc = 'imagepng'; $this->imageExtension = 'png'; + break; case 'image/gif': $this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefromgif'; $this->imageFunc = 'imagegif'; $this->imageExtension = 'gif'; + break; case 'image/jpeg': case 'image/jpg': $this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefromjpeg'; $this->imageFunc = 'imagejpeg'; $this->imageExtension = 'jpg'; + break; case 'image/bmp': case 'image/x-ms-bmp': $this->imageType = 'image/bmp'; $this->imageExtension = 'bmp'; + break; case 'image/tiff': $this->imageExtension = 'tif'; + break; } } @@ -540,7 +539,7 @@ private function setFunctions() * @param int $actualWidth * @param int $actualHeight */ - private function setProportionalSize($actualWidth, $actualHeight) + private function setProportionalSize($actualWidth, $actualHeight): void { $styleWidth = $this->style->getWidth(); $styleHeight = $this->style->getHeight(); @@ -557,7 +556,7 @@ private function setProportionalSize($actualWidth, $actualHeight) } /** - * Get is watermark + * Get is watermark. * * @deprecated 0.10.0 * @@ -569,7 +568,7 @@ public function getIsWatermark() } /** - * Get is memory image + * Get is memory image. * * @deprecated 0.10.0 * diff --git a/src/PhpWord/Element/Line.php b/src/PhpWord/Element/Line.php index 7e40b9402d..7659a11483 100644 --- a/src/PhpWord/Element/Line.php +++ b/src/PhpWord/Element/Line.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,19 +20,19 @@ use PhpOffice\PhpWord\Style\Line as LineStyle; /** - * Line element + * Line element. */ class Line extends AbstractElement { /** - * Line style + * Line style. * * @var \PhpOffice\PhpWord\Style\Line */ private $style; /** - * Create new line element + * Create new line element. * * @param mixed $style */ @@ -42,7 +42,7 @@ public function __construct($style = null) } /** - * Get line style + * Get line style. * * @return \PhpOffice\PhpWord\Style\Line */ diff --git a/src/PhpWord/Element/Link.php b/src/PhpWord/Element/Link.php index 25a87feecb..ddf5d31f70 100644 --- a/src/PhpWord/Element/Link.php +++ b/src/PhpWord/Element/Link.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -22,54 +22,54 @@ use PhpOffice\PhpWord\Style\Paragraph; /** - * Link element + * Link element. */ class Link extends AbstractElement { /** - * Link source + * Link source. * * @var string */ private $source; /** - * Link text + * Link text. * * @var string */ private $text; /** - * Font style + * Font style. * - * @var string|\PhpOffice\PhpWord\Style\Font + * @var \PhpOffice\PhpWord\Style\Font|string */ private $fontStyle; /** - * Paragraph style + * Paragraph style. * - * @var string|\PhpOffice\PhpWord\Style\Paragraph + * @var \PhpOffice\PhpWord\Style\Paragraph|string */ private $paragraphStyle; /** - * Has media relation flag; true for Link, Image, and Object + * Has media relation flag; true for Link, Image, and Object. * * @var bool */ protected $mediaRelation = true; /** - * Has internal flag - anchor to internal bookmark + * Has internal flag - anchor to internal bookmark. * * @var bool */ protected $internal = false; /** - * Create a new Link Element + * Create a new Link Element. * * @param string $source * @param string $text @@ -80,14 +80,14 @@ class Link extends AbstractElement public function __construct($source, $text = null, $fontStyle = null, $paragraphStyle = null, $internal = false) { $this->source = SharedText::toUTF8($source); - $this->text = is_null($text) ? $this->source : SharedText::toUTF8($text); + $this->text = null === $text ? $this->source : SharedText::toUTF8($text); $this->fontStyle = $this->setNewStyle(new Font('text'), $fontStyle); $this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle); $this->internal = $internal; } /** - * Get link source + * Get link source. * * @return string */ @@ -97,7 +97,7 @@ public function getSource() } /** - * Get link text + * Get link text. * * @return string */ @@ -107,9 +107,9 @@ public function getText() } /** - * Get Text style + * Get Text style. * - * @return string|\PhpOffice\PhpWord\Style\Font + * @return \PhpOffice\PhpWord\Style\Font|string */ public function getFontStyle() { @@ -117,9 +117,9 @@ public function getFontStyle() } /** - * Get Paragraph style + * Get Paragraph style. * - * @return string|\PhpOffice\PhpWord\Style\Paragraph + * @return \PhpOffice\PhpWord\Style\Paragraph|string */ public function getParagraphStyle() { @@ -127,7 +127,7 @@ public function getParagraphStyle() } /** - * Get link target + * Get link target. * * @deprecated 0.12.0 * @@ -141,7 +141,7 @@ public function getTarget() } /** - * Get Link source + * Get Link source. * * @deprecated 0.10.0 * @@ -155,7 +155,7 @@ public function getLinkSrc() } /** - * Get Link name + * Get Link name. * * @deprecated 0.10.0 * @@ -169,7 +169,7 @@ public function getLinkName() } /** - * is internal + * is internal. * * @return bool */ diff --git a/src/PhpWord/Element/ListItem.php b/src/PhpWord/Element/ListItem.php index 40381de0d9..36484d90f9 100644 --- a/src/PhpWord/Element/ListItem.php +++ b/src/PhpWord/Element/ListItem.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,38 +21,38 @@ use PhpOffice\PhpWord\Style\ListItem as ListItemStyle; /** - * List item element + * List item element. */ class ListItem extends AbstractElement { /** - * Element style + * Element style. * * @var \PhpOffice\PhpWord\Style\ListItem */ private $style; /** - * Text object + * Text object. * * @var \PhpOffice\PhpWord\Element\Text */ private $textObject; /** - * Depth + * Depth. * * @var int */ private $depth; /** - * Create a new ListItem + * Create a new ListItem. * * @param string $text * @param int $depth * @param mixed $fontStyle - * @param array|string|null $listStyle + * @param null|array|string $listStyle * @param mixed $paragraphStyle */ public function __construct($text, $depth = 0, $fontStyle = null, $listStyle = null, $paragraphStyle = null) @@ -61,7 +61,7 @@ public function __construct($text, $depth = 0, $fontStyle = null, $listStyle = n $this->depth = $depth; // Version >= 0.10.0 will pass numbering style name. Older version will use old method - if (!is_null($listStyle) && is_string($listStyle)) { + if (null !== $listStyle && is_string($listStyle)) { $this->style = new ListItemStyle($listStyle); // @codeCoverageIgnore } else { $this->style = $this->setNewStyle(new ListItemStyle(), $listStyle, true); @@ -69,7 +69,7 @@ public function __construct($text, $depth = 0, $fontStyle = null, $listStyle = n } /** - * Get style + * Get style. * * @return \PhpOffice\PhpWord\Style\ListItem */ @@ -79,7 +79,7 @@ public function getStyle() } /** - * Get Text object + * Get Text object. * * @return \PhpOffice\PhpWord\Element\Text */ @@ -89,7 +89,7 @@ public function getTextObject() } /** - * Get depth + * Get depth. * * @return int */ @@ -99,9 +99,10 @@ public function getDepth() } /** - * Get text + * Get text. * * @return string + * * @since 0.11.0 */ public function getText() diff --git a/src/PhpWord/Element/ListItemRun.php b/src/PhpWord/Element/ListItemRun.php index 6e48a69012..69274a520c 100644 --- a/src/PhpWord/Element/ListItemRun.php +++ b/src/PhpWord/Element/ListItemRun.php @@ -1,26 +1,26 @@ depth = $depth; // Version >= 0.10.0 will pass numbering style name. Older version will use old method - if (!is_null($listStyle) && is_string($listStyle)) { + if (null !== $listStyle && is_string($listStyle)) { $this->style = new ListItemStyle($listStyle); } else { $this->style = $this->setNewStyle(new ListItemStyle(), $listStyle, true); diff --git a/src/PhpWord/Element/OLEObject.php b/src/PhpWord/Element/OLEObject.php index 1a17b74753..00092ea869 100644 --- a/src/PhpWord/Element/OLEObject.php +++ b/src/PhpWord/Element/OLEObject.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,56 +21,54 @@ use PhpOffice\PhpWord\Style\Image as ImageStyle; /** - * OLEObject element + * OLEObject element. */ class OLEObject extends AbstractElement { /** - * Ole-Object Src + * Ole-Object Src. * * @var string */ private $source; /** - * Image Style + * Image Style. * * @var \PhpOffice\PhpWord\Style\Image */ private $style; /** - * Icon + * Icon. * * @var string */ private $icon; /** - * Image Relation ID + * Image Relation ID. * * @var int */ private $imageRelationId; /** - * Has media relation flag; true for Link, Image, and Object + * Has media relation flag; true for Link, Image, and Object. * * @var bool */ protected $mediaRelation = true; /** - * Create a new Ole-Object Element + * Create a new Ole-Object Element. * * @param string $source * @param mixed $style - * - * @throws \PhpOffice\PhpWord\Exception\InvalidObjectException */ public function __construct($source, $style = null) { - $supportedTypes = array('xls', 'doc', 'ppt', 'xlsx', 'docx', 'pptx'); + $supportedTypes = ['xls', 'doc', 'ppt', 'xlsx', 'docx', 'pptx']; $pathInfo = pathinfo($source); if (file_exists($source) && in_array($pathInfo['extension'], $supportedTypes)) { @@ -90,7 +88,7 @@ public function __construct($source, $style = null) } /** - * Get object source + * Get object source. * * @return string */ @@ -100,7 +98,7 @@ public function getSource() } /** - * Get object style + * Get object style. * * @return \PhpOffice\PhpWord\Style\Image */ @@ -110,7 +108,7 @@ public function getStyle() } /** - * Get object icon + * Get object icon. * * @return string */ @@ -120,7 +118,7 @@ public function getIcon() } /** - * Get image relation ID + * Get image relation ID. * * @return int */ @@ -134,13 +132,13 @@ public function getImageRelationId() * * @param int $rId */ - public function setImageRelationId($rId) + public function setImageRelationId($rId): void { $this->imageRelationId = $rId; } /** - * Get Object ID + * Get Object ID. * * @deprecated 0.10.0 * @@ -154,7 +152,7 @@ public function getObjectId() } /** - * Set Object ID + * Set Object ID. * * @deprecated 0.10.0 * @@ -162,7 +160,7 @@ public function getObjectId() * * @codeCoverageIgnore */ - public function setObjectId($objId) + public function setObjectId($objId): void { $this->relationId = $objId; } diff --git a/src/PhpWord/Element/PageBreak.php b/src/PhpWord/Element/PageBreak.php index 1e2ada80ad..02f5989f1d 100644 --- a/src/PhpWord/Element/PageBreak.php +++ b/src/PhpWord/Element/PageBreak.php @@ -11,19 +11,19 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Element; /** - * Page break element + * Page break element. */ class PageBreak extends AbstractElement { /** - * Create new page break + * Create new page break. */ public function __construct() { diff --git a/src/PhpWord/Element/PreserveText.php b/src/PhpWord/Element/PreserveText.php index a6210bab8a..19f468bb41 100644 --- a/src/PhpWord/Element/PreserveText.php +++ b/src/PhpWord/Element/PreserveText.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -22,33 +22,33 @@ use PhpOffice\PhpWord\Style\Paragraph; /** - * Preserve text/field element + * Preserve text/field element. */ class PreserveText extends AbstractElement { /** - * Text content + * Text content. * - * @var string|array + * @var array|string */ private $text; /** - * Text style + * Text style. * - * @var string|\PhpOffice\PhpWord\Style\Font + * @var \PhpOffice\PhpWord\Style\Font|string */ private $fontStyle; /** - * Paragraph style + * Paragraph style. * - * @var string|\PhpOffice\PhpWord\Style\Paragraph + * @var \PhpOffice\PhpWord\Style\Paragraph|string */ private $paragraphStyle; /** - * Create a new Preserve Text Element + * Create a new Preserve Text Element. * * @param string $text * @param mixed $fontStyle @@ -67,9 +67,9 @@ public function __construct($text = null, $fontStyle = null, $paragraphStyle = n } /** - * Get Text style + * Get Text style. * - * @return string|\PhpOffice\PhpWord\Style\Font + * @return \PhpOffice\PhpWord\Style\Font|string */ public function getFontStyle() { @@ -77,9 +77,9 @@ public function getFontStyle() } /** - * Get Paragraph style + * Get Paragraph style. * - * @return string|\PhpOffice\PhpWord\Style\Paragraph + * @return \PhpOffice\PhpWord\Style\Paragraph|string */ public function getParagraphStyle() { @@ -87,9 +87,9 @@ public function getParagraphStyle() } /** - * Get Text content + * Get Text content. * - * @return string|array + * @return array|string */ public function getText() { diff --git a/src/PhpWord/Element/Row.php b/src/PhpWord/Element/Row.php index da4dfe5d73..d2f0ecac89 100644 --- a/src/PhpWord/Element/Row.php +++ b/src/PhpWord/Element/Row.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,35 +20,35 @@ use PhpOffice\PhpWord\Style\Row as RowStyle; /** - * Table row element + * Table row element. * * @since 0.8.0 */ class Row extends AbstractElement { /** - * Row height + * Row height. * * @var int */ - private $height = null; + private $height; /** - * Row style + * Row style. * * @var \PhpOffice\PhpWord\Style\Row */ private $style; /** - * Row cells + * Row cells. * * @var \PhpOffice\PhpWord\Element\Cell[] */ - private $cells = array(); + private $cells = []; /** - * Create a new table row + * Create a new table row. * * @param int $height * @param mixed $style @@ -60,10 +60,11 @@ public function __construct($height = null, $style = null) } /** - * Add a cell + * Add a cell. * * @param int $width * @param mixed $style + * * @return \PhpOffice\PhpWord\Element\Cell */ public function addCell($width = null, $style = null) @@ -76,7 +77,7 @@ public function addCell($width = null, $style = null) } /** - * Get all cells + * Get all cells. * * @return \PhpOffice\PhpWord\Element\Cell[] */ @@ -86,7 +87,7 @@ public function getCells() } /** - * Get row style + * Get row style. * * @return \PhpOffice\PhpWord\Style\Row */ @@ -96,7 +97,7 @@ public function getStyle() } /** - * Get row height + * Get row height. * * @return int */ diff --git a/src/PhpWord/Element/SDT.php b/src/PhpWord/Element/SDT.php index 5548f768c7..b7ff31ec21 100644 --- a/src/PhpWord/Element/SDT.php +++ b/src/PhpWord/Element/SDT.php @@ -11,56 +11,56 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Element; /** - * Structured document tag (SDT) element + * Structured document tag (SDT) element. * * @since 0.12.0 */ class SDT extends Text { /** - * Form field type: comboBox|dropDownList|date + * Form field type: comboBox|dropDownList|date. * * @var string */ private $type; /** - * Value + * Value. * - * @var string|bool|int + * @var bool|int|string */ private $value; /** - * CheckBox/DropDown list entries + * CheckBox/DropDown list entries. * * @var array */ - private $listItems = array(); + private $listItems = []; /** - * Alias + * Alias. * * @var string */ private $alias; /** - * Tag + * Tag. * * @var string */ private $tag; /** - * Create new instance + * Create new instance. * * @param string $type * @param mixed $fontStyle @@ -73,7 +73,7 @@ public function __construct($type, $fontStyle = null, $paragraphStyle = null) } /** - * Get type + * Get type. * * @return string */ @@ -83,23 +83,24 @@ public function getType() } /** - * Set type + * Set type. * * @param string $value + * * @return self */ public function setType($value) { - $enum = array('plainText', 'comboBox', 'dropDownList', 'date'); + $enum = ['plainText', 'comboBox', 'dropDownList', 'date']; $this->type = $this->setEnumVal($value, $enum, 'comboBox'); return $this; } /** - * Get value + * Get value. * - * @return string|bool|int + * @return bool|int|string */ public function getValue() { @@ -107,9 +108,10 @@ public function getValue() } /** - * Set value + * Set value. + * + * @param bool|int|string $value * - * @param string|bool|int $value * @return self */ public function setValue($value) @@ -120,7 +122,7 @@ public function setValue($value) } /** - * Get listItems + * Get listItems. * * @return array */ @@ -130,9 +132,10 @@ public function getListItems() } /** - * Set listItems + * Set listItems. * * @param array $value + * * @return self */ public function setListItems($value) @@ -143,7 +146,7 @@ public function setListItems($value) } /** - * Get tag + * Get tag. * * @return string */ @@ -153,9 +156,10 @@ public function getTag() } /** - * Set tag + * Set tag. * * @param string $tag + * * @return self */ public function setTag($tag) @@ -166,7 +170,7 @@ public function setTag($tag) } /** - * Get alias + * Get alias. * * @return string */ @@ -176,9 +180,10 @@ public function getAlias() } /** - * Set alias + * Set alias. * * @param string $alias + * * @return self */ public function setAlias($alias) diff --git a/src/PhpWord/Element/Section.php b/src/PhpWord/Element/Section.php index caf2ca2738..e9710b8e6e 100644 --- a/src/PhpWord/Element/Section.php +++ b/src/PhpWord/Element/Section.php @@ -11,12 +11,13 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Element; +use Exception; use PhpOffice\PhpWord\ComplexType\FootnoteProperties; use PhpOffice\PhpWord\Style\Section as SectionStyle; @@ -28,35 +29,35 @@ class Section extends AbstractContainer protected $container = 'Section'; /** - * Section style + * Section style. * * @var \PhpOffice\PhpWord\Style\Section */ private $style; /** - * Section headers, indexed from 1, not zero + * Section headers, indexed from 1, not zero. * * @var Header[] */ - private $headers = array(); + private $headers = []; /** - * Section footers, indexed from 1, not zero + * Section footers, indexed from 1, not zero. * * @var Footer[] */ - private $footers = array(); + private $footers = []; /** - * The properties for the footnote of this section + * The properties for the footnote of this section. * * @var FootnoteProperties */ private $footnoteProperties; /** - * Create new instance + * Create new instance. * * @param int $sectionCount * @param null|array|\PhpOffice\PhpWord\Style $style @@ -76,15 +77,15 @@ public function __construct($sectionCount, $style = null) * * @param array $style */ - public function setStyle($style = null) + public function setStyle($style = null): void { - if (!is_null($style) && is_array($style)) { + if (null !== $style && is_array($style)) { $this->style->setStyleByArray($style); } } /** - * Get section style + * Get section style. * * @return \PhpOffice\PhpWord\Style\Section */ @@ -94,7 +95,7 @@ public function getStyle() } /** - * Add header + * Add header. * * @since 0.10.0 * @@ -108,7 +109,7 @@ public function addHeader($type = Header::AUTO) } /** - * Add footer + * Add footer. * * @since 0.10.0 * @@ -122,7 +123,7 @@ public function addFooter($type = Header::AUTO) } /** - * Get header elements + * Get header elements. * * @return Header[] */ @@ -132,7 +133,7 @@ public function getHeaders() } /** - * Get footer elements + * Get footer elements. * * @return Footer[] */ @@ -142,7 +143,7 @@ public function getFooters() } /** - * Get the footnote properties + * Get the footnote properties. * * @return FootnoteProperties */ @@ -152,7 +153,7 @@ public function getFootnoteProperties() } /** - * Get the footnote properties + * Get the footnote properties. * * @deprecated Use the `getFootnoteProperties` method instead * @@ -166,11 +167,11 @@ public function getFootnotePropoperties() } /** - * Set the footnote properties + * Set the footnote properties. * * @param FootnoteProperties $footnoteProperties */ - public function setFootnoteProperties(FootnoteProperties $footnoteProperties = null) + public function setFootnoteProperties(?FootnoteProperties $footnoteProperties = null): void { $this->footnoteProperties = $footnoteProperties; } @@ -200,25 +201,23 @@ public function hasDifferentFirstPage() } /** - * Add header/footer + * Add header/footer. * * @since 0.10.0 * * @param string $type * @param bool $header * - * @throws \Exception - * - * @return Header|Footer + * @return Footer|Header */ private function addHeaderFooter($type = Header::AUTO, $header = true) { - $containerClass = substr(get_class($this), 0, strrpos(get_class($this), '\\')) . '\\' . + $containerClass = substr(static::class, 0, strrpos(static::class, '\\')) . '\\' . ($header ? 'Header' : 'Footer'); $collectionArray = $header ? 'headers' : 'footers'; $collection = &$this->$collectionArray; - if (in_array($type, array(Header::AUTO, Header::FIRST, Header::EVEN))) { + if (in_array($type, [Header::AUTO, Header::FIRST, Header::EVEN])) { $index = count($collection); /** @var \PhpOffice\PhpWord\Element\AbstractContainer $container Type hint */ $container = new $containerClass($this->sectionId, ++$index, $type); @@ -228,11 +227,12 @@ private function addHeaderFooter($type = Header::AUTO, $header = true) return $container; } - throw new \Exception('Invalid header/footer type.'); + + throw new Exception('Invalid header/footer type.'); } /** - * Set section style + * Set section style. * * @deprecated 0.12.0 * @@ -240,13 +240,13 @@ private function addHeaderFooter($type = Header::AUTO, $header = true) * * @codeCoverageIgnore */ - public function setSettings($settings = null) + public function setSettings($settings = null): void { $this->setStyle($settings); } /** - * Get section style + * Get section style. * * @deprecated 0.12.0 * @@ -260,7 +260,7 @@ public function getSettings() } /** - * Create header + * Create header. * * @deprecated 0.10.0 * @@ -274,7 +274,7 @@ public function createHeader() } /** - * Create footer + * Create footer. * * @deprecated 0.10.0 * @@ -288,7 +288,7 @@ public function createFooter() } /** - * Get footer + * Get footer. * * @deprecated 0.10.0 * diff --git a/src/PhpWord/Element/Shape.php b/src/PhpWord/Element/Shape.php index d143c9b694..930ed8a95d 100644 --- a/src/PhpWord/Element/Shape.php +++ b/src/PhpWord/Element/Shape.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,28 +20,28 @@ use PhpOffice\PhpWord\Style\Shape as ShapeStyle; /** - * Shape element + * Shape element. * * @since 0.12.0 */ class Shape extends AbstractElement { /** - * Shape type arc|curve|line|polyline|rect|oval + * Shape type arc|curve|line|polyline|rect|oval. * * @var string */ private $type; /** - * Shape style + * Shape style. * * @var \PhpOffice\PhpWord\Style\Shape */ private $style; /** - * Create new instance + * Create new instance. * * @param string $type * @param mixed $style @@ -53,7 +53,7 @@ public function __construct($type, $style = null) } /** - * Get type + * Get type. * * @return string */ @@ -63,21 +63,22 @@ public function getType() } /** - * Set pattern + * Set pattern. * * @param string $value + * * @return self */ public function setType($value = null) { - $enum = array('arc', 'curve', 'line', 'polyline', 'rect', 'oval'); + $enum = ['arc', 'curve', 'line', 'polyline', 'rect', 'oval']; $this->type = $this->setEnumVal($value, $enum, null); return $this; } /** - * Get shape style + * Get shape style. * * @return \PhpOffice\PhpWord\Style\Shape */ diff --git a/src/PhpWord/Element/TOC.php b/src/PhpWord/Element/TOC.php index c51d0e6be3..0fbae57e6a 100644 --- a/src/PhpWord/Element/TOC.php +++ b/src/PhpWord/Element/TOC.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -22,40 +22,40 @@ use PhpOffice\PhpWord\Style\TOC as TOCStyle; /** - * Table of contents + * Table of contents. */ class TOC extends AbstractElement { /** - * TOC style + * TOC style. * * @var \PhpOffice\PhpWord\Style\TOC */ private $TOCStyle; /** - * Font style + * Font style. * * @var \PhpOffice\PhpWord\Style\Font|string */ private $fontStyle; /** - * Min title depth to show + * Min title depth to show. * * @var int */ private $minDepth = 1; /** - * Max title depth to show + * Max title depth to show. * * @var int */ private $maxDepth = 9; /** - * Create a new Table-of-Contents Element + * Create a new Table-of-Contents Element. * * @param mixed $fontStyle * @param array $tocStyle @@ -66,11 +66,11 @@ public function __construct($fontStyle = null, $tocStyle = null, $minDepth = 1, { $this->TOCStyle = new TOCStyle(); - if (!is_null($tocStyle) && is_array($tocStyle)) { + if (null !== $tocStyle && is_array($tocStyle)) { $this->TOCStyle->setStyleByArray($tocStyle); } - if (!is_null($fontStyle) && is_array($fontStyle)) { + if (null !== $fontStyle && is_array($fontStyle)) { $this->fontStyle = new Font(); $this->fontStyle->setStyleByArray($fontStyle); } else { @@ -82,14 +82,14 @@ public function __construct($fontStyle = null, $tocStyle = null, $minDepth = 1, } /** - * Get all titles + * Get all titles. * * @return array */ public function getTitles() { if (!$this->phpWord instanceof PhpWord) { - return array(); + return []; } $titles = $this->phpWord->getTitles()->getItems(); @@ -108,7 +108,7 @@ public function getTitles() } /** - * Get TOC Style + * Get TOC Style. * * @return \PhpOffice\PhpWord\Style\TOC */ @@ -118,7 +118,7 @@ public function getStyleTOC() } /** - * Get Font Style + * Get Font Style. * * @return \PhpOffice\PhpWord\Style\Font|string */ @@ -132,13 +132,13 @@ public function getStyleFont() * * @param int $value */ - public function setMaxDepth($value) + public function setMaxDepth($value): void { $this->maxDepth = $value; } /** - * Get Max Depth + * Get Max Depth. * * @return int Max depth of titles */ @@ -152,13 +152,13 @@ public function getMaxDepth() * * @param int $value */ - public function setMinDepth($value) + public function setMinDepth($value): void { $this->minDepth = $value; } /** - * Get Min Depth + * Get Min Depth. * * @return int Min depth of titles */ diff --git a/src/PhpWord/Element/Table.php b/src/PhpWord/Element/Table.php index 44fe3744bd..308e7bc63e 100644 --- a/src/PhpWord/Element/Table.php +++ b/src/PhpWord/Element/Table.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,33 +20,33 @@ use PhpOffice\PhpWord\Style\Table as TableStyle; /** - * Table element + * Table element. */ class Table extends AbstractElement { /** - * Table style + * Table style. * * @var \PhpOffice\PhpWord\Style\Table */ private $style; /** - * Table rows + * Table rows. * * @var \PhpOffice\PhpWord\Element\Row[] */ - private $rows = array(); + private $rows = []; /** - * Table width + * Table width. * * @var int */ - private $width = null; + private $width; /** - * Create a new table + * Create a new table. * * @param mixed $style */ @@ -56,10 +56,11 @@ public function __construct($style = null) } /** - * Add a row + * Add a row. * * @param int $height * @param mixed $style + * * @return \PhpOffice\PhpWord\Element\Row */ public function addRow($height = null, $style = null) @@ -72,10 +73,11 @@ public function addRow($height = null, $style = null) } /** - * Add a cell + * Add a cell. * * @param int $width * @param mixed $style + * * @return \PhpOffice\PhpWord\Element\Cell */ public function addCell($width = null, $style = null) @@ -88,7 +90,7 @@ public function addCell($width = null, $style = null) } /** - * Get all rows + * Get all rows. * * @return \PhpOffice\PhpWord\Element\Row[] */ @@ -98,7 +100,7 @@ public function getRows() } /** - * Get table style + * Get table style. * * @return \PhpOffice\PhpWord\Style\Table */ @@ -108,7 +110,7 @@ public function getStyle() } /** - * Get table width + * Get table width. * * @return int */ @@ -122,13 +124,13 @@ public function getWidth() * * @param int $width */ - public function setWidth($width) + public function setWidth($width): void { $this->width = $width; } /** - * Get column count + * Get column count. * * @return int */ @@ -137,7 +139,7 @@ public function countColumns() $columnCount = 0; $rowCount = count($this->rows); - for ($i = 0; $i < $rowCount; $i++) { + for ($i = 0; $i < $rowCount; ++$i) { /** @var \PhpOffice\PhpWord\Element\Row $row Type hint */ $row = $this->rows[$i]; $cellCount = count($row->getCells()); @@ -150,20 +152,20 @@ public function countColumns() } /** - * The first declared cell width for each column + * The first declared cell width for each column. * * @return int[] */ public function findFirstDefinedCellWidths() { - $cellWidths = array(); + $cellWidths = []; foreach ($this->rows as $row) { $cells = $row->getCells(); if (count($cells) <= count($cellWidths)) { continue; } - $cellWidths = array(); + $cellWidths = []; foreach ($cells as $cell) { $cellWidths[] = $cell->getWidth(); } diff --git a/src/PhpWord/Element/Text.php b/src/PhpWord/Element/Text.php index 1ad497b08d..6a11e82f75 100644 --- a/src/PhpWord/Element/Text.php +++ b/src/PhpWord/Element/Text.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -22,33 +22,33 @@ use PhpOffice\PhpWord\Style\Paragraph; /** - * Text element + * Text element. */ class Text extends AbstractElement { /** - * Text content + * Text content. * * @var string */ protected $text; /** - * Text style + * Text style. * - * @var string|\PhpOffice\PhpWord\Style\Font + * @var \PhpOffice\PhpWord\Style\Font|string */ protected $fontStyle; /** - * Paragraph style + * Paragraph style. * - * @var string|\PhpOffice\PhpWord\Style\Paragraph + * @var \PhpOffice\PhpWord\Style\Paragraph|string */ protected $paragraphStyle; /** - * Create a new Text Element + * Create a new Text Element. * * @param string $text * @param mixed $fontStyle @@ -62,11 +62,12 @@ public function __construct($text = null, $fontStyle = null, $paragraphStyle = n } /** - * Set Text style + * Set Text style. + * + * @param array|\PhpOffice\PhpWord\Style\Font|string $style + * @param array|\PhpOffice\PhpWord\Style\Paragraph|string $paragraphStyle * - * @param string|array|\PhpOffice\PhpWord\Style\Font $style - * @param string|array|\PhpOffice\PhpWord\Style\Paragraph $paragraphStyle - * @return string|\PhpOffice\PhpWord\Style\Font + * @return \PhpOffice\PhpWord\Style\Font|string */ public function setFontStyle($style = null, $paragraphStyle = null) { @@ -87,9 +88,9 @@ public function setFontStyle($style = null, $paragraphStyle = null) } /** - * Get Text style + * Get Text style. * - * @return string|\PhpOffice\PhpWord\Style\Font + * @return \PhpOffice\PhpWord\Style\Font|string */ public function getFontStyle() { @@ -97,10 +98,11 @@ public function getFontStyle() } /** - * Set Paragraph style + * Set Paragraph style. * - * @param string|array|\PhpOffice\PhpWord\Style\Paragraph $style - * @return string|\PhpOffice\PhpWord\Style\Paragraph + * @param array|\PhpOffice\PhpWord\Style\Paragraph|string $style + * + * @return \PhpOffice\PhpWord\Style\Paragraph|string */ public function setParagraphStyle($style = null) { @@ -119,9 +121,9 @@ public function setParagraphStyle($style = null) } /** - * Get Paragraph style + * Get Paragraph style. * - * @return string|\PhpOffice\PhpWord\Style\Paragraph + * @return \PhpOffice\PhpWord\Style\Paragraph|string */ public function getParagraphStyle() { @@ -129,9 +131,10 @@ public function getParagraphStyle() } /** - * Set text content + * Set text content. * * @param string $text + * * @return self */ public function setText($text) @@ -142,7 +145,7 @@ public function setText($text) } /** - * Get Text content + * Get Text content. * * @return string */ diff --git a/src/PhpWord/Element/TextBox.php b/src/PhpWord/Element/TextBox.php index b9f274d6b8..7472f4bc34 100644 --- a/src/PhpWord/Element/TextBox.php +++ b/src/PhpWord/Element/TextBox.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,7 +20,7 @@ use PhpOffice\PhpWord\Style\TextBox as TextBoxStyle; /** - * TextBox element + * TextBox element. * * @since 0.11.0 */ @@ -32,14 +32,14 @@ class TextBox extends AbstractContainer protected $container = 'TextBox'; /** - * TextBox style + * TextBox style. * * @var \PhpOffice\PhpWord\Style\TextBox */ private $style; /** - * Create a new textbox + * Create a new textbox. * * @param mixed $style */ @@ -49,7 +49,7 @@ public function __construct($style = null) } /** - * Get textbox style + * Get textbox style. * * @return \PhpOffice\PhpWord\Style\TextBox */ diff --git a/src/PhpWord/Element/TextBreak.php b/src/PhpWord/Element/TextBreak.php index 385fec5a84..088503a40e 100644 --- a/src/PhpWord/Element/TextBreak.php +++ b/src/PhpWord/Element/TextBreak.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,46 +21,47 @@ use PhpOffice\PhpWord\Style\Paragraph; /** - * Text break element + * Text break element. */ class TextBreak extends AbstractElement { /** - * Paragraph style + * Paragraph style. * - * @var string|\PhpOffice\PhpWord\Style\Paragraph + * @var \PhpOffice\PhpWord\Style\Paragraph|string */ - private $paragraphStyle = null; + private $paragraphStyle; /** - * Text style + * Text style. * - * @var string|\PhpOffice\PhpWord\Style\Font + * @var \PhpOffice\PhpWord\Style\Font|string */ - private $fontStyle = null; + private $fontStyle; /** - * Create a new TextBreak Element + * Create a new TextBreak Element. * * @param mixed $fontStyle * @param mixed $paragraphStyle */ public function __construct($fontStyle = null, $paragraphStyle = null) { - if (!is_null($paragraphStyle)) { + if (null !== $paragraphStyle) { $paragraphStyle = $this->setParagraphStyle($paragraphStyle); } - if (!is_null($fontStyle)) { + if (null !== $fontStyle) { $this->setFontStyle($fontStyle, $paragraphStyle); } } /** - * Set Text style + * Set Text style. * * @param mixed $style * @param mixed $paragraphStyle - * @return string|\PhpOffice\PhpWord\Style\Font + * + * @return \PhpOffice\PhpWord\Style\Font|string */ public function setFontStyle($style = null, $paragraphStyle = null) { @@ -79,9 +80,9 @@ public function setFontStyle($style = null, $paragraphStyle = null) } /** - * Get Text style + * Get Text style. * - * @return string|\PhpOffice\PhpWord\Style\Font + * @return \PhpOffice\PhpWord\Style\Font|string */ public function getFontStyle() { @@ -89,10 +90,11 @@ public function getFontStyle() } /** - * Set Paragraph style + * Set Paragraph style. + * + * @param array|\PhpOffice\PhpWord\Style\Paragraph|string $style * - * @param string|array|\PhpOffice\PhpWord\Style\Paragraph $style - * @return string|\PhpOffice\PhpWord\Style\Paragraph + * @return \PhpOffice\PhpWord\Style\Paragraph|string */ public function setParagraphStyle($style = null) { @@ -109,9 +111,9 @@ public function setParagraphStyle($style = null) } /** - * Get Paragraph style + * Get Paragraph style. * - * @return string|\PhpOffice\PhpWord\Style\Paragraph + * @return \PhpOffice\PhpWord\Style\Paragraph|string */ public function getParagraphStyle() { @@ -119,12 +121,12 @@ public function getParagraphStyle() } /** - * Has font/paragraph style defined + * Has font/paragraph style defined. * * @return bool */ public function hasStyle() { - return !is_null($this->fontStyle) || !is_null($this->paragraphStyle); + return null !== $this->fontStyle || null !== $this->paragraphStyle; } } diff --git a/src/PhpWord/Element/TextRun.php b/src/PhpWord/Element/TextRun.php index 9af55d4687..fc8727592a 100644 --- a/src/PhpWord/Element/TextRun.php +++ b/src/PhpWord/Element/TextRun.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,7 +20,7 @@ use PhpOffice\PhpWord\Style\Paragraph; /** - * Textrun/paragraph element + * Textrun/paragraph element. */ class TextRun extends AbstractContainer { @@ -30,16 +30,16 @@ class TextRun extends AbstractContainer protected $container = 'TextRun'; /** - * Paragraph style + * Paragraph style. * - * @var string|\PhpOffice\PhpWord\Style\Paragraph + * @var \PhpOffice\PhpWord\Style\Paragraph|string */ protected $paragraphStyle; /** - * Create new instance + * Create new instance. * - * @param string|array|\PhpOffice\PhpWord\Style\Paragraph $paragraphStyle + * @param array|\PhpOffice\PhpWord\Style\Paragraph|string $paragraphStyle */ public function __construct($paragraphStyle = null) { @@ -47,9 +47,9 @@ public function __construct($paragraphStyle = null) } /** - * Get Paragraph style + * Get Paragraph style. * - * @return string|\PhpOffice\PhpWord\Style\Paragraph + * @return \PhpOffice\PhpWord\Style\Paragraph|string */ public function getParagraphStyle() { @@ -57,10 +57,11 @@ public function getParagraphStyle() } /** - * Set Paragraph style + * Set Paragraph style. + * + * @param array|\PhpOffice\PhpWord\Style\Paragraph|string $style * - * @param string|array|\PhpOffice\PhpWord\Style\Paragraph $style - * @return string|\PhpOffice\PhpWord\Style\Paragraph + * @return \PhpOffice\PhpWord\Style\Paragraph|string */ public function setParagraphStyle($style = null) { diff --git a/src/PhpWord/Element/Title.php b/src/PhpWord/Element/Title.php index f061b3d568..947e941696 100644 --- a/src/PhpWord/Element/Title.php +++ b/src/PhpWord/Element/Title.php @@ -11,50 +11,51 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Element; +use InvalidArgumentException; use PhpOffice\PhpWord\Shared\Text as SharedText; use PhpOffice\PhpWord\Style; /** - * Title element + * Title element. */ class Title extends AbstractElement { /** - * Title Text content + * Title Text content. * * @var string|TextRun */ private $text; /** - * Title depth + * Title depth. * * @var int */ private $depth = 1; /** - * Name of the heading style, e.g. 'Heading1' + * Name of the heading style, e.g. 'Heading1'. * * @var string */ private $style; /** - * Is part of collection + * Is part of collection. * * @var bool */ protected $collectionRelation = true; /** - * Create a new Title Element + * Create a new Title Element. * * @param string|TextRun $text * @param int $depth @@ -66,7 +67,7 @@ public function __construct($text, $depth = 1) } elseif ($text instanceof TextRun) { $this->text = $text; } else { - throw new \InvalidArgumentException('Invalid text, should be a string or a TextRun'); + throw new InvalidArgumentException('Invalid text, should be a string or a TextRun'); } $this->depth = $depth; @@ -77,7 +78,7 @@ public function __construct($text, $depth = 1) } /** - * Get Title Text content + * Get Title Text content. * * @return string */ @@ -87,7 +88,7 @@ public function getText() } /** - * Get depth + * Get depth. * * @return int */ @@ -97,7 +98,7 @@ public function getDepth() } /** - * Get Title style + * Get Title style. * * @return string */ diff --git a/src/PhpWord/Element/TrackChange.php b/src/PhpWord/Element/TrackChange.php index 91c221f2a8..064e6380b7 100644 --- a/src/PhpWord/Element/TrackChange.php +++ b/src/PhpWord/Element/TrackChange.php @@ -11,14 +11,17 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Element; +use DateTime; + /** - * TrackChange element + * TrackChange element. + * * @see http://datypic.com/sc/ooxml/t-w_CT_TrackChange.html * @see http://datypic.com/sc/ooxml/t-w_CT_RunTrackChange.html */ @@ -33,44 +36,44 @@ class TrackChange extends AbstractContainer protected $container = 'TrackChange'; /** - * The type of change, (insert or delete), not applicable for PhpOffice\PhpWord\Element\Comment + * The type of change, (insert or delete), not applicable for PhpOffice\PhpWord\Element\Comment. * * @var string */ private $changeType; /** - * Author + * Author. * * @var string */ private $author; /** - * Date + * Date. * - * @var \DateTime + * @var DateTime */ private $date; /** - * Create a new TrackChange Element + * Create a new TrackChange Element. * * @param string $changeType * @param string $author - * @param null|int|bool|\DateTime $date + * @param null|bool|DateTime|int $date */ public function __construct($changeType = null, $author = null, $date = null) { $this->changeType = $changeType; $this->author = $author; if ($date !== null && $date !== false) { - $this->date = ($date instanceof \DateTime) ? $date : new \DateTime('@' . $date); + $this->date = ($date instanceof DateTime) ? $date : new DateTime('@' . $date); } } /** - * Get TrackChange Author + * Get TrackChange Author. * * @return string */ @@ -80,9 +83,9 @@ public function getAuthor() } /** - * Get TrackChange Date + * Get TrackChange Date. * - * @return \DateTime + * @return DateTime */ public function getDate() { @@ -90,7 +93,7 @@ public function getDate() } /** - * Get the Change type + * Get the Change type. * * @return string */ diff --git a/src/PhpWord/Escaper/AbstractEscaper.php b/src/PhpWord/Escaper/AbstractEscaper.php index 1575c069e2..571d5df92e 100644 --- a/src/PhpWord/Escaper/AbstractEscaper.php +++ b/src/PhpWord/Escaper/AbstractEscaper.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Escaper/EscaperInterface.php b/src/PhpWord/Escaper/EscaperInterface.php index deb2cfbc0e..ac68058ed2 100644 --- a/src/PhpWord/Escaper/EscaperInterface.php +++ b/src/PhpWord/Escaper/EscaperInterface.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Escaper/RegExp.php b/src/PhpWord/Escaper/RegExp.php index f69aad8217..84f6faee99 100644 --- a/src/PhpWord/Escaper/RegExp.php +++ b/src/PhpWord/Escaper/RegExp.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Escaper/Rtf.php b/src/PhpWord/Escaper/Rtf.php index 42eb22a777..b627bcd11e 100644 --- a/src/PhpWord/Escaper/Rtf.php +++ b/src/PhpWord/Escaper/Rtf.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -46,6 +46,7 @@ protected function escapeMultibyteCharacter($code) /** * @see http://www.randomchaos.com/documents/?source=php_and_unicode + * * @param string $input */ protected function escapeSingleValue($input) @@ -53,7 +54,7 @@ protected function escapeSingleValue($input) $escapedValue = ''; $numberOfBytes = 1; - $bytes = array(); + $bytes = []; for ($i = 0; $i < strlen($input); ++$i) { $character = $input[$i]; $asciiCode = ord($character); @@ -87,7 +88,7 @@ protected function escapeSingleValue($input) } $numberOfBytes = 1; - $bytes = array(); + $bytes = []; } } } diff --git a/src/PhpWord/Escaper/Xml.php b/src/PhpWord/Escaper/Xml.php index 16ce2340cd..446ea771d0 100644 --- a/src/PhpWord/Escaper/Xml.php +++ b/src/PhpWord/Escaper/Xml.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -26,6 +26,6 @@ class Xml extends AbstractEscaper { protected function escapeSingleValue($input) { - return (!is_null($input)) ? htmlspecialchars($input, ENT_QUOTES) : ''; + return (null !== $input) ? htmlspecialchars($input, ENT_QUOTES) : ''; } } diff --git a/src/PhpWord/Exception/CopyFileException.php b/src/PhpWord/Exception/CopyFileException.php index d1c3bd0123..2ee8187165 100644 --- a/src/PhpWord/Exception/CopyFileException.php +++ b/src/PhpWord/Exception/CopyFileException.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -28,7 +28,7 @@ final class CopyFileException extends Exception * @param int $code The user defined exception code * @param \Exception $previous The previous exception used for the exception chaining */ - final public function __construct($source, $destination, $code = 0, \Exception $previous = null) + public function __construct($source, $destination, $code = 0, ?\Exception $previous = null) { parent::__construct( sprintf('Could not copy \'%s\' file to \'%s\'.', $source, $destination), diff --git a/src/PhpWord/Exception/CreateTemporaryFileException.php b/src/PhpWord/Exception/CreateTemporaryFileException.php index c8a06429d8..7be01d6750 100644 --- a/src/PhpWord/Exception/CreateTemporaryFileException.php +++ b/src/PhpWord/Exception/CreateTemporaryFileException.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -26,7 +26,7 @@ final class CreateTemporaryFileException extends Exception * @param int $code The user defined exception code * @param \Exception $previous The previous exception used for the exception chaining */ - final public function __construct($code = 0, \Exception $previous = null) + public function __construct($code = 0, ?\Exception $previous = null) { parent::__construct( 'Could not create a temporary file with unique name in the specified directory.', diff --git a/src/PhpWord/Exception/Exception.php b/src/PhpWord/Exception/Exception.php index d874625cdc..7500dd3b23 100644 --- a/src/PhpWord/Exception/Exception.php +++ b/src/PhpWord/Exception/Exception.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Exception; /** - * General exception + * General exception. */ class Exception extends \Exception { diff --git a/src/PhpWord/Exception/InvalidImageException.php b/src/PhpWord/Exception/InvalidImageException.php index 07c966815a..359744451c 100644 --- a/src/PhpWord/Exception/InvalidImageException.php +++ b/src/PhpWord/Exception/InvalidImageException.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Exception; /** - * Exception used for when an image is not found + * Exception used for when an image is not found. */ class InvalidImageException extends Exception { diff --git a/src/PhpWord/Exception/InvalidObjectException.php b/src/PhpWord/Exception/InvalidObjectException.php index d8fef9613e..955b222fd4 100644 --- a/src/PhpWord/Exception/InvalidObjectException.php +++ b/src/PhpWord/Exception/InvalidObjectException.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Exception; /** - * Exception used for when an image is not found + * Exception used for when an image is not found. */ class InvalidObjectException extends Exception { diff --git a/src/PhpWord/Exception/InvalidStyleException.php b/src/PhpWord/Exception/InvalidStyleException.php index 58c1961ddd..dd4e09a454 100644 --- a/src/PhpWord/Exception/InvalidStyleException.php +++ b/src/PhpWord/Exception/InvalidStyleException.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,7 +20,7 @@ use InvalidArgumentException; /** - * Exception used for when a style value is invalid + * Exception used for when a style value is invalid. */ class InvalidStyleException extends InvalidArgumentException { diff --git a/src/PhpWord/Exception/UnsupportedImageTypeException.php b/src/PhpWord/Exception/UnsupportedImageTypeException.php index ee27065345..8807fe0d3f 100644 --- a/src/PhpWord/Exception/UnsupportedImageTypeException.php +++ b/src/PhpWord/Exception/UnsupportedImageTypeException.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Exception; /** - * Exception used for when an image type is unsupported + * Exception used for when an image type is unsupported. */ class UnsupportedImageTypeException extends Exception { diff --git a/src/PhpWord/IOFactory.php b/src/PhpWord/IOFactory.php index 3929f485e4..de2656d8c6 100644 --- a/src/PhpWord/IOFactory.php +++ b/src/PhpWord/IOFactory.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,22 +20,20 @@ use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\Reader\ReaderInterface; use PhpOffice\PhpWord\Writer\WriterInterface; +use ReflectionClass; abstract class IOFactory { /** - * Create new writer + * Create new writer. * - * @param PhpWord $phpWord * @param string $name * - * @throws \PhpOffice\PhpWord\Exception\Exception - * * @return WriterInterface */ public static function createWriter(PhpWord $phpWord, $name = 'Word2007') { - if ($name !== 'WriterInterface' && !in_array($name, array('ODText', 'RTF', 'Word2007', 'HTML', 'PDF'), true)) { + if ($name !== 'WriterInterface' && !in_array($name, ['ODText', 'RTF', 'Word2007', 'HTML', 'PDF'], true)) { throw new Exception("\"{$name}\" is not a valid writer."); } @@ -45,12 +43,10 @@ public static function createWriter(PhpWord $phpWord, $name = 'Word2007') } /** - * Create new reader + * Create new reader. * * @param string $name * - * @throws Exception - * * @return ReaderInterface */ public static function createReader($name = 'Word2007') @@ -59,15 +55,13 @@ public static function createReader($name = 'Word2007') } /** - * Create new object + * Create new object. * * @param string $type * @param string $name * @param \PhpOffice\PhpWord\PhpWord $phpWord * - * @throws \PhpOffice\PhpWord\Exception\Exception - * - * @return \PhpOffice\PhpWord\Writer\WriterInterface|\PhpOffice\PhpWord\Reader\ReaderInterface + * @return \PhpOffice\PhpWord\Reader\ReaderInterface|\PhpOffice\PhpWord\Writer\WriterInterface */ private static function createObject($type, $name, $phpWord = null) { @@ -75,14 +69,16 @@ private static function createObject($type, $name, $phpWord = null) if (class_exists($class) && self::isConcreteClass($class)) { return new $class($phpWord); } + throw new Exception("\"{$name}\" is not a valid {$type}."); } /** - * Loads PhpWord from file + * Loads PhpWord from file. * * @param string $filename The name of the file * @param string $readerName + * * @return \PhpOffice\PhpWord\PhpWord $phpWord */ public static function load($filename, $readerName = 'Word2007') @@ -94,14 +90,15 @@ public static function load($filename, $readerName = 'Word2007') } /** - * Check if it's a concrete class (not abstract nor interface) + * Check if it's a concrete class (not abstract nor interface). * * @param string $class + * * @return bool */ private static function isConcreteClass($class) { - $reflection = new \ReflectionClass($class); + $reflection = new ReflectionClass($class); return !$reflection->isAbstract() && !$reflection->isInterface(); } diff --git a/src/PhpWord/Media.php b/src/PhpWord/Media.php index cc1b290312..2e23f0b63b 100644 --- a/src/PhpWord/Media.php +++ b/src/PhpWord/Media.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,19 +21,19 @@ use PhpOffice\PhpWord\Exception\Exception; /** - * Media collection + * Media collection. */ class Media { /** - * Media elements + * Media elements. * * @var array */ - private static $elements = array(); + private static $elements = []; /** - * Add new media element + * Add new media element. * * @since 0.10.0 * @since 0.9.2 @@ -43,31 +43,29 @@ class Media * @param string $source * @param \PhpOffice\PhpWord\Element\Image $image * - * @throws \PhpOffice\PhpWord\Exception\Exception - * * @return int */ - public static function addElement($container, $mediaType, $source, Image $image = null) + public static function addElement($container, $mediaType, $source, ?Image $image = null) { // Assign unique media Id and initiate media container if none exists $mediaId = md5($container . $source); if (!isset(self::$elements[$container])) { - self::$elements[$container] = array(); + self::$elements[$container] = []; } // Add media if not exists or point to existing media if (!isset(self::$elements[$container][$mediaId])) { $mediaCount = self::countElements($container); $mediaTypeCount = self::countElements($container, $mediaType); - $mediaTypeCount++; + ++$mediaTypeCount; $rId = ++$mediaCount; $target = null; - $mediaData = array('mediaIndex' => $mediaTypeCount); + $mediaData = ['mediaIndex' => $mediaTypeCount]; switch ($mediaType) { // Images case 'image': - if (is_null($image)) { + if (null === $image) { throw new Exception('Image object not assigned.'); } $isMemImage = $image->isMemImage(); @@ -82,14 +80,17 @@ public static function addElement($container, $mediaType, $source, Image $image $target = "{$container}_image{$mediaTypeCount}.{$extension}"; $image->setTarget($target); $image->setMediaIndex($mediaTypeCount); + break; - // Objects + // Objects case 'object': $target = "{$container}_oleObject{$mediaTypeCount}.bin"; + break; - // Links + // Links case 'link': $target = $source; + break; } @@ -103,7 +104,7 @@ public static function addElement($container, $mediaType, $source, Image $image } $mediaData = self::$elements[$container][$mediaId]; - if (!is_null($image)) { + if (null !== $image) { $image->setTarget($mediaData['target']); $image->setMediaIndex($mediaData['mediaIndex']); } @@ -112,11 +113,13 @@ public static function addElement($container, $mediaType, $source, Image $image } /** - * Get media elements count + * Get media elements count. * * @param string $container section|headerx|footerx|footnote|endnote * @param string $mediaType image|object|link + * * @return int + * * @since 0.10.0 */ public static function countElements($container, $mediaType = null) @@ -125,12 +128,12 @@ public static function countElements($container, $mediaType = null) if (isset(self::$elements[$container])) { foreach (self::$elements[$container] as $mediaData) { - if (!is_null($mediaType)) { + if (null !== $mediaType) { if ($mediaType == $mediaData['type']) { - $mediaCount++; + ++$mediaCount; } } else { - $mediaCount++; + ++$mediaCount; } } } @@ -139,16 +142,18 @@ public static function countElements($container, $mediaType = null) } /** - * Get media elements + * Get media elements. * * @param string $container section|headerx|footerx|footnote|endnote * @param string $type image|object|link + * * @return array + * * @since 0.10.0 */ public static function getElements($container, $type = null) { - $elements = array(); + $elements = []; // If header/footer, search for headerx and footerx where x is number if ($container == 'header' || $container == 'footer') { @@ -169,16 +174,18 @@ public static function getElements($container, $type = null) } /** - * Get elements by media type + * Get elements by media type. * * @param string $container section|footnote|endnote * @param string $type image|object|link + * * @return array + * * @since 0.11.0 Splitted from `getElements` to reduce complexity */ private static function getElementsByType($container, $type = null) { - $elements = array(); + $elements = []; foreach (self::$elements[$container] as $key => $data) { if ($type !== null) { @@ -194,15 +201,15 @@ private static function getElementsByType($container, $type = null) } /** - * Reset media elements + * Reset media elements. */ - public static function resetElements() + public static function resetElements(): void { - self::$elements = array(); + self::$elements = []; } /** - * Add new Section Media Element + * Add new Section Media Element. * * @deprecated 0.10.0 * @@ -214,13 +221,13 @@ public static function resetElements() * * @codeCoverageIgnore */ - public static function addSectionMediaElement($src, $type, Image $image = null) + public static function addSectionMediaElement($src, $type, ?Image $image = null) { return self::addElement('section', $type, $src, $image); } /** - * Add new Section Link Element + * Add new Section Link Element. * * @deprecated 0.10.0 * @@ -236,7 +243,7 @@ public static function addSectionLinkElement($linkSrc) } /** - * Get Section Media Elements + * Get Section Media Elements. * * @deprecated 0.10.0 * @@ -252,7 +259,7 @@ public static function getSectionMediaElements($key = null) } /** - * Get Section Media Elements Count + * Get Section Media Elements Count. * * @deprecated 0.10.0 * @@ -268,7 +275,7 @@ public static function countSectionMediaElements($key = null) } /** - * Add new Header Media Element + * Add new Header Media Element. * * @deprecated 0.10.0 * @@ -280,13 +287,13 @@ public static function countSectionMediaElements($key = null) * * @codeCoverageIgnore */ - public static function addHeaderMediaElement($headerCount, $src, Image $image = null) + public static function addHeaderMediaElement($headerCount, $src, ?Image $image = null) { return self::addElement("header{$headerCount}", 'image', $src, $image); } /** - * Get Header Media Elements Count + * Get Header Media Elements Count. * * @deprecated 0.10.0 * @@ -302,7 +309,7 @@ public static function countHeaderMediaElements($key) } /** - * Get Header Media Elements + * Get Header Media Elements. * * @deprecated 0.10.0 * @@ -316,7 +323,7 @@ public static function getHeaderMediaElements() } /** - * Add new Footer Media Element + * Add new Footer Media Element. * * @deprecated 0.10.0 * @@ -328,13 +335,13 @@ public static function getHeaderMediaElements() * * @codeCoverageIgnore */ - public static function addFooterMediaElement($footerCount, $src, Image $image = null) + public static function addFooterMediaElement($footerCount, $src, ?Image $image = null) { return self::addElement("footer{$footerCount}", 'image', $src, $image); } /** - * Get Footer Media Elements Count + * Get Footer Media Elements Count. * * @deprecated 0.10.0 * @@ -350,7 +357,7 @@ public static function countFooterMediaElements($key) } /** - * Get Footer Media Elements + * Get Footer Media Elements. * * @deprecated 0.10.0 * diff --git a/src/PhpWord/Metadata/Compatibility.php b/src/PhpWord/Metadata/Compatibility.php index bf0363aa1a..b0bf14020d 100644 --- a/src/PhpWord/Metadata/Compatibility.php +++ b/src/PhpWord/Metadata/Compatibility.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Metadata; /** - * Compatibility setting class + * Compatibility setting class. * * @since 0.12.0 * @see http://www.datypic.com/sc/ooxml/t-w_CT_Compat.html @@ -26,19 +26,20 @@ class Compatibility { /** - * OOXML version + * OOXML version. * * 12 = 2007 * 14 = 2010 * 15 = 2013 * * @var int + * * @see http://msdn.microsoft.com/en-us/library/dd909048%28v=office.12%29.aspx */ private $ooxmlVersion = 12; /** - * Get OOXML version + * Get OOXML version. * * @return int */ @@ -48,9 +49,10 @@ public function getOoxmlVersion() } /** - * Set OOXML version + * Set OOXML version. * * @param int $value + * * @return self */ public function setOoxmlVersion($value) diff --git a/src/PhpWord/Metadata/DocInfo.php b/src/PhpWord/Metadata/DocInfo.php index 8a2f7d31ab..bdb2b7d37b 100644 --- a/src/PhpWord/Metadata/DocInfo.php +++ b/src/PhpWord/Metadata/DocInfo.php @@ -11,14 +11,16 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Metadata; +use DateTime; + /** - * Document information + * Document information. */ class DocInfo { @@ -31,91 +33,91 @@ class DocInfo const PROPERTY_TYPE_UNKNOWN = 'u'; /** - * Creator + * Creator. * * @var string */ private $creator; /** - * LastModifiedBy + * LastModifiedBy. * * @var string */ private $lastModifiedBy; /** - * Created + * Created. * * @var int */ private $created; /** - * Modified + * Modified. * * @var int */ private $modified; /** - * Title + * Title. * * @var string */ private $title; /** - * Description + * Description. * * @var string */ private $description; /** - * Subject + * Subject. * * @var string */ private $subject; /** - * Keywords + * Keywords. * * @var string */ private $keywords; /** - * Category + * Category. * * @var string */ private $category; /** - * Company + * Company. * * @var string */ private $company; /** - * Manager + * Manager. * * @var string */ private $manager; /** - * Custom Properties + * Custom Properties. * * @var array */ - private $customProperties = array(); + private $customProperties = []; /** - * Create new instance + * Create new instance. */ public function __construct() { @@ -133,7 +135,7 @@ public function __construct() } /** - * Get Creator + * Get Creator. * * @return string */ @@ -143,9 +145,10 @@ public function getCreator() } /** - * Set Creator + * Set Creator. * * @param string $value + * * @return self */ public function setCreator($value = '') @@ -156,7 +159,7 @@ public function setCreator($value = '') } /** - * Get Last Modified By + * Get Last Modified By. * * @return string */ @@ -166,9 +169,10 @@ public function getLastModifiedBy() } /** - * Set Last Modified By + * Set Last Modified By. * * @param string $value + * * @return self */ public function setLastModifiedBy($value = '') @@ -179,7 +183,7 @@ public function setLastModifiedBy($value = '') } /** - * Get Created + * Get Created. * * @return int */ @@ -189,9 +193,10 @@ public function getCreated() } /** - * Set Created + * Set Created. * * @param int $value + * * @return self */ public function setCreated($value = null) @@ -202,7 +207,7 @@ public function setCreated($value = null) } /** - * Get Modified + * Get Modified. * * @return int */ @@ -212,9 +217,10 @@ public function getModified() } /** - * Set Modified + * Set Modified. * * @param int $value + * * @return self */ public function setModified($value = null) @@ -225,7 +231,7 @@ public function setModified($value = null) } /** - * Get Title + * Get Title. * * @return string */ @@ -235,9 +241,10 @@ public function getTitle() } /** - * Set Title + * Set Title. * * @param string $value + * * @return self */ public function setTitle($value = '') @@ -248,7 +255,7 @@ public function setTitle($value = '') } /** - * Get Description + * Get Description. * * @return string */ @@ -258,9 +265,10 @@ public function getDescription() } /** - * Set Description + * Set Description. * * @param string $value + * * @return self */ public function setDescription($value = '') @@ -271,7 +279,7 @@ public function setDescription($value = '') } /** - * Get Subject + * Get Subject. * * @return string */ @@ -281,9 +289,10 @@ public function getSubject() } /** - * Set Subject + * Set Subject. * * @param string $value + * * @return self */ public function setSubject($value = '') @@ -294,7 +303,7 @@ public function setSubject($value = '') } /** - * Get Keywords + * Get Keywords. * * @return string */ @@ -304,9 +313,10 @@ public function getKeywords() } /** - * Set Keywords + * Set Keywords. * * @param string $value + * * @return self */ public function setKeywords($value = '') @@ -317,7 +327,7 @@ public function setKeywords($value = '') } /** - * Get Category + * Get Category. * * @return string */ @@ -327,9 +337,10 @@ public function getCategory() } /** - * Set Category + * Set Category. * * @param string $value + * * @return self */ public function setCategory($value = '') @@ -340,7 +351,7 @@ public function setCategory($value = '') } /** - * Get Company + * Get Company. * * @return string */ @@ -350,9 +361,10 @@ public function getCompany() } /** - * Set Company + * Set Company. * * @param string $value + * * @return self */ public function setCompany($value = '') @@ -363,7 +375,7 @@ public function setCompany($value = '') } /** - * Get Manager + * Get Manager. * * @return string */ @@ -373,9 +385,10 @@ public function getManager() } /** - * Set Manager + * Set Manager. * * @param string $value + * * @return self */ public function setManager($value = '') @@ -386,7 +399,7 @@ public function setManager($value = '') } /** - * Get a List of Custom Property Names + * Get a List of Custom Property Names. * * @return array of string */ @@ -396,9 +409,10 @@ public function getCustomProperties() } /** - * Check if a Custom Property is defined + * Check if a Custom Property is defined. * * @param string $propertyName + * * @return bool */ public function isCustomPropertySet($propertyName) @@ -407,9 +421,10 @@ public function isCustomPropertySet($propertyName) } /** - * Get a Custom Property Value + * Get a Custom Property Value. * * @param string $propertyName + * * @return mixed */ public function getCustomPropertyValue($propertyName) @@ -422,9 +437,10 @@ public function getCustomPropertyValue($propertyName) } /** - * Get a Custom Property Type + * Get a Custom Property Type. * * @param string $propertyName + * * @return string */ public function getCustomPropertyType($propertyName) @@ -437,7 +453,7 @@ public function getCustomPropertyType($propertyName) } /** - * Set a Custom Property + * Set a Custom Property. * * @param string $propertyName * @param mixed $propertyValue @@ -447,17 +463,18 @@ public function getCustomPropertyType($propertyName) * 's': String * 'd': Date/Time * 'b': Boolean + * * @return self */ public function setCustomProperty($propertyName, $propertyValue = '', $propertyType = null) { - $propertyTypes = array( + $propertyTypes = [ self::PROPERTY_TYPE_INTEGER, self::PROPERTY_TYPE_FLOAT, self::PROPERTY_TYPE_STRING, self::PROPERTY_TYPE_DATE, self::PROPERTY_TYPE_BOOLEAN, - ); + ]; if (($propertyType === null) || (!in_array($propertyType, $propertyTypes))) { if ($propertyValue === null) { $propertyType = self::PROPERTY_TYPE_STRING; @@ -467,26 +484,27 @@ public function setCustomProperty($propertyName, $propertyValue = '', $propertyT $propertyType = self::PROPERTY_TYPE_INTEGER; } elseif (is_bool($propertyValue)) { $propertyType = self::PROPERTY_TYPE_BOOLEAN; - } elseif ($propertyValue instanceof \DateTime) { + } elseif ($propertyValue instanceof DateTime) { $propertyType = self::PROPERTY_TYPE_DATE; } else { $propertyType = self::PROPERTY_TYPE_STRING; } } - $this->customProperties[$propertyName] = array( + $this->customProperties[$propertyName] = [ 'value' => $propertyValue, - 'type' => $propertyType, - ); + 'type' => $propertyType, + ]; return $this; } /** - * Convert document property based on type + * Convert document property based on type. * * @param string $propertyValue * @param string $propertyType + * * @return mixed */ public static function convertProperty($propertyValue, $propertyType) @@ -514,20 +532,21 @@ public static function convertProperty($propertyValue, $propertyType) } /** - * Convert document property type + * Convert document property type. * * @param string $propertyType + * * @return string */ public static function convertPropertyType($propertyType) { - $typeGroups = array( - self::PROPERTY_TYPE_INTEGER => array('i1', 'i2', 'i4', 'i8', 'int', 'ui1', 'ui2', 'ui4', 'ui8', 'uint'), - self::PROPERTY_TYPE_FLOAT => array('r4', 'r8', 'decimal'), - self::PROPERTY_TYPE_STRING => array('empty', 'null', 'lpstr', 'lpwstr', 'bstr'), - self::PROPERTY_TYPE_DATE => array('date', 'filetime'), - self::PROPERTY_TYPE_BOOLEAN => array('bool'), - ); + $typeGroups = [ + self::PROPERTY_TYPE_INTEGER => ['i1', 'i2', 'i4', 'i8', 'int', 'ui1', 'ui2', 'ui4', 'ui8', 'uint'], + self::PROPERTY_TYPE_FLOAT => ['r4', 'r8', 'decimal'], + self::PROPERTY_TYPE_STRING => ['empty', 'null', 'lpstr', 'lpwstr', 'bstr'], + self::PROPERTY_TYPE_DATE => ['date', 'filetime'], + self::PROPERTY_TYPE_BOOLEAN => ['bool'], + ]; foreach ($typeGroups as $groupId => $groupMembers) { if (in_array($propertyType, $groupMembers)) { return $groupId; @@ -538,10 +557,11 @@ public static function convertPropertyType($propertyType) } /** - * Set default for null and empty value + * Set default for null and empty value. * * @param mixed $value * @param mixed $default + * * @return mixed */ private function setValue($value, $default) @@ -554,22 +574,23 @@ private function setValue($value, $default) } /** - * Get conversion model depending on property type + * Get conversion model depending on property type. * * @param string $propertyType + * * @return string */ private static function getConversion($propertyType) { - $conversions = array( - 'empty' => array('empty'), - 'null' => array('null'), - 'int' => array('i1', 'i2', 'i4', 'i8', 'int'), - 'uint' => array('ui1', 'ui2', 'ui4', 'ui8', 'uint'), - 'float' => array('r4', 'r8', 'decimal'), - 'bool' => array('bool'), - 'date' => array('date', 'filetime'), - ); + $conversions = [ + 'empty' => ['empty'], + 'null' => ['null'], + 'int' => ['i1', 'i2', 'i4', 'i8', 'int'], + 'uint' => ['ui1', 'ui2', 'ui4', 'ui8', 'uint'], + 'float' => ['r4', 'r8', 'decimal'], + 'bool' => ['bool'], + 'date' => ['date', 'filetime'], + ]; foreach ($conversions as $conversion => $types) { if (in_array($propertyType, $types)) { return $conversion; diff --git a/src/PhpWord/Metadata/Protection.php b/src/PhpWord/Metadata/Protection.php index a46d43b945..c9b37631d3 100644 --- a/src/PhpWord/Metadata/Protection.php +++ b/src/PhpWord/Metadata/Protection.php @@ -11,17 +11,18 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Metadata; +use InvalidArgumentException; use PhpOffice\PhpWord\Shared\Microsoft\PasswordEncoder; use PhpOffice\PhpWord\SimpleType\DocProtect; /** - * Document protection class + * Document protection class. * * @since 0.12.0 * @see http://www.datypic.com/sc/ooxml/t-w_CT_DocProtect.html @@ -29,43 +30,44 @@ class Protection { /** - * Editing restriction none|readOnly|comments|trackedChanges|forms + * Editing restriction none|readOnly|comments|trackedChanges|forms. * * @var string + * * @see http://www.datypic.com/sc/ooxml/a-w_edit-1.html */ private $editing; /** - * password + * password. * * @var string */ private $password; /** - * Iterations to Run Hashing Algorithm + * Iterations to Run Hashing Algorithm. * * @var int */ private $spinCount = 100000; /** - * Cryptographic Hashing Algorithm (see constants defined in \PhpOffice\PhpWord\Shared\Microsoft\PasswordEncoder) + * Cryptographic Hashing Algorithm (see constants defined in \PhpOffice\PhpWord\Shared\Microsoft\PasswordEncoder). * * @var string */ private $algorithm = PasswordEncoder::ALGORITHM_SHA_1; /** - * Salt for Password Verifier + * Salt for Password Verifier. * * @var string */ private $salt; /** - * Create a new instance + * Create a new instance. * * @param string $editing */ @@ -77,7 +79,7 @@ public function __construct($editing = null) } /** - * Get editing protection + * Get editing protection. * * @return string */ @@ -87,9 +89,10 @@ public function getEditing() } /** - * Set editing protection + * Set editing protection. * * @param string $editing Any value of \PhpOffice\PhpWord\SimpleType\DocProtect + * * @return self */ public function setEditing($editing = null) @@ -101,7 +104,7 @@ public function setEditing($editing = null) } /** - * Get password + * Get password. * * @return string */ @@ -111,9 +114,10 @@ public function getPassword() } /** - * Set password + * Set password. * * @param string $password + * * @return self */ public function setPassword($password) @@ -124,7 +128,7 @@ public function setPassword($password) } /** - * Get count for hash iterations + * Get count for hash iterations. * * @return int */ @@ -134,9 +138,10 @@ public function getSpinCount() } /** - * Set count for hash iterations + * Set count for hash iterations. * * @param int $spinCount + * * @return self */ public function setSpinCount($spinCount) @@ -147,7 +152,7 @@ public function setSpinCount($spinCount) } /** - * Get algorithm + * Get algorithm. * * @return string */ @@ -157,9 +162,10 @@ public function getAlgorithm() } /** - * Set algorithm + * Set algorithm. * * @param string $algorithm + * * @return self */ public function setAlgorithm($algorithm) @@ -170,7 +176,7 @@ public function setAlgorithm($algorithm) } /** - * Get salt + * Get salt. * * @return string */ @@ -183,13 +189,13 @@ public function getSalt() * Set salt. Salt HAS to be 16 characters, or an exception will be thrown. * * @param string $salt - * @throws \InvalidArgumentException + * * @return self */ public function setSalt($salt) { if ($salt !== null && strlen($salt) !== 16) { - throw new \InvalidArgumentException('salt has to be of exactly 16 bytes length'); + throw new InvalidArgumentException('salt has to be of exactly 16 bytes length'); } $this->salt = $salt; diff --git a/src/PhpWord/Metadata/Settings.php b/src/PhpWord/Metadata/Settings.php index b1552e0210..e0e5ae0a66 100644 --- a/src/PhpWord/Metadata/Settings.php +++ b/src/PhpWord/Metadata/Settings.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -23,7 +23,7 @@ use PhpOffice\PhpWord\Style\Language; /** - * Setting class + * Setting class. * * @since 0.14.0 * @see http://www.datypic.com/sc/ooxml/t-w_CT_Settings.html @@ -31,72 +31,74 @@ class Settings { /** - * Magnification Setting + * Magnification Setting. * * @see http://www.datypic.com/sc/ooxml/e-w_zoom-1.html + * * @var mixed either integer, in which case it treated as a percent, or one of PhpOffice\PhpWord\SimpleType\Zoom */ private $zoom = 100; /** - * Mirror Page Margins + * Mirror Page Margins. * * @see http://www.datypic.com/sc/ooxml/e-w_mirrorMargins-1.html + * * @var bool */ private $mirrorMargins; /** - * Hide spelling errors + * Hide spelling errors. * * @var bool */ private $hideSpellingErrors = false; /** - * Hide grammatical errors + * Hide grammatical errors. * * @var bool */ private $hideGrammaticalErrors = false; /** - * Visibility of Annotation Types + * Visibility of Annotation Types. * * @var TrackChangesView */ private $revisionView; /** - * Track Revisions to Document + * Track Revisions to Document. * * @var bool */ private $trackRevisions = false; /** - * Do Not Use Move Syntax When Tracking Revisions + * Do Not Use Move Syntax When Tracking Revisions. * * @var bool */ private $doNotTrackMoves = false; /** - * Do Not Track Formatting Revisions When Tracking Revisions + * Do Not Track Formatting Revisions When Tracking Revisions. * * @var bool */ private $doNotTrackFormatting = false; /** - * Spelling and Grammatical Checking State + * Spelling and Grammatical Checking State. * * @var \PhpOffice\PhpWord\ComplexType\ProofState */ private $proofState; /** - * Document Editing Restrictions + * Document Editing Restrictions. * * @var \PhpOffice\PhpWord\Metadata\Protection */ @@ -110,49 +112,51 @@ class Settings private $evenAndOddHeaders = false; /** - * Theme Font Languages + * Theme Font Languages. * * @var Language */ private $themeFontLang; /** - * Automatically Recalculate Fields on Open + * Automatically Recalculate Fields on Open. * * @var bool */ private $updateFields = false; /** - * Radix Point for Field Code Evaluation + * Radix Point for Field Code Evaluation. * * @var string */ private $decimalSymbol = '.'; /** - * Automatically hyphenate document contents when displayed + * Automatically hyphenate document contents when displayed. * - * @var bool|null + * @var null|bool */ private $autoHyphenation; /** - * Maximum number of consecutively hyphenated lines + * Maximum number of consecutively hyphenated lines. * - * @var int|null + * @var null|int */ private $consecutiveHyphenLimit; /** - * The allowed amount of whitespace before hyphenation is applied - * @var float|null + * The allowed amount of whitespace before hyphenation is applied. + * + * @var null|float */ private $hyphenationZone; /** - * Do not hyphenate words in all capital letters - * @var bool|null + * Do not hyphenate words in all capital letters. + * + * @var null|bool */ private $doNotHyphenateCaps; @@ -171,7 +175,7 @@ public function getDocumentProtection() /** * @param Protection $documentProtection */ - public function setDocumentProtection($documentProtection) + public function setDocumentProtection($documentProtection): void { $this->documentProtection = $documentProtection; } @@ -191,13 +195,13 @@ public function getProofState() /** * @param ProofState $proofState */ - public function setProofState($proofState) + public function setProofState($proofState): void { $this->proofState = $proofState; } /** - * Are spelling errors hidden + * Are spelling errors hidden. * * @return bool */ @@ -207,17 +211,17 @@ public function hasHideSpellingErrors() } /** - * Hide spelling errors + * Hide spelling errors. * * @param bool $hideSpellingErrors */ - public function setHideSpellingErrors($hideSpellingErrors) + public function setHideSpellingErrors($hideSpellingErrors): void { $this->hideSpellingErrors = $hideSpellingErrors === null ? true : $hideSpellingErrors; } /** - * Are grammatical errors hidden + * Are grammatical errors hidden. * * @return bool */ @@ -227,11 +231,11 @@ public function hasHideGrammaticalErrors() } /** - * Hide grammatical errors + * Hide grammatical errors. * * @param bool $hideGrammaticalErrors */ - public function setHideGrammaticalErrors($hideGrammaticalErrors) + public function setHideGrammaticalErrors($hideGrammaticalErrors): void { $this->hideGrammaticalErrors = $hideGrammaticalErrors === null ? true : $hideGrammaticalErrors; } @@ -247,13 +251,13 @@ public function hasEvenAndOddHeaders() /** * @param bool $evenAndOddHeaders */ - public function setEvenAndOddHeaders($evenAndOddHeaders) + public function setEvenAndOddHeaders($evenAndOddHeaders): void { $this->evenAndOddHeaders = $evenAndOddHeaders === null ? true : $evenAndOddHeaders; } /** - * Get the Visibility of Annotation Types + * Get the Visibility of Annotation Types. * * @return \PhpOffice\PhpWord\ComplexType\TrackChangesView */ @@ -263,11 +267,11 @@ public function getRevisionView() } /** - * Set the Visibility of Annotation Types + * Set the Visibility of Annotation Types. * * @param TrackChangesView $trackChangesView */ - public function setRevisionView(TrackChangesView $trackChangesView = null) + public function setRevisionView(?TrackChangesView $trackChangesView = null): void { $this->revisionView = $trackChangesView; } @@ -283,7 +287,7 @@ public function hasTrackRevisions() /** * @param bool $trackRevisions */ - public function setTrackRevisions($trackRevisions) + public function setTrackRevisions($trackRevisions): void { $this->trackRevisions = $trackRevisions === null ? true : $trackRevisions; } @@ -299,7 +303,7 @@ public function hasDoNotTrackMoves() /** * @param bool $doNotTrackMoves */ - public function setDoNotTrackMoves($doNotTrackMoves) + public function setDoNotTrackMoves($doNotTrackMoves): void { $this->doNotTrackMoves = $doNotTrackMoves === null ? true : $doNotTrackMoves; } @@ -315,7 +319,7 @@ public function hasDoNotTrackFormatting() /** * @param bool $doNotTrackFormatting */ - public function setDoNotTrackFormatting($doNotTrackFormatting) + public function setDoNotTrackFormatting($doNotTrackFormatting): void { $this->doNotTrackFormatting = $doNotTrackFormatting === null ? true : $doNotTrackFormatting; } @@ -331,7 +335,7 @@ public function getZoom() /** * @param mixed $zoom */ - public function setZoom($zoom) + public function setZoom($zoom): void { if (is_numeric($zoom)) { // zoom is a percentage @@ -353,13 +357,13 @@ public function hasMirrorMargins() /** * @param bool $mirrorMargins */ - public function setMirrorMargins($mirrorMargins) + public function setMirrorMargins($mirrorMargins): void { $this->mirrorMargins = $mirrorMargins; } /** - * Returns the Language + * Returns the Language. * * @return Language */ @@ -369,11 +373,11 @@ public function getThemeFontLang() } /** - * sets the Language for this document + * sets the Language for this document. * * @param Language $themeFontLang */ - public function setThemeFontLang($themeFontLang) + public function setThemeFontLang($themeFontLang): void { $this->themeFontLang = $themeFontLang; } @@ -389,13 +393,13 @@ public function hasUpdateFields() /** * @param bool $updateFields */ - public function setUpdateFields($updateFields) + public function setUpdateFields($updateFields): void { $this->updateFields = $updateFields === null ? false : $updateFields; } /** - * Returns the Radix Point for Field Code Evaluation + * Returns the Radix Point for Field Code Evaluation. * * @return string */ @@ -405,17 +409,17 @@ public function getDecimalSymbol() } /** - * sets the Radix Point for Field Code Evaluation + * sets the Radix Point for Field Code Evaluation. * * @param string $decimalSymbol */ - public function setDecimalSymbol($decimalSymbol) + public function setDecimalSymbol($decimalSymbol): void { $this->decimalSymbol = $decimalSymbol; } /** - * @return bool|null + * @return null|bool */ public function hasAutoHyphenation() { @@ -425,13 +429,13 @@ public function hasAutoHyphenation() /** * @param bool $autoHyphenation */ - public function setAutoHyphenation($autoHyphenation) + public function setAutoHyphenation($autoHyphenation): void { $this->autoHyphenation = (bool) $autoHyphenation; } /** - * @return int|null + * @return null|int */ public function getConsecutiveHyphenLimit() { @@ -441,13 +445,13 @@ public function getConsecutiveHyphenLimit() /** * @param int $consecutiveHyphenLimit */ - public function setConsecutiveHyphenLimit($consecutiveHyphenLimit) + public function setConsecutiveHyphenLimit($consecutiveHyphenLimit): void { $this->consecutiveHyphenLimit = (int) $consecutiveHyphenLimit; } /** - * @return float|null + * @return null|float */ public function getHyphenationZone() { @@ -457,7 +461,7 @@ public function getHyphenationZone() /** * @param float $hyphenationZone Measurement unit is twip */ - public function setHyphenationZone($hyphenationZone) + public function setHyphenationZone($hyphenationZone): void { $this->hyphenationZone = $hyphenationZone; } @@ -473,7 +477,7 @@ public function hasDoNotHyphenateCaps() /** * @param bool $doNotHyphenateCaps */ - public function setDoNotHyphenateCaps($doNotHyphenateCaps) + public function setDoNotHyphenateCaps($doNotHyphenateCaps): void { $this->doNotHyphenateCaps = (bool) $doNotHyphenateCaps; } diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index a78df2c4e5..d93310e6e0 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -11,17 +11,18 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 -*/ + */ namespace PhpOffice\PhpWord; +use BadMethodCallException; use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\Exception\Exception; /** - * PHPWord main class + * PHPWord main class. * * @method Collection\Titles getTitles() * @method Collection\Footnotes getFootnotes() @@ -34,7 +35,6 @@ * @method int addEndnote(Element\Endnote $endnote) * @method int addChart(Element\Chart $chart) * @method int addComment(Element\Comment $comment) - * * @method Style\Paragraph addParagraphStyle(string $styleName, mixed $styles) * @method Style\Font addFontStyle(string $styleName, mixed $fontStyle, mixed $paragraphStyle = null) * @method Style\Font addLinkStyle(string $styleName, mixed $styles) @@ -45,7 +45,7 @@ class PhpWord { /** - * Default font settings + * Default font settings. * * @deprecated 0.11.0 Use Settings constants * @@ -66,29 +66,30 @@ class PhpWord const DEFAULT_FONT_CONTENT_TYPE = Settings::DEFAULT_FONT_CONTENT_TYPE; /** - * Collection of sections + * Collection of sections. * * @var \PhpOffice\PhpWord\Element\Section[] */ - private $sections = array(); + private $sections = []; /** - * Collections + * Collections. * * @var array */ - private $collections = array(); + private $collections = []; /** - * Metadata + * Metadata. * * @var array + * * @since 0.12.0 */ - private $metadata = array(); + private $metadata = []; /** - * Create new instance + * Create new instance. * * Collections are created dynamically */ @@ -99,14 +100,14 @@ public function __construct() Style::resetStyles(); // Collection - $collections = array('Bookmarks', 'Titles', 'Footnotes', 'Endnotes', 'Charts', 'Comments'); + $collections = ['Bookmarks', 'Titles', 'Footnotes', 'Endnotes', 'Charts', 'Comments']; foreach ($collections as $collection) { $class = 'PhpOffice\\PhpWord\\Collection\\' . $collection; $this->collections[$collection] = new $class(); } // Metadata - $metadata = array('DocInfo', 'Settings', 'Compatibility'); + $metadata = ['DocInfo', 'Settings', 'Compatibility']; foreach ($metadata as $meta) { $class = 'PhpOffice\\PhpWord\\Metadata\\' . $meta; $this->metadata[$meta] = new $class(); @@ -114,32 +115,30 @@ public function __construct() } /** - * Dynamic function call to reduce static dependency + * Dynamic function call to reduce static dependency. * * @since 0.12.0 * * @param mixed $function * @param mixed $args * - * @throws \BadMethodCallException - * * @return mixed */ public function __call($function, $args) { $function = strtolower($function); - $getCollection = array(); - $addCollection = array(); - $addStyle = array(); + $getCollection = []; + $addCollection = []; + $addStyle = []; - $collections = array('Bookmark', 'Title', 'Footnote', 'Endnote', 'Chart', 'Comment'); + $collections = ['Bookmark', 'Title', 'Footnote', 'Endnote', 'Chart', 'Comment']; foreach ($collections as $collection) { $getCollection[] = strtolower("get{$collection}s"); $addCollection[] = strtolower("add{$collection}"); } - $styles = array('Paragraph', 'Font', 'Table', 'Numbering', 'Link', 'Title'); + $styles = ['Paragraph', 'Font', 'Table', 'Numbering', 'Link', 'Title']; foreach ($styles as $style) { $addStyle[] = strtolower("add{$style}Style"); } @@ -158,20 +157,20 @@ public function __call($function, $args) /** @var \PhpOffice\PhpWord\Collection\AbstractCollection $collectionObject */ $collectionObject = $this->collections[$key]; - return $collectionObject->addItem(isset($args[0]) ? $args[0] : null); + return $collectionObject->addItem($args[0] ?? null); } // Run add style method if (in_array($function, $addStyle)) { - return forward_static_call_array(array('PhpOffice\\PhpWord\\Style', $function), $args); + return forward_static_call_array(['PhpOffice\\PhpWord\\Style', $function], $args); } // Exception - throw new \BadMethodCallException("Method $function is not defined."); + throw new BadMethodCallException("Method $function is not defined."); } /** - * Get document properties object + * Get document properties object. * * @return \PhpOffice\PhpWord\Metadata\DocInfo */ @@ -181,11 +180,13 @@ public function getDocInfo() } /** - * Get protection + * Get protection. * * @return \PhpOffice\PhpWord\Metadata\Protection + * * @since 0.12.0 * @deprecated Get the Document protection from PhpWord->getSettings()->getDocumentProtection(); + * * @codeCoverageIgnore */ public function getProtection() @@ -194,9 +195,10 @@ public function getProtection() } /** - * Get compatibility + * Get compatibility. * * @return \PhpOffice\PhpWord\Metadata\Compatibility + * * @since 0.12.0 */ public function getCompatibility() @@ -205,9 +207,10 @@ public function getCompatibility() } /** - * Get compatibility + * Get compatibility. * * @return \PhpOffice\PhpWord\Metadata\Settings + * * @since 0.14.0 */ public function getSettings() @@ -216,7 +219,7 @@ public function getSettings() } /** - * Get all sections + * Get all sections. * * @return \PhpOffice\PhpWord\Element\Section[] */ @@ -226,10 +229,11 @@ public function getSections() } /** - * Returns the section at the requested position + * Returns the section at the requested position. * * @param int $index - * @return \PhpOffice\PhpWord\Element\Section|null + * + * @return null|\PhpOffice\PhpWord\Element\Section */ public function getSection($index) { @@ -241,9 +245,10 @@ public function getSection($index) } /** - * Create new section + * Create new section. * * @param array $style + * * @return \PhpOffice\PhpWord\Element\Section */ public function addSection($style = null) @@ -256,18 +261,19 @@ public function addSection($style = null) } /** - * Sorts the sections using the callable passed + * Sorts the sections using the callable passed. * * @see http://php.net/manual/en/function.usort.php for usage + * * @param callable $sorter */ - public function sortSections($sorter) + public function sortSections($sorter): void { usort($this->sections, $sorter); } /** - * Get default font name + * Get default font name. * * @return string */ @@ -281,13 +287,13 @@ public function getDefaultFontName() * * @param string $fontName */ - public function setDefaultFontName($fontName) + public function setDefaultFontName($fontName): void { Settings::setDefaultFontName($fontName); } /** - * Get default font size + * Get default font size. * * @return int */ @@ -301,15 +307,16 @@ public function getDefaultFontSize() * * @param int $fontSize */ - public function setDefaultFontSize($fontSize) + public function setDefaultFontSize($fontSize): void { Settings::setDefaultFontSize($fontSize); } /** - * Set default paragraph style definition to styles.xml + * Set default paragraph style definition to styles.xml. * * @param array $styles Paragraph style definition + * * @return \PhpOffice\PhpWord\Style\Paragraph */ public function setDefaultParagraphStyle($styles) @@ -318,14 +325,12 @@ public function setDefaultParagraphStyle($styles) } /** - * Load template by filename + * Load template by filename. * * @deprecated 0.12.0 Use `new TemplateProcessor($documentTemplate)` instead. * * @param string $filename Fully qualified filename * - * @throws \PhpOffice\PhpWord\Exception\Exception - * * @return TemplateProcessor * * @codeCoverageIgnore @@ -335,28 +340,30 @@ public function loadTemplate($filename) if (file_exists($filename)) { return new TemplateProcessor($filename); } + throw new Exception("Template file {$filename} not found."); } /** - * Save to file or download + * Save to file or download. * * All exceptions should already been handled by the writers * * @param string $filename * @param string $format * @param bool $download + * * @return bool */ public function save($filename, $format = 'Word2007', $download = false) { - $mime = array( - 'Word2007' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'ODText' => 'application/vnd.oasis.opendocument.text', - 'RTF' => 'application/rtf', - 'HTML' => 'text/html', - 'PDF' => 'application/pdf', - ); + $mime = [ + 'Word2007' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'ODText' => 'application/vnd.oasis.opendocument.text', + 'RTF' => 'application/rtf', + 'HTML' => 'text/html', + 'PDF' => 'application/pdf', + ]; $writer = IOFactory::createWriter($this, $format); @@ -376,7 +383,7 @@ public function save($filename, $format = 'Word2007', $download = false) } /** - * Create new section + * Create new section. * * @deprecated 0.10.0 * @@ -392,7 +399,7 @@ public function createSection($settings = null) } /** - * Get document properties object + * Get document properties object. * * @deprecated 0.12.0 * @@ -406,7 +413,7 @@ public function getDocumentProperties() } /** - * Set document properties object + * Set document properties object. * * @deprecated 0.12.0 * diff --git a/src/PhpWord/Reader/AbstractReader.php b/src/PhpWord/Reader/AbstractReader.php index 7db285f758..4a138cd5ce 100644 --- a/src/PhpWord/Reader/AbstractReader.php +++ b/src/PhpWord/Reader/AbstractReader.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,7 +20,7 @@ use PhpOffice\PhpWord\Exception\Exception; /** - * Reader abstract class + * Reader abstract class. * * @since 0.8.0 * @@ -36,7 +36,7 @@ abstract class AbstractReader implements ReaderInterface protected $readDataOnly = true; /** - * File pointer + * File pointer. * * @var bool|resource */ @@ -54,9 +54,10 @@ public function isReadDataOnly() } /** - * Set read data only + * Set read data only. * * @param bool $value + * * @return self */ public function setReadDataOnly($value = true) @@ -67,12 +68,10 @@ public function setReadDataOnly($value = true) } /** - * Open file for reading + * Open file for reading. * * @param string $filename * - * @throws \PhpOffice\PhpWord\Exception\Exception - * * @return resource */ protected function openFile($filename) @@ -83,7 +82,7 @@ protected function openFile($filename) } // Open file - $this->fileHandle = fopen($filename, 'r'); + $this->fileHandle = fopen($filename, 'rb'); if ($this->fileHandle === false) { throw new Exception("Could not open file $filename for reading."); } @@ -93,6 +92,7 @@ protected function openFile($filename) * Can the current ReaderInterface read the file? * * @param string $filename + * * @return bool */ public function canRead($filename) diff --git a/src/PhpWord/Reader/HTML.php b/src/PhpWord/Reader/HTML.php index db9f20891c..30257d98cf 100644 --- a/src/PhpWord/Reader/HTML.php +++ b/src/PhpWord/Reader/HTML.php @@ -11,29 +11,28 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Reader; +use Exception; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Shared\Html as HTMLParser; /** - * HTML Reader class + * HTML Reader class. * * @since 0.11.0 */ class HTML extends AbstractReader implements ReaderInterface { /** - * Loads PhpWord from file + * Loads PhpWord from file. * * @param string $docFile * - * @throws \Exception - * * @return \PhpOffice\PhpWord\PhpWord */ public function load($docFile) @@ -44,7 +43,7 @@ public function load($docFile) $section = $phpWord->addSection(); HTMLParser::addHtml($section, file_get_contents($docFile), true); } else { - throw new \Exception("Cannot read {$docFile}."); + throw new Exception("Cannot read {$docFile}."); } return $phpWord; diff --git a/src/PhpWord/Reader/MsDoc.php b/src/PhpWord/Reader/MsDoc.php index 3a7967b3cd..ac084818a6 100644 --- a/src/PhpWord/Reader/MsDoc.php +++ b/src/PhpWord/Reader/MsDoc.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,65 +21,74 @@ use PhpOffice\PhpWord\Shared\Drawing; use PhpOffice\PhpWord\Shared\OLERead; use PhpOffice\PhpWord\Style; +use stdClass; /** - * Reader for Word97 + * Reader for Word97. * * @since 0.10.0 */ class MsDoc extends AbstractReader implements ReaderInterface { /** - * PhpWord object + * PhpWord object. * * @var PhpWord */ private $phpWord; /** - * WordDocument Stream + * WordDocument Stream. * * @var */ private $dataWorkDocument; + /** - * 1Table Stream + * 1Table Stream. * * @var */ private $data1Table; + /** - * Data Stream + * Data Stream. * * @var */ private $dataData; + /** - * Object Pool Stream + * Object Pool Stream. * * @var */ private $dataObjectPool; + /** - * @var \stdClass[] + * @var stdClass[] */ - private $arrayCharacters = array(); + private $arrayCharacters = []; + /** * @var array */ - private $arrayFib = array(); + private $arrayFib = []; + /** * @var string[] */ - private $arrayFonts = array(); + private $arrayFonts = []; + /** * @var string[] */ - private $arrayParagraphs = array(); + private $arrayParagraphs = []; + /** - * @var \stdClass[] + * @var stdClass[] */ - private $arraySections = array(); + private $arraySections = []; const VERSION_97 = '97'; const VERSION_2000 = '2000'; @@ -111,9 +120,10 @@ class MsDoc extends AbstractReader implements ReaderInterface const MSOBLIPCMYKJPEG = 0x12; /** - * Loads PhpWord from file + * Loads PhpWord from file. * * @param string $filename + * * @return PhpWord */ public function load($filename) @@ -129,10 +139,11 @@ public function load($filename) } /** - * Load an OLE Document + * Load an OLE Document. + * * @param string $filename */ - private function loadOLE($filename) + private function loadOLE($filename): void { // OLE reader $ole = new OLERead(); @@ -159,8 +170,8 @@ private function getNumInLcb($lcb, $iSize) private function getArrayCP($data, $posMem, $iNum) { - $arrayCP = array(); - for ($inc = 0; $inc < $iNum; $inc++) { + $arrayCP = []; + for ($inc = 0; $inc < $iNum; ++$inc) { $arrayCP[$inc] = self::getInt4d($data, $posMem); $posMem += 4; } @@ -171,6 +182,7 @@ private function getArrayCP($data, $posMem, $iNum) /** * @see http://msdn.microsoft.com/en-us/library/dd949344%28v=office.12%29.aspx * @see https://igor.io/2012/09/24/binary-parsing.html + * * @param string $data */ private function readFib($data) @@ -208,7 +220,7 @@ private function readFib($data) // lKey $pos += 4; // envr - $pos += 1; + ++$pos; // $mem = self::getInt1d($data, $pos); // $fMac = ($mem >> 7) & 1; @@ -217,7 +229,7 @@ private function readFib($data) // $reserved1 = ($mem >> 4) & 1; // $reserved2 = ($mem >> 3) & 1; // $fSpare0 = ($mem >> 0) & bindec('111'); - $pos += 1; + ++$pos; // reserved3 $pos += 2; @@ -317,21 +329,25 @@ private function readFib($data) switch ($cbRgFcLcb) { case 0x005D: $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_97); + break; case 0x006C: $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_97); $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2000); + break; case 0x0088: $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_97); $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2000); $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2002); + break; case 0x00A4: $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_97); $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2000); $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2002); $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2003); + break; case 0x00B7: $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_97); @@ -339,6 +355,7 @@ private function readFib($data) $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2002); $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2003); $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2007); + break; } //----- cswNew @@ -1100,7 +1117,7 @@ private function readBlockFibRgFcLcb($data, $pos, $version) return $pos; } - private function readFibContent() + private function readFibContent(): void { // Informations about Font $this->readRecordSttbfFfn(); @@ -1120,15 +1137,16 @@ private function readFibContent() } /** - * Section and information about them + * Section and information about them. + * * @see : http://msdn.microsoft.com/en-us/library/dd924458%28v=office.12%29.aspx */ - private function readRecordPlcfSed() + private function readRecordPlcfSed(): void { $posMem = $this->arrayFib['fcPlcfSed']; // PlcfSed // PlcfSed : aCP - $aCP = array(); + $aCP = []; $aCP[0] = self::getInt4d($this->data1Table, $posMem); $posMem += 4; $aCP[1] = self::getInt4d($this->data1Table, $posMem); @@ -1138,7 +1156,7 @@ private function readRecordPlcfSed() //@see : http://msdn.microsoft.com/en-us/library/dd950194%28v=office.12%29.aspx $numSed = $this->getNumInLcb($this->arrayFib['lcbPlcfSed'], 12); - $aSed = array(); + $aSed = []; for ($iInc = 0; $iInc < $numSed; ++$iInc) { // Sed : http://msdn.microsoft.com/en-us/library/dd950982%28v=office.12%29.aspx // fn @@ -1165,10 +1183,11 @@ private function readRecordPlcfSed() } /** - * Specifies the fonts that are used in the document + * Specifies the fonts that are used in the document. + * * @see : http://msdn.microsoft.com/en-us/library/dd943880%28v=office.12%29.aspx */ - private function readRecordSttbfFfn() + private function readRecordSttbfFfn(): void { $posMem = $this->arrayFib['fcSttbfFfn']; @@ -1178,18 +1197,18 @@ private function readRecordSttbfFfn() $posMem += 2; if ($cData < 0x7FF0 && $cbExtra == 0) { - for ($inc = 0; $inc < $cData; $inc++) { + for ($inc = 0; $inc < $cData; ++$inc) { // len - $posMem += 1; + ++$posMem; // ffid - $posMem += 1; + ++$posMem; // wWeight (400 : Normal - 700 bold) $posMem += 2; // chs - $posMem += 1; + ++$posMem; // ixchSzAlt $ixchSzAlt = self::getInt1d($this->data1Table, $posMem); - $posMem += 1; + ++$posMem; // panose $posMem += 10; // fs @@ -1215,19 +1234,20 @@ private function readRecordSttbfFfn() $xszAlt .= chr($char); } while ($char != 0); } - $this->arrayFonts[] = array( + $this->arrayFonts[] = [ 'main' => $xszFfn, - 'alt' => $xszAlt, - ); + 'alt' => $xszAlt, + ]; } } } /** - * Paragraph and information about them + * Paragraph and information about them. + * * @see http://msdn.microsoft.com/en-us/library/dd908569%28v=office.12%29.aspx */ - private function readRecordPlcfBtePapx() + private function readRecordPlcfBtePapx(): void { $posMem = $this->arrayFib['fcPlcfBtePapx']; $num = $this->getNumInLcb($this->arrayFib['lcbPlcfBtePapx'], 4); @@ -1242,16 +1262,16 @@ private function readRecordPlcfBtePapx() $string = ''; $numRun = self::getInt1d($this->dataWorkDocument, $offset + 511); - $arrayRGFC = array(); - for ($inc = 0; $inc <= $numRun; $inc++) { + $arrayRGFC = []; + for ($inc = 0; $inc <= $numRun; ++$inc) { $arrayRGFC[$inc] = self::getInt4d($this->dataWorkDocument, $offset); $offset += 4; } - $arrayRGB = array(); - for ($inc = 1; $inc <= $numRun; $inc++) { + $arrayRGB = []; + for ($inc = 1; $inc <= $numRun; ++$inc) { // @see http://msdn.microsoft.com/en-us/library/dd925804(v=office.12).aspx $arrayRGB[$inc] = self::getInt1d($this->dataWorkDocument, $offset); - $offset += 1; + ++$offset; // reserved $offset += 12; } @@ -1261,7 +1281,7 @@ private function readRecordPlcfBtePapx() break; } $strLen = $arrayRGFC[$key + 1] - $arrayRGFC[$key] - 1; - for ($inc = 0; $inc < $strLen; $inc++) { + for ($inc = 0; $inc < $strLen; ++$inc) { $byte = self::getInt1d($this->dataWorkDocument, $arrayRGFC[$key] + $inc); if ($byte > 0) { $string .= chr($byte); @@ -1436,15 +1456,16 @@ private function readRecordPlcfBtePapx() } /** - * Character formatting properties to text in a document + * Character formatting properties to text in a document. + * * @see http://msdn.microsoft.com/en-us/library/dd907108%28v=office.12%29.aspx */ - private function readRecordPlcfBteChpx() + private function readRecordPlcfBteChpx(): void { $posMem = $this->arrayFib['fcPlcfBteChpx']; $num = $this->getNumInLcb($this->arrayFib['lcbPlcfBteChpx'], 4); - $aPnBteChpx = array(); - for ($inc = 0; $inc <= $num; $inc++) { + $aPnBteChpx = []; + for ($inc = 0; $inc <= $num; ++$inc) { $aPnBteChpx[$inc] = self::getInt4d($this->data1Table, $posMem); $posMem += 4; } @@ -1457,21 +1478,21 @@ private function readRecordPlcfBteChpx() // ChpxFkp // @see : http://msdn.microsoft.com/en-us/library/dd910989%28v=office.12%29.aspx $numRGFC = self::getInt1d($this->dataWorkDocument, $offset + 511); - $arrayRGFC = array(); - for ($inc = 0; $inc <= $numRGFC; $inc++) { + $arrayRGFC = []; + for ($inc = 0; $inc <= $numRGFC; ++$inc) { $arrayRGFC[$inc] = self::getInt4d($this->dataWorkDocument, $offset); $offset += 4; } - $arrayRGB = array(); - for ($inc = 1; $inc <= $numRGFC; $inc++) { + $arrayRGB = []; + for ($inc = 1; $inc <= $numRGFC; ++$inc) { $arrayRGB[$inc] = self::getInt1d($this->dataWorkDocument, $offset); - $offset += 1; + ++$offset; } $start = 0; foreach ($arrayRGB as $keyRGB => $rgb) { - $oStyle = new \stdClass(); + $oStyle = new stdClass(); $oStyle->pos_start = $start; $oStyle->pos_len = (int) ceil((($arrayRGFC[$keyRGB] - 1) - $arrayRGFC[$keyRGB - 1]) / 2); $start += $oStyle->pos_len; @@ -1482,7 +1503,7 @@ private function readRecordPlcfBteChpx() $posRGB = $offsetBase + $rgb * 2; $cb = self::getInt1d($this->dataWorkDocument, $posRGB); - $posRGB += 1; + ++$posRGB; $oStyle->style = $this->readPrl($this->dataWorkDocument, $posRGB, $cb); $posRGB += $oStyle->style->length; @@ -1493,15 +1514,16 @@ private function readRecordPlcfBteChpx() /** * @param $sprm - * @return \stdClass + * + * @return stdClass */ private function readSprm($sprm) { - $oSprm = new \stdClass(); + $oSprm = new stdClass(); $oSprm->isPmd = $sprm & 0x01FF; - $oSprm->f = (int)($sprm / 512) & 0x0001; - $oSprm->sgc = (int)($sprm / 1024) & 0x0007; - $oSprm->spra = (int)($sprm / 8192); + $oSprm->f = (int) ($sprm / 512) & 0x0001; + $oSprm->sgc = (int) ($sprm / 1024) & 0x0007; + $oSprm->spra = (int) ($sprm / 8192); return $oSprm; } @@ -1509,7 +1531,8 @@ private function readSprm($sprm) /** * @param string $data * @param int $pos - * @param \stdClass $oSprm + * @param stdClass $oSprm + * * @return array */ private function readSprmSpra($data, $pos, $oSprm) @@ -1524,59 +1547,70 @@ private function readSprmSpra($data, $pos, $oSprm) switch (dechex($operand)) { case 0x00: $operand = false; + break; case 0x01: $operand = true; + break; case 0x80: $operand = self::SPRA_VALUE; + break; case 0x81: $operand = self::SPRA_VALUE_OPPOSITE; + break; } + break; case 0x1: $operand = self::getInt1d($data, $pos); $length = 1; + break; case 0x2: case 0x4: case 0x5: $operand = self::getInt2d($data, $pos); $length = 2; + break; case 0x3: if ($oSprm->isPmd != 0x70) { $operand = self::getInt4d($data, $pos); $length = 4; } + break; case 0x7: $operand = self::getInt3d($data, $pos); $length = 3; + break; default: // print_r('YO YO YO : '.PHP_EOL); } - return array( - 'length' => $length, + return [ + 'length' => $length, 'operand' => $operand, - ); + ]; } /** * @param $data int * @param $pos int * @param $cbNum int - * @return \stdClass + * + * @return stdClass + * * @see http://msdn.microsoft.com/en-us/library/dd772849%28v=office.12%29.aspx */ private function readPrl($data, $pos, $cbNum) { $posStart = $pos; - $oStylePrl = new \stdClass(); + $oStylePrl = new stdClass(); // Variables $sprmCPicLocation = null; @@ -1601,199 +1635,250 @@ private function readPrl($data, $pos, $cbNum) // Paragraph property case 0x01: break; - // Character property + // Character property case 0x02: if (!isset($oStylePrl->styleFont)) { - $oStylePrl->styleFont = array(); + $oStylePrl->styleFont = []; } switch ($oSprm->isPmd) { // sprmCFRMarkIns case 0x01: break; - // sprmCFFldVanish + // sprmCFFldVanish case 0x02: break; - // sprmCPicLocation + // sprmCPicLocation case 0x03: $sprmCPicLocation = $operand; + break; - // sprmCFData + // sprmCFData case 0x06: $sprmCFData = dechex($operand) != 0x00; + break; - // sprmCFItalic + // sprmCFItalic case 0x36: // By default, text is not italicized. switch ($operand) { case false: case true: $oStylePrl->styleFont['italic'] = $operand; + break; case self::SPRA_VALUE: $oStylePrl->styleFont['italic'] = false; + break; case self::SPRA_VALUE_OPPOSITE: $oStylePrl->styleFont['italic'] = true; + break; } + break; - // sprmCIstd + // sprmCIstd case 0x30: //print_r('sprmCIstd : '.dechex($operand).PHP_EOL.PHP_EOL); break; - // sprmCFBold + // sprmCFBold case 0x35: // By default, text is not bold. switch ($operand) { case false: case true: $oStylePrl->styleFont['bold'] = $operand; + break; case self::SPRA_VALUE: $oStylePrl->styleFont['bold'] = false; + break; case self::SPRA_VALUE_OPPOSITE: $oStylePrl->styleFont['bold'] = true; + break; } + break; - // sprmCFStrike + // sprmCFStrike case 0x37: // By default, text is not struck through. switch ($operand) { case false: case true: $oStylePrl->styleFont['strikethrough'] = $operand; + break; case self::SPRA_VALUE: $oStylePrl->styleFont['strikethrough'] = false; + break; case self::SPRA_VALUE_OPPOSITE: $oStylePrl->styleFont['strikethrough'] = true; + break; } + break; - // sprmCKul + // sprmCKul case 0x3E: switch (dechex($operand)) { case 0x00: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_NONE; + break; case 0x01: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_SINGLE; + break; case 0x02: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_WORDS; + break; case 0x03: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOUBLE; + break; case 0x04: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTTED; + break; case 0x06: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_HEAVY; + break; case 0x07: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DASH; + break; case 0x09: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTDASH; + break; case 0x0A: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTDOTDASH; + break; case 0x0B: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_WAVY; + break; case 0x14: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTTEDHEAVY; + break; case 0x17: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DASHHEAVY; + break; case 0x19: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTDASHHEAVY; + break; case 0x1A: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTDOTDASHHEAVY; + break; case 0x1B: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_WAVYHEAVY; + break; case 0x27: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DASHLONG; + break; case 0x2B: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_WAVYDOUBLE; + break; case 0x37: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DASHLONGHEAVY; + break; default: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_NONE; + break; } + break; - // sprmCIco - //@see http://msdn.microsoft.com/en-us/library/dd773060%28v=office.12%29.aspx + // sprmCIco + //@see http://msdn.microsoft.com/en-us/library/dd773060%28v=office.12%29.aspx case 0x42: switch (dechex($operand)) { case 0x00: case 0x01: $oStylePrl->styleFont['color'] = '000000'; + break; case 0x02: $oStylePrl->styleFont['color'] = '0000FF'; + break; case 0x03: $oStylePrl->styleFont['color'] = '00FFFF'; + break; case 0x04: $oStylePrl->styleFont['color'] = '00FF00'; + break; case 0x05: $oStylePrl->styleFont['color'] = 'FF00FF'; + break; case 0x06: $oStylePrl->styleFont['color'] = 'FF0000'; + break; case 0x07: $oStylePrl->styleFont['color'] = 'FFFF00'; + break; case 0x08: $oStylePrl->styleFont['color'] = 'FFFFFF'; + break; case 0x09: $oStylePrl->styleFont['color'] = '000080'; + break; case 0x0A: $oStylePrl->styleFont['color'] = '008080'; + break; case 0x0B: $oStylePrl->styleFont['color'] = '008000'; + break; case 0x0C: $oStylePrl->styleFont['color'] = '800080'; + break; case 0x0D: $oStylePrl->styleFont['color'] = '800080'; + break; case 0x0E: $oStylePrl->styleFont['color'] = '808000'; + break; case 0x0F: $oStylePrl->styleFont['color'] = '808080'; + break; case 0x10: $oStylePrl->styleFont['color'] = 'C0C0C0'; } + break; - // sprmCHps + // sprmCHps case 0x43: $oStylePrl->styleFont['size'] = dechex($operand / 2); + break; - // sprmCIss + // sprmCIss case 0x48: if (!isset($oStylePrl->styleFont['superScript'])) { $oStylePrl->styleFont['superScript'] = false; @@ -1807,42 +1892,46 @@ private function readPrl($data, $pos, $cbNum) break; case 0x01: $oStylePrl->styleFont['superScript'] = true; + break; case 0x02: $oStylePrl->styleFont['subScript'] = true; + break; } + break; - // sprmCRgFtc0 + // sprmCRgFtc0 case 0x4F: $oStylePrl->styleFont['name'] = ''; if (isset($this->arrayFonts[$operand])) { $oStylePrl->styleFont['name'] = $this->arrayFonts[$operand]['main']; } + break; - // sprmCRgFtc1 + // sprmCRgFtc1 case 0x50: // if the language for the text is an East Asian language break; - // sprmCRgFtc2 + // sprmCRgFtc2 case 0x51: // if the character falls outside the Unicode character range break; - // sprmCFSpec + // sprmCFSpec case 0x55: //$sprmCFSpec = $operand; break; - // sprmCFtcBi + // sprmCFtcBi case 0x5E: break; - // sprmCFItalicBi + // sprmCFItalicBi case 0x5D: break; - // sprmCHpsBi + // sprmCHpsBi case 0x61: break; - // sprmCShd80 - //@see http://msdn.microsoft.com/en-us/library/dd923447%28v=office.12%29.aspx + // sprmCShd80 + //@see http://msdn.microsoft.com/en-us/library/dd923447%28v=office.12%29.aspx case 0x66: // $operand = self::getInt2d($data, $pos); $pos += 2; @@ -1851,78 +1940,86 @@ private function readPrl($data, $pos, $cbNum) // $icoBack = ($operand >> 6) && bindec('11111'); // $icoFore = ($operand >> 11) && bindec('11111'); break; - // sprmCCv - //@see : http://msdn.microsoft.com/en-us/library/dd952824%28v=office.12%29.aspx + // sprmCCv + //@see : http://msdn.microsoft.com/en-us/library/dd952824%28v=office.12%29.aspx case 0x70: $red = str_pad(dechex(self::getInt1d($this->dataWorkDocument, $pos)), 2, '0', STR_PAD_LEFT); - $pos += 1; + ++$pos; $green = str_pad(dechex(self::getInt1d($this->dataWorkDocument, $pos)), 2, '0', STR_PAD_LEFT); - $pos += 1; + ++$pos; $blue = str_pad(dechex(self::getInt1d($this->dataWorkDocument, $pos)), 2, '0', STR_PAD_LEFT); - $pos += 1; - $pos += 1; + ++$pos; + ++$pos; $oStylePrl->styleFont['color'] = $red . $green . $blue; $cbNum -= 4; + break; default: // print_r('@todo Character : 0x'.dechex($oSprm->isPmd)); // print_r(PHP_EOL); } + break; - // Picture property + // Picture property case 0x03: break; - // Section property + // Section property case 0x04: if (!isset($oStylePrl->styleSection)) { - $oStylePrl->styleSection = array(); + $oStylePrl->styleSection = []; } switch ($oSprm->isPmd) { // sprmSNfcPgn case 0x0E: // numbering format used for page numbers break; - // sprmSXaPage + // sprmSXaPage case 0x1F: $oStylePrl->styleSection['pageSizeW'] = $operand; + break; - // sprmSYaPage + // sprmSYaPage case 0x20: $oStylePrl->styleSection['pageSizeH'] = $operand; + break; - // sprmSDxaLeft + // sprmSDxaLeft case 0x21: $oStylePrl->styleSection['marginLeft'] = $operand; + break; - // sprmSDxaRight + // sprmSDxaRight case 0x22: $oStylePrl->styleSection['marginRight'] = $operand; + break; - // sprmSDyaTop + // sprmSDyaTop case 0x23: $oStylePrl->styleSection['marginTop'] = $operand; + break; - // sprmSDyaBottom + // sprmSDyaBottom case 0x24: $oStylePrl->styleSection['marginBottom'] = $operand; + break; - // sprmSFBiDi + // sprmSFBiDi case 0x28: // RTL layout break; - // sprmSDxtCharSpace + // sprmSDxtCharSpace case 0x30: // characpter pitch break; - // sprmSDyaLinePitch + // sprmSDyaLinePitch case 0x31: // line height break; - // sprmSClm + // sprmSClm case 0x32: // document grid mode break; - // sprmSTextFlow + // sprmSTextFlow case 0x33: // text flow break; @@ -1930,15 +2027,16 @@ private function readPrl($data, $pos, $cbNum) // print_r('@todo Section : 0x'.dechex($oSprm->isPmd)); // print_r(PHP_EOL); } + break; - // Table property + // Table property case 0x05: break; } } while ($cbNum > 0); - if (!is_null($sprmCPicLocation)) { - if (!is_null($sprmCFData) && $sprmCFData == 0x01) { + if (null !== $sprmCPicLocation) { + if (null !== $sprmCFData && $sprmCFData == 0x01) { // NilPICFAndBinData //@todo Read Hyperlink structure /*$lcb = self::getInt4d($this->dataData, $sprmCPicLocation); @@ -2070,9 +2168,9 @@ private function readPrl($data, $pos, $cbNum) $picmidDxaCropBottom = self::getInt2d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 2; // PICF : picmid : fReserved - $sprmCPicLocation += 1; + ++$sprmCPicLocation; // PICF : picmid : bpp - $sprmCPicLocation += 1; + ++$sprmCPicLocation; // PICF : picmid : brcTop80 $sprmCPicLocation += 4; // PICF : picmid : brcLeft80 @@ -2091,13 +2189,13 @@ private function readPrl($data, $pos, $cbNum) if ($mfpfMm == 0x0066) { // cchPicName $cchPicName = self::getInt1d($this->dataData, $sprmCPicLocation); - $sprmCPicLocation += 1; + ++$sprmCPicLocation; // stPicName //$stPicName = ''; - for ($inc = 0; $inc <= $cchPicName; $inc++) { + for ($inc = 0; $inc <= $cchPicName; ++$inc) { //$chr = self::getInt1d($this->dataData, $sprmCPicLocation); - $sprmCPicLocation += 1; + ++$sprmCPicLocation; //$stPicName .= chr($chr); } } @@ -2119,9 +2217,9 @@ private function readPrl($data, $pos, $cbNum) //@see : http://msdn.microsoft.com/en-us/library/dd944923%28v=office.12%29.aspx case 0xF007: // btWin32 - $sprmCPicLocation += 1; + ++$sprmCPicLocation; // btMacOS - $sprmCPicLocation += 1; + ++$sprmCPicLocation; // rgbUid $sprmCPicLocation += 16; // tag @@ -2133,18 +2231,18 @@ private function readPrl($data, $pos, $cbNum) // foDelay $sprmCPicLocation += 4; // unused1 - $sprmCPicLocation += 1; + ++$sprmCPicLocation; // cbName $cbName = self::getInt1d($this->dataData, $sprmCPicLocation); - $sprmCPicLocation += 1; + ++$sprmCPicLocation; // unused2 - $sprmCPicLocation += 1; + ++$sprmCPicLocation; // unused3 - $sprmCPicLocation += 1; + ++$sprmCPicLocation; // nameData if ($cbName > 0) { //$nameData = ''; - for ($inc = 0; $inc <= ($cbName / 2); $inc++) { + for ($inc = 0; $inc <= ($cbName / 2); ++$inc) { //$chr = self::getInt2d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 2; //$nameData .= chr($chr); @@ -2157,7 +2255,7 @@ private function readPrl($data, $pos, $cbNum) case self::OFFICEARTBLIPJPG: case self::OFFICEARTBLIPJPEG: if (!isset($oStylePrl->image)) { - $oStylePrl->image = array(); + $oStylePrl->image = []; } $sprmCPicLocation += 8; // embeddedBlip : rgbUid1 @@ -2167,7 +2265,7 @@ private function readPrl($data, $pos, $cbNum) $sprmCPicLocation += 16; } // embeddedBlip : tag - $sprmCPicLocation += 1; + ++$sprmCPicLocation; // embeddedBlip : BLIPFileData $oStylePrl->image['data'] = substr($this->dataData, $sprmCPicLocation, $embeddedBlipRH['recLen']); $oStylePrl->image['format'] = 'jpg'; @@ -2184,12 +2282,14 @@ private function readPrl($data, $pos, $cbNum) $oStylePrl->image['height'] = Drawing::twipsToPixels($iCropHeight * $picmidMy / 1000); $sprmCPicLocation += $embeddedBlipRH['recLen']; + break; case self::OFFICEARTBLIPPNG: break; default: // print_r(dechex($embeddedBlipRH['recType'])); } + break; } $fileBlockRH = $this->loadRecordHeader($this->dataData, $sprmCPicLocation); @@ -2203,9 +2303,11 @@ private function readPrl($data, $pos, $cbNum) } /** - * Read a record header + * Read a record header. + * * @param string $stream * @param int $pos + * * @return array */ private function loadRecordHeader($stream, $pos) @@ -2214,15 +2316,15 @@ private function loadRecordHeader($stream, $pos) $recType = self::getInt2d($stream, $pos + 2); $recLen = self::getInt4d($stream, $pos + 4); - return array( - 'recVer' => ($rec >> 0) & bindec('1111'), + return [ + 'recVer' => ($rec >> 0) & bindec('1111'), 'recInstance' => ($rec >> 4) & bindec('111111111111'), - 'recType' => $recType, - 'recLen' => $recLen, - ); + 'recType' => $recType, + 'recLen' => $recLen, + ]; } - private function generatePhpWord() + private function generatePhpWord(): void { foreach ($this->arraySections as $itmSection) { $oSection = $this->phpWord->addSection(); @@ -2243,7 +2345,7 @@ private function generatePhpWord() } // Style Character - $styleFont = array(); + $styleFont = []; if (isset($oCharacters->style)) { if (isset($oCharacters->style->styleFont)) { $styleFont = $oCharacters->style->styleFont; @@ -2283,7 +2385,7 @@ private function generatePhpWord() if (isset($oCharacters->style->image)) { $fileImage = tempnam(sys_get_temp_dir(), 'PHPWord_MsDoc') . '.' . $oCharacters->style->image['format']; file_put_contents($fileImage, $oCharacters->style->image['data']); - $oSection->addImage($fileImage, array('width' => $oCharacters->style->image['width'], 'height' => $oCharacters->style->image['height'])); + $oSection->addImage($fileImage, ['width' => $oCharacters->style->image['width'], 'height' => $oCharacters->style->image['height']]); // print_r('>addImage<'.$fileImage.'>'.EOL); } } @@ -2296,10 +2398,11 @@ private function generatePhpWord() } /** - * Read 8-bit unsigned integer + * Read 8-bit unsigned integer. * * @param string $data * @param int $pos + * * @return int */ public static function getInt1d($data, $pos) @@ -2308,10 +2411,11 @@ public static function getInt1d($data, $pos) } /** - * Read 16-bit unsigned integer + * Read 16-bit unsigned integer. * * @param string $data * @param int $pos + * * @return int */ public static function getInt2d($data, $pos) @@ -2320,10 +2424,11 @@ public static function getInt2d($data, $pos) } /** - * Read 24-bit signed integer + * Read 24-bit signed integer. * * @param string $data * @param int $pos + * * @return int */ public static function getInt3d($data, $pos) @@ -2332,10 +2437,11 @@ public static function getInt3d($data, $pos) } /** - * Read 32-bit signed integer + * Read 32-bit signed integer. * * @param string $data * @param int $pos + * * @return int */ public static function getInt4d($data, $pos) diff --git a/src/PhpWord/Reader/ODText.php b/src/PhpWord/Reader/ODText.php index d0aa9138fa..aba280db01 100644 --- a/src/PhpWord/Reader/ODText.php +++ b/src/PhpWord/Reader/ODText.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,16 +21,17 @@ use PhpOffice\PhpWord\Shared\XMLReader; /** - * Reader for ODText + * Reader for ODText. * * @since 0.10.0 */ class ODText extends AbstractReader implements ReaderInterface { /** - * Loads PhpWord from file + * Loads PhpWord from file. * * @param string $docFile + * * @return \PhpOffice\PhpWord\PhpWord */ public function load($docFile) @@ -38,10 +39,10 @@ public function load($docFile) $phpWord = new PhpWord(); $relationships = $this->readRelationships($docFile); - $readerParts = array( + $readerParts = [ 'content.xml' => 'Content', - 'meta.xml' => 'Meta', - ); + 'meta.xml' => 'Meta', + ]; foreach ($readerParts as $xmlFile => $partName) { $this->readPart($phpWord, $relationships, $partName, $docFile, $xmlFile); @@ -53,13 +54,12 @@ public function load($docFile) /** * Read document part. * - * @param \PhpOffice\PhpWord\PhpWord $phpWord * @param array $relationships * @param string $partName * @param string $docFile * @param string $xmlFile */ - private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile, $xmlFile) + private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile, $xmlFile): void { $partClass = "PhpOffice\\PhpWord\\Reader\\ODText\\{$partName}"; if (class_exists($partClass)) { @@ -71,14 +71,15 @@ private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile, } /** - * Read all relationship files + * Read all relationship files. * * @param string $docFile + * * @return array */ private function readRelationships($docFile) { - $rels = array(); + $rels = []; $xmlFile = 'META-INF/manifest.xml'; $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($docFile, $xmlFile); @@ -86,7 +87,7 @@ private function readRelationships($docFile) foreach ($nodes as $node) { $type = $xmlReader->getAttribute('manifest:media-type', $node); $target = $xmlReader->getAttribute('manifest:full-path', $node); - $rels[] = array('type' => $type, 'target' => $target); + $rels[] = ['type' => $type, 'target' => $target]; } return $rels; diff --git a/src/PhpWord/Reader/ODText/AbstractPart.php b/src/PhpWord/Reader/ODText/AbstractPart.php index ff664e01fa..4c89192edd 100644 --- a/src/PhpWord/Reader/ODText/AbstractPart.php +++ b/src/PhpWord/Reader/ODText/AbstractPart.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,9 +20,10 @@ use PhpOffice\PhpWord\Reader\Word2007\AbstractPart as Word2007AbstractPart; /** - * Abstract part reader + * Abstract part reader. * * @since 0.10.0 + * * @codeCoverageIgnore */ abstract class AbstractPart extends Word2007AbstractPart diff --git a/src/PhpWord/Reader/ODText/Content.php b/src/PhpWord/Reader/ODText/Content.php index cec064181f..ccbc5eec96 100644 --- a/src/PhpWord/Reader/ODText/Content.php +++ b/src/PhpWord/Reader/ODText/Content.php @@ -11,18 +11,19 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Reader\ODText; +use DateTime; use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Shared\XMLReader; /** - * Content reader + * Content reader. * * @since 0.10.0 */ @@ -30,15 +31,13 @@ class Content extends AbstractPart { /** * Read content.xml. - * - * @param \PhpOffice\PhpWord\PhpWord $phpWord */ - public function read(PhpWord $phpWord) + public function read(PhpWord $phpWord): void { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); - $trackedChanges = array(); + $trackedChanges = []; $nodes = $xmlReader->getElements('office:body/office:text/*'); if ($nodes->length > 0) { @@ -49,6 +48,7 @@ public function read(PhpWord $phpWord) case 'text:h': // Heading $depth = $xmlReader->getAttribute('text:outline-level', $node); $section->addTitle($node->nodeValue, $depth); + break; case 'text:p': // Paragraph $children = $node->childNodes; @@ -59,15 +59,18 @@ public function read(PhpWord $phpWord) if (isset($trackedChanges[$changeId])) { $changed = $trackedChanges[$changeId]; } + break; case 'text:change-end': unset($changed); + break; case 'text:change': $changeId = $child->getAttribute('text:change-id'); if (isset($trackedChanges[$changeId])) { $changed = $trackedChanges[$changeId]; } + break; } } @@ -82,6 +85,7 @@ public function read(PhpWord $phpWord) } } } + break; case 'text:list': // List $listItems = $xmlReader->getElements('text:list-item/text:p', $node); @@ -89,6 +93,7 @@ public function read(PhpWord $phpWord) // $listStyleName = $xmlReader->getAttribute('text:style-name', $listItem); $section->addListItem($listItem->nodeValue, 0); } + break; case 'text:tracked-changes': $changedRegions = $xmlReader->getElements('text:changed-region', $node); @@ -99,11 +104,12 @@ public function read(PhpWord $phpWord) $dateNode = $xmlReader->getElements('office:change-info/dc:date', $changedRegion->firstChild); $date = $dateNode[0]->nodeValue; $date = preg_replace('/\.\d+$/', '', $date); - $date = \DateTime::createFromFormat('Y-m-d\TH:i:s', $date); + $date = DateTime::createFromFormat('Y-m-d\TH:i:s', $date); $changed = new TrackChange($type, $author, $date); $textNodes = $xmlReader->getElements('text:deletion/text:p', $changedRegion); - $trackedChanges[$changedRegion->getAttribute('text:id')] = array('changed' => $changed, 'textNodes'=> $textNodes); + $trackedChanges[$changedRegion->getAttribute('text:id')] = ['changed' => $changed, 'textNodes' => $textNodes]; } + break; } } diff --git a/src/PhpWord/Reader/ODText/Meta.php b/src/PhpWord/Reader/ODText/Meta.php index 9a3d83414f..200ee1306f 100644 --- a/src/PhpWord/Reader/ODText/Meta.php +++ b/src/PhpWord/Reader/ODText/Meta.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,7 +21,7 @@ use PhpOffice\PhpWord\Shared\XMLReader; /** - * Meta reader + * Meta reader. * * @since 0.11.0 */ @@ -30,10 +30,9 @@ class Meta extends AbstractPart /** * Read meta.xml. * - * @param \PhpOffice\PhpWord\PhpWord $phpWord * @todo Process property type */ - public function read(PhpWord $phpWord) + public function read(PhpWord $phpWord): void { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); @@ -42,16 +41,16 @@ public function read(PhpWord $phpWord) $metaNode = $xmlReader->getElement('office:meta'); // Standard properties - $properties = array( - 'title' => 'dc:title', - 'subject' => 'dc:subject', - 'description' => 'dc:description', - 'keywords' => 'meta:keyword', - 'creator' => 'meta:initial-creator', + $properties = [ + 'title' => 'dc:title', + 'subject' => 'dc:subject', + 'description' => 'dc:description', + 'keywords' => 'meta:keyword', + 'creator' => 'meta:initial-creator', 'lastModifiedBy' => 'dc:creator', // 'created' => 'meta:creation-date', // 'modified' => 'dc:date', - ); + ]; foreach ($properties as $property => $path) { $method = "set{$property}"; $propertyNode = $xmlReader->getElement($path, $metaNode); @@ -66,7 +65,7 @@ public function read(PhpWord $phpWord) $property = $xmlReader->getAttribute('meta:name', $propertyNode); // Set category, company, and manager property - if (in_array($property, array('Category', 'Company', 'Manager'))) { + if (in_array($property, ['Category', 'Company', 'Manager'])) { $method = "set{$property}"; $docProps->$method($propertyNode->nodeValue); } else { diff --git a/src/PhpWord/Reader/RTF.php b/src/PhpWord/Reader/RTF.php index 620252ffd7..2fdfb03839 100644 --- a/src/PhpWord/Reader/RTF.php +++ b/src/PhpWord/Reader/RTF.php @@ -11,29 +11,28 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Reader; +use Exception; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Reader\RTF\Document; /** - * RTF Reader class + * RTF Reader class. * * @since 0.11.0 */ class RTF extends AbstractReader implements ReaderInterface { /** - * Loads PhpWord from file + * Loads PhpWord from file. * * @param string $docFile * - * @throws \Exception - * * @return \PhpOffice\PhpWord\PhpWord */ public function load($docFile) @@ -45,7 +44,7 @@ public function load($docFile) $doc->rtf = file_get_contents($docFile); $doc->read($phpWord); } else { - throw new \Exception("Cannot read {$docFile}."); + throw new Exception("Cannot read {$docFile}."); } return $phpWord; diff --git a/src/PhpWord/Reader/RTF/Document.php b/src/PhpWord/Reader/RTF/Document.php index b9509d71fe..21b76cf71f 100644 --- a/src/PhpWord/Reader/RTF/Document.php +++ b/src/PhpWord/Reader/RTF/Document.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,7 +21,7 @@ use PhpOffice\PhpWord\SimpleType\Jc; /** - * RTF document reader + * RTF document reader. * * References: * - How to Write an RTF Reader http://latex2rtf.sourceforge.net/rtfspec_45.html @@ -29,6 +29,7 @@ * - JavaScript RTF-parser by LazyGyu https://github.com/lazygyu/RTF-parser * * @since 0.11.0 + * * @SuppressWarnings(PHPMD.UnusedPrivateMethod) */ class Document @@ -39,109 +40,108 @@ class Document const SKIP = 'readSkip'; /** - * PhpWord object + * PhpWord object. * * @var \PhpOffice\PhpWord\PhpWord */ private $phpWord; /** - * Section object + * Section object. * * @var \PhpOffice\PhpWord\Element\Section */ private $section; /** - * Textrun object + * Textrun object. * * @var \PhpOffice\PhpWord\Element\TextRun */ private $textrun; /** - * RTF content + * RTF content. * * @var string */ public $rtf; /** - * Content length + * Content length. * * @var int */ private $length = 0; /** - * Character index + * Character index. * * @var int */ private $offset = 0; /** - * Current control word + * Current control word. * * @var string */ private $control = ''; /** - * Text content + * Text content. * * @var string */ private $text = ''; /** - * Parsing a control word flag + * Parsing a control word flag. * * @var bool */ private $isControl = false; /** - * First character flag: watch out for control symbols + * First character flag: watch out for control symbols. * * @var bool */ private $isFirst = false; /** - * Group groups + * Group groups. * * @var array */ - private $groups = array(); + private $groups = []; /** - * Parser flags; not used + * Parser flags; not used. * * @var array */ - private $flags = array(); + private $flags = []; /** - * Parse RTF content + * Parse RTF content. * * - Marks controlling characters `{`, `}`, and `\` * - Removes line endings * - Builds control words and control symbols * - Pushes every other character into the text queue * - * @param \PhpOffice\PhpWord\PhpWord $phpWord * @todo Use `fread` stream for scalability */ - public function read(PhpWord $phpWord) + public function read(PhpWord $phpWord): void { - $markers = array( + $markers = [ 123 => 'markOpening', // { 125 => 'markClosing', // } - 92 => 'markBackslash', // \ - 10 => 'markNewline', // LF - 13 => 'markNewline', // CR - ); + 92 => 'markBackslash', // \ + 10 => 'markNewline', // LF + 13 => 'markNewline', // CR + ]; $this->phpWord = $phpWord; $this->section = $phpWord->addSection(); @@ -176,7 +176,7 @@ public function read(PhpWord $phpWord) } } } - $this->offset++; + ++$this->offset; } $this->flushText(); } @@ -184,7 +184,7 @@ public function read(PhpWord $phpWord) /** * Mark opening braket `{` character. */ - private function markOpening() + private function markOpening(): void { $this->flush(true); array_push($this->groups, $this->flags); @@ -193,7 +193,7 @@ private function markOpening() /** * Mark closing braket `}` character. */ - private function markClosing() + private function markClosing(): void { $this->flush(true); $this->flags = array_pop($this->groups); @@ -202,7 +202,7 @@ private function markClosing() /** * Mark backslash `\` character. */ - private function markBackslash() + private function markBackslash(): void { if ($this->isFirst) { $this->setControl(false); @@ -217,7 +217,7 @@ private function markBackslash() /** * Mark newline character: Flush control word because it's not possible to span multiline. */ - private function markNewline() + private function markNewline(): void { if ($this->isControl) { $this->flushControl(true); @@ -229,7 +229,7 @@ private function markNewline() * * @param bool $isControl */ - private function flush($isControl = false) + private function flush($isControl = false): void { if ($this->isControl) { $this->flushControl($isControl); @@ -243,10 +243,10 @@ private function flush($isControl = false) * * @param bool $isControl */ - private function flushControl($isControl = false) + private function flushControl($isControl = false): void { if (1 === preg_match('/^([A-Za-z]+)(-?[0-9]*) ?$/', $this->control, $match)) { - list(, $control, $parameter) = $match; + [, $control, $parameter] = $match; $this->parseControl($control, $parameter); } @@ -258,7 +258,7 @@ private function flushControl($isControl = false) /** * Flush text in queue. */ - private function flushText() + private function flushText(): void { if ($this->text != '') { if (isset($this->flags['property'])) { // Set property @@ -284,7 +284,7 @@ private function flushText() * * @param bool $value */ - private function setControl($value) + private function setControl($value): void { $this->isControl = $value; $this->isFirst = $value; @@ -295,7 +295,7 @@ private function setControl($value) * * @param string $char */ - private function pushText($char) + private function pushText($char): void { if ('<' == $char) { $this->text .= '<'; @@ -312,32 +312,32 @@ private function pushText($char) * @param string $control * @param string $parameter */ - private function parseControl($control, $parameter) + private function parseControl($control, $parameter): void { - $controls = array( - 'par' => array(self::PARA, 'paragraph', true), - 'b' => array(self::STYL, 'font', 'bold', true), - 'i' => array(self::STYL, 'font', 'italic', true), - 'u' => array(self::STYL, 'font', 'underline', true), - 'strike' => array(self::STYL, 'font', 'strikethrough', true), - 'fs' => array(self::STYL, 'font', 'size', $parameter), - 'qc' => array(self::STYL, 'paragraph', 'alignment', Jc::CENTER), - 'sa' => array(self::STYL, 'paragraph', 'spaceAfter', $parameter), - 'fonttbl' => array(self::SKIP, 'fonttbl', null), - 'colortbl' => array(self::SKIP, 'colortbl', null), - 'info' => array(self::SKIP, 'info', null), - 'generator' => array(self::SKIP, 'generator', null), - 'title' => array(self::SKIP, 'title', null), - 'subject' => array(self::SKIP, 'subject', null), - 'category' => array(self::SKIP, 'category', null), - 'keywords' => array(self::SKIP, 'keywords', null), - 'comment' => array(self::SKIP, 'comment', null), - 'shppict' => array(self::SKIP, 'pic', null), - 'fldinst' => array(self::SKIP, 'link', null), - ); + $controls = [ + 'par' => [self::PARA, 'paragraph', true], + 'b' => [self::STYL, 'font', 'bold', true], + 'i' => [self::STYL, 'font', 'italic', true], + 'u' => [self::STYL, 'font', 'underline', true], + 'strike' => [self::STYL, 'font', 'strikethrough', true], + 'fs' => [self::STYL, 'font', 'size', $parameter], + 'qc' => [self::STYL, 'paragraph', 'alignment', Jc::CENTER], + 'sa' => [self::STYL, 'paragraph', 'spaceAfter', $parameter], + 'fonttbl' => [self::SKIP, 'fonttbl', null], + 'colortbl' => [self::SKIP, 'colortbl', null], + 'info' => [self::SKIP, 'info', null], + 'generator' => [self::SKIP, 'generator', null], + 'title' => [self::SKIP, 'title', null], + 'subject' => [self::SKIP, 'subject', null], + 'category' => [self::SKIP, 'category', null], + 'keywords' => [self::SKIP, 'keywords', null], + 'comment' => [self::SKIP, 'comment', null], + 'shppict' => [self::SKIP, 'pic', null], + 'fldinst' => [self::SKIP, 'link', null], + ]; if (isset($controls[$control])) { - list($function) = $controls[$control]; + [$function] = $controls[$control]; if (method_exists($this, $function)) { $directives = $controls[$control]; array_shift($directives); // remove the function variable; we won't need it @@ -351,9 +351,9 @@ private function parseControl($control, $parameter) * * @param array $directives */ - private function readParagraph($directives) + private function readParagraph($directives): void { - list($property, $value) = $directives; + [$property, $value] = $directives; $this->textrun = $this->section->addTextRun(); $this->flags[$property] = $value; } @@ -363,9 +363,9 @@ private function readParagraph($directives) * * @param array $directives */ - private function readStyle($directives) + private function readStyle($directives): void { - list($style, $property, $value) = $directives; + [$style, $property, $value] = $directives; $this->flags['styles'][$style][$property] = $value; } @@ -374,9 +374,9 @@ private function readStyle($directives) * * @param array $directives */ - private function readSkip($directives) + private function readSkip($directives): void { - list($property) = $directives; + [$property] = $directives; $this->flags['property'] = $property; $this->flags['skipped'] = true; } @@ -384,7 +384,7 @@ private function readSkip($directives) /** * Read text. */ - private function readText() + private function readText(): void { $text = $this->textrun->addText($this->text); if (isset($this->flags['styles']['font'])) { diff --git a/src/PhpWord/Reader/ReaderInterface.php b/src/PhpWord/Reader/ReaderInterface.php index 4024cdb3d6..83c6993310 100644 --- a/src/PhpWord/Reader/ReaderInterface.php +++ b/src/PhpWord/Reader/ReaderInterface.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Reader; /** - * Reader interface + * Reader interface. * * @since 0.8.0 */ @@ -28,12 +28,13 @@ interface ReaderInterface * Can the current ReaderInterface read the file? * * @param string $filename + * * @return bool */ public function canRead($filename); /** - * Loads PhpWord from file + * Loads PhpWord from file. * * @param string $filename */ diff --git a/src/PhpWord/Reader/Word2007.php b/src/PhpWord/Reader/Word2007.php index 699a4eadd1..5f2a69c721 100644 --- a/src/PhpWord/Reader/Word2007.php +++ b/src/PhpWord/Reader/Word2007.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -22,18 +22,20 @@ use PhpOffice\PhpWord\Shared\ZipArchive; /** - * Reader for Word2007 + * Reader for Word2007. * * @since 0.8.0 + * * @todo watermark, checkbox, toc * @todo Partly done: image, object */ class Word2007 extends AbstractReader implements ReaderInterface { /** - * Loads PhpWord from file + * Loads PhpWord from file. * * @param string $docFile + * * @return \PhpOffice\PhpWord\PhpWord */ public function load($docFile) @@ -41,23 +43,23 @@ public function load($docFile) $phpWord = new PhpWord(); $relationships = $this->readRelationships($docFile); - $steps = array( - array('stepPart' => 'document', 'stepItems' => array( - 'styles' => 'Styles', + $steps = [ + ['stepPart' => 'document', 'stepItems' => [ + 'styles' => 'Styles', 'numbering' => 'Numbering', - )), - array('stepPart' => 'main', 'stepItems' => array( - 'officeDocument' => 'Document', - 'core-properties' => 'DocPropsCore', + ]], + ['stepPart' => 'main', 'stepItems' => [ + 'officeDocument' => 'Document', + 'core-properties' => 'DocPropsCore', 'extended-properties' => 'DocPropsApp', - 'custom-properties' => 'DocPropsCustom', - )), - array('stepPart' => 'document', 'stepItems' => array( - 'endnotes' => 'Endnotes', + 'custom-properties' => 'DocPropsCustom', + ]], + ['stepPart' => 'document', 'stepItems' => [ + 'endnotes' => 'Endnotes', 'footnotes' => 'Footnotes', - 'settings' => 'Settings', - )), - ); + 'settings' => 'Settings', + ]], + ]; foreach ($steps as $step) { $stepPart = $step['stepPart']; @@ -81,13 +83,12 @@ public function load($docFile) /** * Read document part. * - * @param \PhpOffice\PhpWord\PhpWord $phpWord * @param array $relationships * @param string $partName * @param string $docFile * @param string $xmlFile */ - private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile, $xmlFile) + private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile, $xmlFile): void { $partClass = "PhpOffice\\PhpWord\\Reader\\Word2007\\{$partName}"; if (class_exists($partClass)) { @@ -99,14 +100,15 @@ private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile, } /** - * Read all relationship files + * Read all relationship files. * * @param string $docFile + * * @return array */ private function readRelationships($docFile) { - $relationships = array(); + $relationships = []; // _rels/.rels $relationships['main'] = $this->getRels($docFile, '_rels/.rels'); @@ -115,7 +117,7 @@ private function readRelationships($docFile) $wordRelsPath = 'word/_rels/'; $zip = new ZipArchive(); if ($zip->open($docFile) === true) { - for ($i = 0; $i < $zip->numFiles; $i++) { + for ($i = 0; $i < $zip->numFiles; ++$i) { $xmlFile = $zip->getNameIndex($i); if ((substr($xmlFile, 0, strlen($wordRelsPath))) == $wordRelsPath && (substr($xmlFile, -1)) != '/') { $docPart = str_replace('.xml.rels', '', str_replace($wordRelsPath, '', $xmlFile)); @@ -129,11 +131,12 @@ private function readRelationships($docFile) } /** - * Get relationship array + * Get relationship array. * * @param string $docFile * @param string $xmlFile * @param string $targetPrefix + * * @return array */ private function getRels($docFile, $xmlFile, $targetPrefix = '') @@ -141,7 +144,7 @@ private function getRels($docFile, $xmlFile, $targetPrefix = '') $metaPrefix = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/'; $officePrefix = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/'; - $rels = array(); + $rels = []; $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($docFile, $xmlFile); @@ -163,7 +166,7 @@ private function getRels($docFile, $xmlFile, $targetPrefix = '') } // Push to return array - $rels[$rId] = array('type' => $type, 'target' => $target, 'docPart' => $docPart, 'targetMode' => $mode); + $rels[$rId] = ['type' => $type, 'target' => $target, 'docPart' => $docPart, 'targetMode' => $mode]; } ksort($rels); diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 729c0b95b0..7d4209953b 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -11,12 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Reader\Word2007; +use DateTime; +use DOMElement; use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType; use PhpOffice\PhpWord\Element\AbstractContainer; use PhpOffice\PhpWord\Element\TextRun; @@ -25,7 +27,7 @@ use PhpOffice\PhpWord\Shared\XMLReader; /** - * Abstract part reader + * Abstract part reader. * * This class is inherited by ODText reader * @@ -34,7 +36,7 @@ abstract class AbstractPart { /** - * Conversion method + * Conversion method. * * @const int */ @@ -45,25 +47,25 @@ abstract class AbstractPart const READ_SIZE = 'attributeMultiplyByTwo'; // Read special attribute value for Font::$size /** - * Document file + * Document file. * * @var string */ protected $docFile; /** - * XML file + * XML file. * * @var string */ protected $xmlFile; /** - * Part relationships + * Part relationships. * * @var array */ - protected $rels = array(); + protected $rels = []; /** * Read part. @@ -71,7 +73,7 @@ abstract class AbstractPart abstract public function read(PhpWord $phpWord); /** - * Create new instance + * Create new instance. * * @param string $docFile * @param string $xmlFile @@ -87,7 +89,7 @@ public function __construct($docFile, $xmlFile) * * @param array $value */ - public function setRels($value) + public function setRels($value): void { $this->rels = $value; } @@ -95,14 +97,12 @@ public function setRels($value) /** * Read w:p. * - * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader - * @param \DOMElement $domNode * @param \PhpOffice\PhpWord\Element\AbstractContainer $parent * @param string $docPart * * @todo Get font style for preserve text */ - protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $parent, $docPart = 'document') + protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $parent, $docPart = 'document'): void { // Paragraph style $paragraphStyle = null; @@ -128,7 +128,7 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $pa $ignoreText = false; } } - if (!is_null($instrText)) { + if (null !== $instrText) { $textContent .= '{' . $instrText . '}'; } else { if (false === $ignoreText) { @@ -177,19 +177,20 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $pa } /** - * Returns the depth of the Heading, returns 0 for a Title + * Returns the depth of the Heading, returns 0 for a Title. * * @param array $paragraphStyle - * @return number|null + * + * @return null|number */ - private function getHeadingDepth(array $paragraphStyle = null) + private function getHeadingDepth(?array $paragraphStyle = null) { if (is_array($paragraphStyle) && isset($paragraphStyle['styleName'])) { if ('Title' === $paragraphStyle['styleName']) { return 0; } - $headingMatches = array(); + $headingMatches = []; preg_match('/Heading(\d)/', $paragraphStyle['styleName'], $headingMatches); if (!empty($headingMatches)) { return $headingMatches[1]; @@ -202,17 +203,15 @@ private function getHeadingDepth(array $paragraphStyle = null) /** * Read w:r. * - * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader - * @param \DOMElement $domNode * @param \PhpOffice\PhpWord\Element\AbstractContainer $parent * @param string $docPart * @param mixed $paragraphStyle * * @todo Footnote paragraph style */ - protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, $parent, $docPart, $paragraphStyle = null) + protected function readRun(XMLReader $xmlReader, DOMElement $domNode, $parent, $docPart, $paragraphStyle = null): void { - if (in_array($domNode->nodeName, array('w:ins', 'w:del', 'w:smartTag', 'w:hyperlink'))) { + if (in_array($domNode->nodeName, ['w:ins', 'w:del', 'w:smartTag', 'w:hyperlink'])) { $nodes = $xmlReader->getElements('*', $domNode); foreach ($nodes as $node) { $this->readRun($xmlReader, $node, $parent, $docPart, $paragraphStyle); @@ -227,16 +226,13 @@ protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, $parent, } /** - * Parses nodes under w:r + * Parses nodes under w:r. * - * @param XMLReader $xmlReader - * @param \DOMElement $node - * @param AbstractContainer $parent * @param string $docPart * @param mixed $paragraphStyle * @param mixed $fontStyle */ - protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, AbstractContainer $parent, $docPart, $paragraphStyle = null, $fontStyle = null) + protected function readRunChild(XMLReader $xmlReader, DOMElement $node, AbstractContainer $parent, $docPart, $paragraphStyle = null, $fontStyle = null): void { $runParent = $node->parentNode->parentNode; if ($node->nodeName == 'w:footnoteReference') { @@ -253,7 +249,7 @@ protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, Abstrac // Image $rId = $xmlReader->getAttribute('r:id', $node, 'v:shape/v:imagedata'); $target = $this->getMediaTarget($docPart, $rId); - if (!is_null($target)) { + if (null !== $target) { if ('External' == $this->getTargetMode($docPart, $rId)) { $imageSource = $target; } else { @@ -275,7 +271,7 @@ protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, Abstrac $embedId = $xmlReader->getAttribute('r:embed', $node, 'wp:anchor/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip'); } $target = $this->getMediaTarget($docPart, $embedId); - if (!is_null($target)) { + if (null !== $target) { $imageSource = "zip://{$this->docFile}#{$target}"; $parent->addImage($imageSource, null, false, $name); } @@ -284,7 +280,7 @@ protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, Abstrac $rId = $xmlReader->getAttribute('r:id', $node, 'o:OLEObject'); // $rIdIcon = $xmlReader->getAttribute('r:id', $domNode, 'w:object/v:shape/v:imagedata'); $target = $this->getMediaTarget($docPart, $rId); - if (!is_null($target)) { + if (null !== $target) { $textContent = "<Object: {$target}>"; $parent->addText($textContent, $fontStyle, $paragraphStyle); } @@ -312,7 +308,7 @@ protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, Abstrac if ($runParent->nodeName == 'w:hyperlink') { $rId = $xmlReader->getAttribute('r:id', $runParent); $target = $this->getMediaTarget($docPart, $rId); - if (!is_null($target)) { + if (null !== $target) { $parent->addLink($target, $textContent, $fontStyle, $paragraphStyle); } else { $parent->addText($textContent, $fontStyle, $paragraphStyle); @@ -320,10 +316,10 @@ protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, Abstrac } else { /** @var AbstractElement $element */ $element = $parent->addText($textContent, $fontStyle, $paragraphStyle); - if (in_array($runParent->nodeName, array('w:ins', 'w:del'))) { + if (in_array($runParent->nodeName, ['w:ins', 'w:del'])) { $type = ($runParent->nodeName == 'w:del') ? TrackChange::DELETED : TrackChange::INSERTED; $author = $runParent->getAttribute('w:author'); - $date = \DateTime::createFromFormat('Y-m-d\TH:i:s\Z', $runParent->getAttribute('w:date')); + $date = DateTime::createFromFormat('Y-m-d\TH:i:s\Z', $runParent->getAttribute('w:date')); $element->setChangeInfo($type, $author, $date); } } @@ -333,12 +329,10 @@ protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, Abstrac /** * Read w:tbl. * - * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader - * @param \DOMElement $domNode * @param mixed $parent * @param string $docPart */ - protected function readTable(XMLReader $xmlReader, \DOMElement $domNode, $parent, $docPart = 'document') + protected function readTable(XMLReader $xmlReader, DOMElement $domNode, $parent, $docPart = 'document'): void { // Table style $tblStyle = null; @@ -356,11 +350,11 @@ protected function readTable(XMLReader $xmlReader, \DOMElement $domNode, $parent $rowHeight = $xmlReader->getAttribute('w:val', $tblNode, 'w:trPr/w:trHeight'); $rowHRule = $xmlReader->getAttribute('w:hRule', $tblNode, 'w:trPr/w:trHeight'); $rowHRule = $rowHRule == 'exact'; - $rowStyle = array( - 'tblHeader' => $xmlReader->elementExists('w:trPr/w:tblHeader', $tblNode), - 'cantSplit' => $xmlReader->elementExists('w:trPr/w:cantSplit', $tblNode), + $rowStyle = [ + 'tblHeader' => $xmlReader->elementExists('w:trPr/w:tblHeader', $tblNode), + 'cantSplit' => $xmlReader->elementExists('w:trPr/w:cantSplit', $tblNode), 'exactHeight' => $rowHRule, - ); + ]; $row = $table->addRow($rowHeight, $rowStyle); $rowNodes = $xmlReader->getElements('*', $tblNode); @@ -371,7 +365,7 @@ protected function readTable(XMLReader $xmlReader, \DOMElement $domNode, $parent $cellWidth = $xmlReader->getAttribute('w:w', $rowNode, 'w:tcPr/w:tcW'); $cellStyle = null; $cellStyleNode = $xmlReader->getElement('w:tcPr', $rowNode); - if (!is_null($cellStyleNode)) { + if (null !== $cellStyleNode) { $cellStyle = $this->readCellStyle($xmlReader, $cellStyleNode); } @@ -391,48 +385,44 @@ protected function readTable(XMLReader $xmlReader, \DOMElement $domNode, $parent /** * Read w:pPr. * - * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader - * @param \DOMElement $domNode - * @return array|null + * @return null|array */ - protected function readParagraphStyle(XMLReader $xmlReader, \DOMElement $domNode) + protected function readParagraphStyle(XMLReader $xmlReader, DOMElement $domNode) { if (!$xmlReader->elementExists('w:pPr', $domNode)) { return null; } $styleNode = $xmlReader->getElement('w:pPr', $domNode); - $styleDefs = array( - 'styleName' => array(self::READ_VALUE, array('w:pStyle', 'w:name')), - 'alignment' => array(self::READ_VALUE, 'w:jc'), - 'basedOn' => array(self::READ_VALUE, 'w:basedOn'), - 'next' => array(self::READ_VALUE, 'w:next'), - 'indent' => array(self::READ_VALUE, 'w:ind', 'w:left'), - 'hanging' => array(self::READ_VALUE, 'w:ind', 'w:hanging'), - 'spaceAfter' => array(self::READ_VALUE, 'w:spacing', 'w:after'), - 'spaceBefore' => array(self::READ_VALUE, 'w:spacing', 'w:before'), - 'widowControl' => array(self::READ_FALSE, 'w:widowControl'), - 'keepNext' => array(self::READ_TRUE, 'w:keepNext'), - 'keepLines' => array(self::READ_TRUE, 'w:keepLines'), - 'pageBreakBefore' => array(self::READ_TRUE, 'w:pageBreakBefore'), - 'contextualSpacing' => array(self::READ_TRUE, 'w:contextualSpacing'), - 'bidi' => array(self::READ_TRUE, 'w:bidi'), - 'suppressAutoHyphens' => array(self::READ_TRUE, 'w:suppressAutoHyphens'), - ); + $styleDefs = [ + 'styleName' => [self::READ_VALUE, ['w:pStyle', 'w:name']], + 'alignment' => [self::READ_VALUE, 'w:jc'], + 'basedOn' => [self::READ_VALUE, 'w:basedOn'], + 'next' => [self::READ_VALUE, 'w:next'], + 'indent' => [self::READ_VALUE, 'w:ind', 'w:left'], + 'hanging' => [self::READ_VALUE, 'w:ind', 'w:hanging'], + 'spaceAfter' => [self::READ_VALUE, 'w:spacing', 'w:after'], + 'spaceBefore' => [self::READ_VALUE, 'w:spacing', 'w:before'], + 'widowControl' => [self::READ_FALSE, 'w:widowControl'], + 'keepNext' => [self::READ_TRUE, 'w:keepNext'], + 'keepLines' => [self::READ_TRUE, 'w:keepLines'], + 'pageBreakBefore' => [self::READ_TRUE, 'w:pageBreakBefore'], + 'contextualSpacing' => [self::READ_TRUE, 'w:contextualSpacing'], + 'bidi' => [self::READ_TRUE, 'w:bidi'], + 'suppressAutoHyphens' => [self::READ_TRUE, 'w:suppressAutoHyphens'], + ]; return $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); } /** - * Read w:rPr + * Read w:rPr. * - * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader - * @param \DOMElement $domNode - * @return array|null + * @return null|array */ - protected function readFontStyle(XMLReader $xmlReader, \DOMElement $domNode) + protected function readFontStyle(XMLReader $xmlReader, DOMElement $domNode) { - if (is_null($domNode)) { + if (null === $domNode) { return null; } // Hyperlink has an extra w:r child @@ -444,64 +434,63 @@ protected function readFontStyle(XMLReader $xmlReader, \DOMElement $domNode) } $styleNode = $xmlReader->getElement('w:rPr', $domNode); - $styleDefs = array( - 'styleName' => array(self::READ_VALUE, 'w:rStyle'), - 'name' => array(self::READ_VALUE, 'w:rFonts', array('w:ascii', 'w:hAnsi', 'w:eastAsia', 'w:cs')), - 'hint' => array(self::READ_VALUE, 'w:rFonts', 'w:hint'), - 'size' => array(self::READ_SIZE, array('w:sz', 'w:szCs')), - 'color' => array(self::READ_VALUE, 'w:color'), - 'underline' => array(self::READ_VALUE, 'w:u'), - 'bold' => array(self::READ_TRUE, 'w:b'), - 'italic' => array(self::READ_TRUE, 'w:i'), - 'strikethrough' => array(self::READ_TRUE, 'w:strike'), - 'doubleStrikethrough' => array(self::READ_TRUE, 'w:dstrike'), - 'smallCaps' => array(self::READ_TRUE, 'w:smallCaps'), - 'allCaps' => array(self::READ_TRUE, 'w:caps'), - 'superScript' => array(self::READ_EQUAL, 'w:vertAlign', 'w:val', 'superscript'), - 'subScript' => array(self::READ_EQUAL, 'w:vertAlign', 'w:val', 'subscript'), - 'fgColor' => array(self::READ_VALUE, 'w:highlight'), - 'rtl' => array(self::READ_TRUE, 'w:rtl'), - 'lang' => array(self::READ_VALUE, 'w:lang'), - 'position' => array(self::READ_VALUE, 'w:position'), - 'hidden' => array(self::READ_TRUE, 'w:vanish'), - ); + $styleDefs = [ + 'styleName' => [self::READ_VALUE, 'w:rStyle'], + 'name' => [self::READ_VALUE, 'w:rFonts', ['w:ascii', 'w:hAnsi', 'w:eastAsia', 'w:cs']], + 'hint' => [self::READ_VALUE, 'w:rFonts', 'w:hint'], + 'size' => [self::READ_SIZE, ['w:sz', 'w:szCs']], + 'color' => [self::READ_VALUE, 'w:color'], + 'underline' => [self::READ_VALUE, 'w:u'], + 'bold' => [self::READ_TRUE, 'w:b'], + 'italic' => [self::READ_TRUE, 'w:i'], + 'strikethrough' => [self::READ_TRUE, 'w:strike'], + 'doubleStrikethrough' => [self::READ_TRUE, 'w:dstrike'], + 'smallCaps' => [self::READ_TRUE, 'w:smallCaps'], + 'allCaps' => [self::READ_TRUE, 'w:caps'], + 'superScript' => [self::READ_EQUAL, 'w:vertAlign', 'w:val', 'superscript'], + 'subScript' => [self::READ_EQUAL, 'w:vertAlign', 'w:val', 'subscript'], + 'fgColor' => [self::READ_VALUE, 'w:highlight'], + 'rtl' => [self::READ_TRUE, 'w:rtl'], + 'lang' => [self::READ_VALUE, 'w:lang'], + 'position' => [self::READ_VALUE, 'w:position'], + 'hidden' => [self::READ_TRUE, 'w:vanish'], + ]; return $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); } /** - * Read w:tblPr + * Read w:tblPr. + * + * @return null|array|string * - * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader - * @param \DOMElement $domNode - * @return string|array|null * @todo Capture w:tblStylePr w:type="firstRow" */ - protected function readTableStyle(XMLReader $xmlReader, \DOMElement $domNode) + protected function readTableStyle(XMLReader $xmlReader, DOMElement $domNode) { $style = null; - $margins = array('top', 'left', 'bottom', 'right'); - $borders = array_merge($margins, array('insideH', 'insideV')); + $margins = ['top', 'left', 'bottom', 'right']; + $borders = array_merge($margins, ['insideH', 'insideV']); if ($xmlReader->elementExists('w:tblPr', $domNode)) { if ($xmlReader->elementExists('w:tblPr/w:tblStyle', $domNode)) { $style = $xmlReader->getAttribute('w:val', $domNode, 'w:tblPr/w:tblStyle'); } else { $styleNode = $xmlReader->getElement('w:tblPr', $domNode); - $styleDefs = array(); + $styleDefs = []; foreach ($margins as $side) { $ucfSide = ucfirst($side); - $styleDefs["cellMargin$ucfSide"] = array(self::READ_VALUE, "w:tblCellMar/w:$side", 'w:w'); + $styleDefs["cellMargin$ucfSide"] = [self::READ_VALUE, "w:tblCellMar/w:$side", 'w:w']; } foreach ($borders as $side) { $ucfSide = ucfirst($side); - $styleDefs["border{$ucfSide}Size"] = array(self::READ_VALUE, "w:tblBorders/w:$side", 'w:sz'); - $styleDefs["border{$ucfSide}Color"] = array(self::READ_VALUE, "w:tblBorders/w:$side", 'w:color'); - $styleDefs["border{$ucfSide}Style"] = array(self::READ_VALUE, "w:tblBorders/w:$side", 'w:val'); + $styleDefs["border{$ucfSide}Size"] = [self::READ_VALUE, "w:tblBorders/w:$side", 'w:sz']; + $styleDefs["border{$ucfSide}Color"] = [self::READ_VALUE, "w:tblBorders/w:$side", 'w:color']; + $styleDefs["border{$ucfSide}Style"] = [self::READ_VALUE, "w:tblBorders/w:$side", 'w:val']; } - $styleDefs['layout'] = array(self::READ_VALUE, 'w:tblLayout', 'w:type'); - $styleDefs['bidiVisual'] = array(self::READ_TRUE, 'w:bidiVisual'); - $styleDefs['cellSpacing'] = array(self::READ_VALUE, 'w:tblCellSpacing', 'w:w'); + $styleDefs['layout'] = [self::READ_VALUE, 'w:tblLayout', 'w:type']; + $styleDefs['bidiVisual'] = [self::READ_TRUE, 'w:bidiVisual']; + $styleDefs['cellSpacing'] = [self::READ_VALUE, 'w:tblCellSpacing', 'w:w']; $style = $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); $tablePositionNode = $xmlReader->getElement('w:tblpPr', $styleNode); @@ -520,77 +509,70 @@ protected function readTableStyle(XMLReader $xmlReader, \DOMElement $domNode) } /** - * Read w:tblpPr + * Read w:tblpPr. * - * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader - * @param \DOMElement $domNode * @return array */ - private function readTablePosition(XMLReader $xmlReader, \DOMElement $domNode) + private function readTablePosition(XMLReader $xmlReader, DOMElement $domNode) { - $styleDefs = array( - 'leftFromText' => array(self::READ_VALUE, '.', 'w:leftFromText'), - 'rightFromText' => array(self::READ_VALUE, '.', 'w:rightFromText'), - 'topFromText' => array(self::READ_VALUE, '.', 'w:topFromText'), - 'bottomFromText' => array(self::READ_VALUE, '.', 'w:bottomFromText'), - 'vertAnchor' => array(self::READ_VALUE, '.', 'w:vertAnchor'), - 'horzAnchor' => array(self::READ_VALUE, '.', 'w:horzAnchor'), - 'tblpXSpec' => array(self::READ_VALUE, '.', 'w:tblpXSpec'), - 'tblpX' => array(self::READ_VALUE, '.', 'w:tblpX'), - 'tblpYSpec' => array(self::READ_VALUE, '.', 'w:tblpYSpec'), - 'tblpY' => array(self::READ_VALUE, '.', 'w:tblpY'), - ); + $styleDefs = [ + 'leftFromText' => [self::READ_VALUE, '.', 'w:leftFromText'], + 'rightFromText' => [self::READ_VALUE, '.', 'w:rightFromText'], + 'topFromText' => [self::READ_VALUE, '.', 'w:topFromText'], + 'bottomFromText' => [self::READ_VALUE, '.', 'w:bottomFromText'], + 'vertAnchor' => [self::READ_VALUE, '.', 'w:vertAnchor'], + 'horzAnchor' => [self::READ_VALUE, '.', 'w:horzAnchor'], + 'tblpXSpec' => [self::READ_VALUE, '.', 'w:tblpXSpec'], + 'tblpX' => [self::READ_VALUE, '.', 'w:tblpX'], + 'tblpYSpec' => [self::READ_VALUE, '.', 'w:tblpYSpec'], + 'tblpY' => [self::READ_VALUE, '.', 'w:tblpY'], + ]; return $this->readStyleDefs($xmlReader, $domNode, $styleDefs); } /** - * Read w:tblInd + * Read w:tblInd. * - * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader - * @param \DOMElement $domNode * @return TblWidthComplexType */ - private function readTableIndent(XMLReader $xmlReader, \DOMElement $domNode) + private function readTableIndent(XMLReader $xmlReader, DOMElement $domNode) { - $styleDefs = array( - 'value' => array(self::READ_VALUE, '.', 'w:w'), - 'type' => array(self::READ_VALUE, '.', 'w:type'), - ); + $styleDefs = [ + 'value' => [self::READ_VALUE, '.', 'w:w'], + 'type' => [self::READ_VALUE, '.', 'w:type'], + ]; $styleDefs = $this->readStyleDefs($xmlReader, $domNode, $styleDefs); return new TblWidthComplexType((int) $styleDefs['value'], $styleDefs['type']); } /** - * Read w:tcPr + * Read w:tcPr. * - * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader - * @param \DOMElement $domNode * @return array */ - private function readCellStyle(XMLReader $xmlReader, \DOMElement $domNode) + private function readCellStyle(XMLReader $xmlReader, DOMElement $domNode) { - $styleDefs = array( - 'valign' => array(self::READ_VALUE, 'w:vAlign'), - 'textDirection' => array(self::READ_VALUE, 'w:textDirection'), - 'gridSpan' => array(self::READ_VALUE, 'w:gridSpan'), - 'vMerge' => array(self::READ_VALUE, 'w:vMerge'), - 'bgColor' => array(self::READ_VALUE, 'w:shd', 'w:fill'), - ); + $styleDefs = [ + 'valign' => [self::READ_VALUE, 'w:vAlign'], + 'textDirection' => [self::READ_VALUE, 'w:textDirection'], + 'gridSpan' => [self::READ_VALUE, 'w:gridSpan'], + 'vMerge' => [self::READ_VALUE, 'w:vMerge'], + 'bgColor' => [self::READ_VALUE, 'w:shd', 'w:fill'], + ]; return $this->readStyleDefs($xmlReader, $domNode, $styleDefs); } /** - * Returns the first child element found + * Returns the first child element found. + * + * @param null|array|string $elements * - * @param XMLReader $xmlReader - * @param \DOMElement|null $parentNode - * @param string|array|null $elements - * @return string|null + * @return null|string */ - private function findPossibleElement(XMLReader $xmlReader, \DOMElement $parentNode = null, $elements = null) + private function findPossibleElement(XMLReader $xmlReader, ?DOMElement $parentNode = null, $elements = null) { if (is_array($elements)) { //if element is an array, we take the first element that exists in the XML @@ -607,14 +589,13 @@ private function findPossibleElement(XMLReader $xmlReader, \DOMElement $parentNo } /** - * Returns the first attribute found + * Returns the first attribute found. * - * @param XMLReader $xmlReader - * @param \DOMElement $node - * @param string|array $attributes - * @return string|null + * @param array|string $attributes + * + * @return null|string */ - private function findPossibleAttribute(XMLReader $xmlReader, \DOMElement $node, $attributes) + private function findPossibleAttribute(XMLReader $xmlReader, DOMElement $node, $attributes) { //if attribute is an array, we take the first attribute that exists in the XML if (is_array($attributes)) { @@ -631,20 +612,21 @@ private function findPossibleAttribute(XMLReader $xmlReader, \DOMElement $node, } /** - * Read style definition + * Read style definition. * - * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader - * @param \DOMElement $parentNode + * @param DOMElement $parentNode * @param array $styleDefs + * * @ignoreScrutinizerPatch + * * @return array */ - protected function readStyleDefs(XMLReader $xmlReader, \DOMElement $parentNode = null, $styleDefs = array()) + protected function readStyleDefs(XMLReader $xmlReader, ?DOMElement $parentNode = null, $styleDefs = []) { - $styles = array(); + $styles = []; foreach ($styleDefs as $styleProp => $styleVal) { - list($method, $element, $attribute, $expected) = array_pad($styleVal, 4, null); + [$method, $element, $attribute, $expected] = array_pad($styleVal, 4, null); $element = $this->findPossibleElement($xmlReader, $parentNode, $element); if ($element === null) { @@ -671,12 +653,15 @@ protected function readStyleDefs(XMLReader $xmlReader, \DOMElement $parentNode = } /** - * Return style definition based on conversion method + * Return style definition based on conversion method. * * @param string $method + * * @ignoreScrutinizerPatch - * @param string|null $attributeValue + * + * @param null|string $attributeValue * @param mixed $expected + * * @return mixed */ private function readStyleDef($method, $attributeValue, $expected) @@ -697,10 +682,12 @@ private function readStyleDef($method, $attributeValue, $expected) } /** - * Parses the value of the on/off value, null is considered true as it means the w:val attribute was not present + * Parses the value of the on/off value, null is considered true as it means the w:val attribute was not present. * * @see http://www.datypic.com/sc/ooxml/t-w_ST_OnOff.html + * * @param string $value + * * @return bool */ private function isOn($value = null) @@ -709,17 +696,18 @@ private function isOn($value = null) } /** - * Returns the target of image, object, or link as stored in ::readMainRels + * Returns the target of image, object, or link as stored in ::readMainRels. * * @param string $docPart * @param string $rId - * @return string|null + * + * @return null|string */ private function getMediaTarget($docPart, $rId) { $target = null; - if (isset($this->rels[$docPart]) && isset($this->rels[$docPart][$rId])) { + if (isset($this->rels[$docPart], $this->rels[$docPart][$rId])) { $target = $this->rels[$docPart][$rId]['target']; } @@ -727,17 +715,18 @@ private function getMediaTarget($docPart, $rId) } /** - * Returns the target mode + * Returns the target mode. * * @param string $docPart * @param string $rId - * @return string|null + * + * @return null|string */ private function getTargetMode($docPart, $rId) { $mode = null; - if (isset($this->rels[$docPart]) && isset($this->rels[$docPart][$rId])) { + if (isset($this->rels[$docPart], $this->rels[$docPart][$rId])) { $mode = $this->rels[$docPart][$rId]['targetMode']; } diff --git a/src/PhpWord/Reader/Word2007/DocPropsApp.php b/src/PhpWord/Reader/Word2007/DocPropsApp.php index decc510390..9d6f3cbbe9 100644 --- a/src/PhpWord/Reader/Word2007/DocPropsApp.php +++ b/src/PhpWord/Reader/Word2007/DocPropsApp.php @@ -11,30 +11,30 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Reader\Word2007; /** - * Extended properties reader + * Extended properties reader. * * @since 0.10.0 */ class DocPropsApp extends DocPropsCore { /** - * Property mapping + * Property mapping. * * @var array */ - protected $mapping = array('Company' => 'setCompany', 'Manager' => 'setManager'); + protected $mapping = ['Company' => 'setCompany', 'Manager' => 'setManager']; /** - * Callback functions + * Callback functions. * * @var array */ - protected $callbacks = array(); + protected $callbacks = []; } diff --git a/src/PhpWord/Reader/Word2007/DocPropsCore.php b/src/PhpWord/Reader/Word2007/DocPropsCore.php index d241df184a..d3eac27de6 100644 --- a/src/PhpWord/Reader/Word2007/DocPropsCore.php +++ b/src/PhpWord/Reader/Word2007/DocPropsCore.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,42 +21,40 @@ use PhpOffice\PhpWord\Shared\XMLReader; /** - * Core properties reader + * Core properties reader. * * @since 0.10.0 */ class DocPropsCore extends AbstractPart { /** - * Property mapping + * Property mapping. * * @var array */ - protected $mapping = array( - 'dc:creator' => 'setCreator', - 'dc:title' => 'setTitle', - 'dc:description' => 'setDescription', - 'dc:subject' => 'setSubject', - 'cp:keywords' => 'setKeywords', - 'cp:category' => 'setCategory', + protected $mapping = [ + 'dc:creator' => 'setCreator', + 'dc:title' => 'setTitle', + 'dc:description' => 'setDescription', + 'dc:subject' => 'setSubject', + 'cp:keywords' => 'setKeywords', + 'cp:category' => 'setCategory', 'cp:lastModifiedBy' => 'setLastModifiedBy', - 'dcterms:created' => 'setCreated', - 'dcterms:modified' => 'setModified', - ); + 'dcterms:created' => 'setCreated', + 'dcterms:modified' => 'setModified', + ]; /** - * Callback functions + * Callback functions. * * @var array */ - protected $callbacks = array('dcterms:created' => 'strtotime', 'dcterms:modified' => 'strtotime'); + protected $callbacks = ['dcterms:created' => 'strtotime', 'dcterms:modified' => 'strtotime']; /** * Read core/extended document properties. - * - * @param \PhpOffice\PhpWord\PhpWord $phpWord */ - public function read(PhpWord $phpWord) + public function read(PhpWord $phpWord): void { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); diff --git a/src/PhpWord/Reader/Word2007/DocPropsCustom.php b/src/PhpWord/Reader/Word2007/DocPropsCustom.php index feb41006c9..69cd551c79 100644 --- a/src/PhpWord/Reader/Word2007/DocPropsCustom.php +++ b/src/PhpWord/Reader/Word2007/DocPropsCustom.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -22,7 +22,7 @@ use PhpOffice\PhpWord\Shared\XMLReader; /** - * Custom properties reader + * Custom properties reader. * * @since 0.11.0 */ @@ -30,10 +30,8 @@ class DocPropsCustom extends AbstractPart { /** * Read custom document properties. - * - * @param \PhpOffice\PhpWord\PhpWord $phpWord */ - public function read(PhpWord $phpWord) + public function read(PhpWord $phpWord): void { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); diff --git a/src/PhpWord/Reader/Word2007/Document.php b/src/PhpWord/Reader/Word2007/Document.php index 13a92e4786..da42bddc9e 100644 --- a/src/PhpWord/Reader/Word2007/Document.php +++ b/src/PhpWord/Reader/Word2007/Document.php @@ -11,26 +11,28 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Reader\Word2007; +use DOMElement; use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Shared\XMLReader; /** - * Document reader + * Document reader. * * @since 0.10.0 + * * @SuppressWarnings(PHPMD.UnusedPrivateMethod) For readWPNode */ class Document extends AbstractPart { /** - * PhpWord object + * PhpWord object. * * @var \PhpOffice\PhpWord\PhpWord */ @@ -38,15 +40,13 @@ class Document extends AbstractPart /** * Read document.xml. - * - * @param \PhpOffice\PhpWord\PhpWord $phpWord */ - public function read(PhpWord $phpWord) + public function read(PhpWord $phpWord): void { $this->phpWord = $phpWord; $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); - $readMethods = array('w:p' => 'readWPNode', 'w:tbl' => 'readTable', 'w:sectPr' => 'readWSectPrNode'); + $readMethods = ['w:p' => 'readWPNode', 'w:tbl' => 'readTable', 'w:sectPr' => 'readWSectPrNode']; $nodes = $xmlReader->getElements('w:body/*'); if ($nodes->length > 0) { @@ -64,16 +64,15 @@ public function read(PhpWord $phpWord) * Read header footer. * * @param array $settings - * @param \PhpOffice\PhpWord\Element\Section &$section */ - private function readHeaderFooter($settings, Section &$section) + private function readHeaderFooter($settings, Section &$section): void { - $readMethods = array('w:p' => 'readParagraph', 'w:tbl' => 'readTable'); + $readMethods = ['w:p' => 'readParagraph', 'w:tbl' => 'readTable']; if (is_array($settings) && isset($settings['hf'])) { foreach ($settings['hf'] as $rId => $hfSetting) { if (isset($this->rels['document'][$rId])) { - list($hfType, $xmlFile, $docPart) = array_values($this->rels['document'][$rId]); + [$hfType, $xmlFile, $docPart] = array_values($this->rels['document'][$rId]); $addMethod = "add{$hfType}"; $hfObject = $section->$addMethod($hfSetting['type']); @@ -95,31 +94,30 @@ private function readHeaderFooter($settings, Section &$section) } /** - * Read w:sectPr + * Read w:sectPr. * - * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader - * @param \DOMElement $domNode * @ignoreScrutinizerPatch + * * @return array */ - private function readSectionStyle(XMLReader $xmlReader, \DOMElement $domNode) + private function readSectionStyle(XMLReader $xmlReader, DOMElement $domNode) { - $styleDefs = array( - 'breakType' => array(self::READ_VALUE, 'w:type'), - 'vAlign' => array(self::READ_VALUE, 'w:vAlign'), - 'pageSizeW' => array(self::READ_VALUE, 'w:pgSz', 'w:w'), - 'pageSizeH' => array(self::READ_VALUE, 'w:pgSz', 'w:h'), - 'orientation' => array(self::READ_VALUE, 'w:pgSz', 'w:orient'), - 'colsNum' => array(self::READ_VALUE, 'w:cols', 'w:num'), - 'colsSpace' => array(self::READ_VALUE, 'w:cols', 'w:space'), - 'marginTop' => array(self::READ_VALUE, 'w:pgMar', 'w:top'), - 'marginLeft' => array(self::READ_VALUE, 'w:pgMar', 'w:left'), - 'marginBottom' => array(self::READ_VALUE, 'w:pgMar', 'w:bottom'), - 'marginRight' => array(self::READ_VALUE, 'w:pgMar', 'w:right'), - 'headerHeight' => array(self::READ_VALUE, 'w:pgMar', 'w:header'), - 'footerHeight' => array(self::READ_VALUE, 'w:pgMar', 'w:footer'), - 'gutter' => array(self::READ_VALUE, 'w:pgMar', 'w:gutter'), - ); + $styleDefs = [ + 'breakType' => [self::READ_VALUE, 'w:type'], + 'vAlign' => [self::READ_VALUE, 'w:vAlign'], + 'pageSizeW' => [self::READ_VALUE, 'w:pgSz', 'w:w'], + 'pageSizeH' => [self::READ_VALUE, 'w:pgSz', 'w:h'], + 'orientation' => [self::READ_VALUE, 'w:pgSz', 'w:orient'], + 'colsNum' => [self::READ_VALUE, 'w:cols', 'w:num'], + 'colsSpace' => [self::READ_VALUE, 'w:cols', 'w:space'], + 'marginTop' => [self::READ_VALUE, 'w:pgMar', 'w:top'], + 'marginLeft' => [self::READ_VALUE, 'w:pgMar', 'w:left'], + 'marginBottom' => [self::READ_VALUE, 'w:pgMar', 'w:bottom'], + 'marginRight' => [self::READ_VALUE, 'w:pgMar', 'w:right'], + 'headerHeight' => [self::READ_VALUE, 'w:pgMar', 'w:header'], + 'footerHeight' => [self::READ_VALUE, 'w:pgMar', 'w:footer'], + 'gutter' => [self::READ_VALUE, 'w:pgMar', 'w:gutter'], + ]; $styles = $this->readStyleDefs($xmlReader, $domNode, $styleDefs); // Header and footer @@ -128,10 +126,10 @@ private function readSectionStyle(XMLReader $xmlReader, \DOMElement $domNode) foreach ($nodes as $node) { if ($node->nodeName == 'w:headerReference' || $node->nodeName == 'w:footerReference') { $id = $xmlReader->getAttribute('r:id', $node); - $styles['hf'][$id] = array( + $styles['hf'][$id] = [ 'method' => str_replace('w:', '', str_replace('Reference', '', $node->nodeName)), - 'type' => $xmlReader->getAttribute('w:type', $node), - ); + 'type' => $xmlReader->getAttribute('w:type', $node), + ]; } } @@ -141,13 +139,9 @@ private function readSectionStyle(XMLReader $xmlReader, \DOMElement $domNode) /** * Read w:p node. * - * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader - * @param \DOMElement $node - * @param \PhpOffice\PhpWord\Element\Section &$section - * * @todo */ - private function readWPNode(XMLReader $xmlReader, \DOMElement $node, Section &$section) + private function readWPNode(XMLReader $xmlReader, DOMElement $node, Section &$section): void { // Page break if ($xmlReader->getAttribute('w:type', $node, 'w:r/w:br') == 'page') { @@ -169,12 +163,8 @@ private function readWPNode(XMLReader $xmlReader, \DOMElement $node, Section &$s /** * Read w:sectPr node. - * - * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader - * @param \DOMElement $node - * @param \PhpOffice\PhpWord\Element\Section &$section */ - private function readWSectPrNode(XMLReader $xmlReader, \DOMElement $node, Section &$section) + private function readWSectPrNode(XMLReader $xmlReader, DOMElement $node, Section &$section): void { $style = $this->readSectionStyle($xmlReader, $node); $section->setStyle($style); diff --git a/src/PhpWord/Reader/Word2007/Endnotes.php b/src/PhpWord/Reader/Word2007/Endnotes.php index aa8b65d750..0c6b18db37 100644 --- a/src/PhpWord/Reader/Word2007/Endnotes.php +++ b/src/PhpWord/Reader/Word2007/Endnotes.php @@ -11,28 +11,28 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Reader\Word2007; /** - * Endnotes reader + * Endnotes reader. * * @since 0.10.0 */ class Endnotes extends Footnotes { /** - * Collection name + * Collection name. * * @var string */ protected $collection = 'endnotes'; /** - * Element name + * Element name. * * @var string */ diff --git a/src/PhpWord/Reader/Word2007/Footnotes.php b/src/PhpWord/Reader/Word2007/Footnotes.php index a8829d0bad..d40af195e3 100644 --- a/src/PhpWord/Reader/Word2007/Footnotes.php +++ b/src/PhpWord/Reader/Word2007/Footnotes.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,21 +21,21 @@ use PhpOffice\PhpWord\Shared\XMLReader; /** - * Footnotes reader + * Footnotes reader. * * @since 0.10.0 */ class Footnotes extends AbstractPart { /** - * Collection name footnotes|endnotes + * Collection name footnotes|endnotes. * * @var string */ protected $collection = 'footnotes'; /** - * Element name footnote|endnote + * Element name footnote|endnote. * * @var string */ @@ -43,10 +43,8 @@ class Footnotes extends AbstractPart /** * Read (footnotes|endnotes).xml. - * - * @param \PhpOffice\PhpWord\PhpWord $phpWord */ - public function read(PhpWord $phpWord) + public function read(PhpWord $phpWord): void { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); @@ -58,7 +56,7 @@ public function read(PhpWord $phpWord) // Avoid w:type "separator" and "continuationSeparator" // Only look for or without w:type attribute, or with w:type = normal - if ((is_null($type) || $type === 'normal')) { + if ((null === $type || $type === 'normal')) { $element = $this->getElement($phpWord, $id); if ($element !== null) { $pNodes = $xmlReader->getElements('w:p/*', $node); @@ -74,11 +72,11 @@ public function read(PhpWord $phpWord) } /** - * Searches for the element with the given relationId + * Searches for the element with the given relationId. * - * @param PhpWord $phpWord * @param int $relationId - * @return \PhpOffice\PhpWord\Element\AbstractContainer|null + * + * @return null|\PhpOffice\PhpWord\Element\AbstractContainer */ private function getElement(PhpWord $phpWord, $relationId) { diff --git a/src/PhpWord/Reader/Word2007/Numbering.php b/src/PhpWord/Reader/Word2007/Numbering.php index dea8f3ee62..4ae7a828bc 100644 --- a/src/PhpWord/Reader/Word2007/Numbering.php +++ b/src/PhpWord/Reader/Word2007/Numbering.php @@ -11,17 +11,18 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Reader\Word2007; +use DOMElement; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Shared\XMLReader; /** - * Numbering reader + * Numbering reader. * * @since 0.10.0 */ @@ -29,13 +30,11 @@ class Numbering extends AbstractPart { /** * Read numbering.xml. - * - * @param \PhpOffice\PhpWord\PhpWord $phpWord */ - public function read(PhpWord $phpWord) + public function read(PhpWord $phpWord): void { - $abstracts = array(); - $numberings = array(); + $abstracts = []; + $numberings = []; $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); @@ -44,17 +43,19 @@ public function read(PhpWord $phpWord) if ($nodes->length > 0) { foreach ($nodes as $node) { $abstractId = $xmlReader->getAttribute('w:abstractNumId', $node); - $abstracts[$abstractId] = array('levels' => array()); + $abstracts[$abstractId] = ['levels' => []]; $abstract = &$abstracts[$abstractId]; $subnodes = $xmlReader->getElements('*', $node); foreach ($subnodes as $subnode) { switch ($subnode->nodeName) { case 'w:multiLevelType': $abstract['type'] = $xmlReader->getAttribute('w:val', $subnode); + break; case 'w:lvl': $levelId = $xmlReader->getAttribute('w:ilvl', $subnode); $abstract['levels'][$levelId] = $this->readLevel($xmlReader, $subnode, $levelId); + break; } } @@ -87,16 +88,15 @@ public function read(PhpWord $phpWord) } /** - * Read numbering level definition from w:abstractNum and w:num + * Read numbering level definition from w:abstractNum and w:num. * - * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader - * @param \DOMElement $subnode * @param int $levelId + * * @return array */ - private function readLevel(XMLReader $xmlReader, \DOMElement $subnode, $levelId) + private function readLevel(XMLReader $xmlReader, DOMElement $subnode, $levelId) { - $level = array(); + $level = []; $level['level'] = $levelId; $level['start'] = $xmlReader->getAttribute('w:val', $subnode, 'w:start'); @@ -112,7 +112,7 @@ private function readLevel(XMLReader $xmlReader, \DOMElement $subnode, $levelId) $level['hint'] = $xmlReader->getAttribute('w:hint', $subnode, 'w:rPr/w:rFonts'); foreach ($level as $key => $value) { - if (is_null($value)) { + if (null === $value) { unset($level[$key]); } } diff --git a/src/PhpWord/Reader/Word2007/Settings.php b/src/PhpWord/Reader/Word2007/Settings.php index 0a59e0454d..63578595f5 100644 --- a/src/PhpWord/Reader/Word2007/Settings.php +++ b/src/PhpWord/Reader/Word2007/Settings.php @@ -11,25 +11,26 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Reader\Word2007; +use DOMElement; use PhpOffice\PhpWord\ComplexType\TrackChangesView; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Shared\XMLReader; use PhpOffice\PhpWord\Style\Language; /** - * Settings reader + * Settings reader. * * @since 0.14.0 */ class Settings extends AbstractPart { - private static $booleanProperties = array( + private static $booleanProperties = [ 'mirrorMargins', 'hideSpellingErrors', 'hideGrammaticalErrors', @@ -40,14 +41,12 @@ class Settings extends AbstractPart 'updateFields', 'autoHyphenation', 'doNotHyphenateCaps', - ); + ]; /** * Read settings.xml. - * - * @param \PhpOffice\PhpWord\PhpWord $phpWord */ - public function read(PhpWord $phpWord) + public function read(PhpWord $phpWord): void { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); @@ -77,13 +76,9 @@ public function read(PhpWord $phpWord) } /** - * Sets the document Language - * - * @param XMLReader $xmlReader - * @param PhpWord $phpWord - * @param \DOMElement $node + * Sets the document Language. */ - protected function setThemeFontLang(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) + protected function setThemeFontLang(XMLReader $xmlReader, PhpWord $phpWord, DOMElement $node): void { $val = $xmlReader->getAttribute('w:val', $node); $eastAsia = $xmlReader->getAttribute('w:eastAsia', $node); @@ -98,13 +93,9 @@ protected function setThemeFontLang(XMLReader $xmlReader, PhpWord $phpWord, \DOM } /** - * Sets the document protection - * - * @param XMLReader $xmlReader - * @param PhpWord $phpWord - * @param \DOMElement $node + * Sets the document protection. */ - protected function setDocumentProtection(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) + protected function setDocumentProtection(XMLReader $xmlReader, PhpWord $phpWord, DOMElement $node): void { $documentProtection = $phpWord->getSettings()->getDocumentProtection(); @@ -115,13 +106,9 @@ protected function setDocumentProtection(XMLReader $xmlReader, PhpWord $phpWord, } /** - * Sets the proof state - * - * @param XMLReader $xmlReader - * @param PhpWord $phpWord - * @param \DOMElement $node + * Sets the proof state. */ - protected function setProofState(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) + protected function setProofState(XMLReader $xmlReader, PhpWord $phpWord, DOMElement $node): void { $proofState = $phpWord->getSettings()->getProofState(); @@ -137,13 +124,9 @@ protected function setProofState(XMLReader $xmlReader, PhpWord $phpWord, \DOMEle } /** - * Sets the proof state - * - * @param XMLReader $xmlReader - * @param PhpWord $phpWord - * @param \DOMElement $node + * Sets the proof state. */ - protected function setZoom(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) + protected function setZoom(XMLReader $xmlReader, PhpWord $phpWord, DOMElement $node): void { $percent = $xmlReader->getAttribute('w:percent', $node); $val = $xmlReader->getAttribute('w:val', $node); @@ -154,13 +137,9 @@ protected function setZoom(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $ } /** - * Set the Revision view - * - * @param XMLReader $xmlReader - * @param PhpWord $phpWord - * @param \DOMElement $node + * Set the Revision view. */ - protected function setRevisionView(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) + protected function setRevisionView(XMLReader $xmlReader, PhpWord $phpWord, DOMElement $node): void { $revisionView = new TrackChangesView(); $revisionView->setMarkup(filter_var($xmlReader->getAttribute('w:markup', $node), FILTER_VALIDATE_BOOLEAN)); @@ -171,12 +150,7 @@ protected function setRevisionView(XMLReader $xmlReader, PhpWord $phpWord, \DOME $phpWord->getSettings()->setRevisionView($revisionView); } - /** - * @param XMLReader $xmlReader - * @param PhpWord $phpWord - * @param \DOMElement $node - */ - protected function setConsecutiveHyphenLimit(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) + protected function setConsecutiveHyphenLimit(XMLReader $xmlReader, PhpWord $phpWord, DOMElement $node): void { $value = $xmlReader->getAttribute('w:val', $node); @@ -185,12 +159,7 @@ protected function setConsecutiveHyphenLimit(XMLReader $xmlReader, PhpWord $phpW } } - /** - * @param XMLReader $xmlReader - * @param PhpWord $phpWord - * @param \DOMElement $node - */ - protected function setHyphenationZone(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) + protected function setHyphenationZone(XMLReader $xmlReader, PhpWord $phpWord, DOMElement $node): void { $value = $xmlReader->getAttribute('w:val', $node); diff --git a/src/PhpWord/Reader/Word2007/Styles.php b/src/PhpWord/Reader/Word2007/Styles.php index 37ce4909af..4566398ad2 100644 --- a/src/PhpWord/Reader/Word2007/Styles.php +++ b/src/PhpWord/Reader/Word2007/Styles.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -22,7 +22,7 @@ use PhpOffice\PhpWord\Style\Language; /** - * Styles reader + * Styles reader. * * @since 0.10.0 */ @@ -30,10 +30,8 @@ class Styles extends AbstractPart { /** * Read styles.xml. - * - * @param \PhpOffice\PhpWord\PhpWord $phpWord */ - public function read(PhpWord $phpWord) + public function read(PhpWord $phpWord): void { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); @@ -65,10 +63,10 @@ public function read(PhpWord $phpWord) foreach ($nodes as $node) { $type = $xmlReader->getAttribute('w:type', $node); $name = $xmlReader->getAttribute('w:val', $node, 'w:name'); - if (is_null($name)) { + if (null === $name) { $name = $xmlReader->getAttribute('w:styleId', $node); } - $headingMatches = array(); + $headingMatches = []; preg_match('/Heading\s*(\d)/i', $name, $headingMatches); // $default = ($xmlReader->getAttribute('w:default', $node) == 1); switch ($type) { @@ -86,18 +84,21 @@ public function read(PhpWord $phpWord) $phpWord->addFontStyle($name, $fontStyle, $paragraphStyle); } } + break; case 'character': $fontStyle = $this->readFontStyle($xmlReader, $node); if (!empty($fontStyle)) { $phpWord->addFontStyle($name, $fontStyle); } + break; case 'table': $tStyle = $this->readTableStyle($xmlReader, $node); if (!empty($tStyle)) { $phpWord->addTableStyle($name, $tStyle); } + break; } } diff --git a/src/PhpWord/Settings.php b/src/PhpWord/Settings.php index 457156aacc..6664770e96 100644 --- a/src/PhpWord/Settings.php +++ b/src/PhpWord/Settings.php @@ -11,21 +11,21 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord; /** - * PHPWord settings class + * PHPWord settings class. * * @since 0.8.0 */ class Settings { /** - * Zip libraries + * Zip libraries. * * @const string */ @@ -34,7 +34,7 @@ class Settings const OLD_LIB = 'PhpOffice\\PhpWord\\Shared\\ZipArchive'; // @deprecated 0.11 /** - * PDF rendering libraries + * PDF rendering libraries. * * @const string */ @@ -43,7 +43,7 @@ class Settings const PDF_RENDERER_MPDF = 'MPDF'; /** - * Measurement units multiplication factor + * Measurement units multiplication factor. * * Applied to: * - Section: margins, header/footer height, gutter, column spacing @@ -61,7 +61,7 @@ class Settings const UNIT_PICA = 'pica'; // = 1/6 inch = 12 points /** - * Default font settings + * Default font settings. * * OOXML defined font size values in halfpoints, i.e. twice of what PhpWord * use, and the conversion will be conducted during XML writing. @@ -73,55 +73,57 @@ class Settings const DEFAULT_PAPER = 'A4'; /** - * Compatibility option for XMLWriter + * Compatibility option for XMLWriter. * * @var bool */ private static $xmlWriterCompatibility = true; /** - * Name of the class used for Zip file management + * Name of the class used for Zip file management. * * @var string */ private static $zipClass = self::ZIPARCHIVE; /** - * Name of the external Library used for rendering PDF files + * Name of the external Library used for rendering PDF files. * * @var string */ - private static $pdfRendererName = null; + private static $pdfRendererName; /** - * Directory Path to the external Library used for rendering PDF files + * Directory Path to the external Library used for rendering PDF files. * * @var string */ - private static $pdfRendererPath = null; + private static $pdfRendererPath; /** - * Measurement unit + * Measurement unit. * - * @var int|float + * @var float|int */ private static $measurementUnit = self::UNIT_TWIP; /** - * Default font name + * Default font name. * * @var string */ private static $defaultFontName = self::DEFAULT_FONT_NAME; /** - * Default font size + * Default font size. + * * @var int */ private static $defaultFontSize = self::DEFAULT_FONT_SIZE; /** - * Default paper + * Default paper. + * * @var string */ private static $defaultPaper = self::DEFAULT_PAPER; @@ -142,7 +144,7 @@ class Settings private static $outputEscapingEnabled = false; /** - * Return the compatibility option used by the XMLWriter + * Return the compatibility option used by the XMLWriter. * * @return bool Compatibility */ @@ -152,11 +154,12 @@ public static function hasCompatibility() } /** - * Set the compatibility option used by the XMLWriter + * Set the compatibility option used by the XMLWriter. * * This sets the setIndent and setIndentString for better compatibility * * @param bool $compatibility + * * @return bool */ public static function setCompatibility($compatibility) @@ -168,7 +171,7 @@ public static function setCompatibility($compatibility) } /** - * Get zip handler class + * Get zip handler class. * * @return string */ @@ -178,14 +181,15 @@ public static function getZipClass() } /** - * Set zip handler class + * Set zip handler class. * * @param string $zipClass + * * @return bool */ public static function setZipClass($zipClass) { - if (in_array($zipClass, array(self::PCLZIP, self::ZIPARCHIVE, self::OLD_LIB))) { + if (in_array($zipClass, [self::PCLZIP, self::ZIPARCHIVE, self::OLD_LIB])) { self::$zipClass = $zipClass; return true; @@ -195,10 +199,11 @@ public static function setZipClass($zipClass) } /** - * Set details of the external library for rendering PDF files + * Set details of the external library for rendering PDF files. * * @param string $libraryName * @param string $libraryBaseDir + * * @return bool Success or failure */ public static function setPdfRenderer($libraryName, $libraryBaseDir) @@ -221,14 +226,15 @@ public static function getPdfRendererName() } /** - * Identify the external library to use for rendering PDF files + * Identify the external library to use for rendering PDF files. * * @param string $libraryName + * * @return bool */ public static function setPdfRendererName($libraryName) { - $pdfRenderers = array(self::PDF_RENDERER_DOMPDF, self::PDF_RENDERER_TCPDF, self::PDF_RENDERER_MPDF); + $pdfRenderers = [self::PDF_RENDERER_DOMPDF, self::PDF_RENDERER_TCPDF, self::PDF_RENDERER_MPDF]; if (!in_array($libraryName, $pdfRenderers)) { return false; } @@ -248,9 +254,10 @@ public static function getPdfRendererPath() } /** - * Location of external library to use for rendering PDF files + * Location of external library to use for rendering PDF files. * * @param string $libraryBaseDir Directory path to the library's base folder + * * @return bool Success or failure */ public static function setPdfRendererPath($libraryBaseDir) @@ -264,7 +271,7 @@ public static function setPdfRendererPath($libraryBaseDir) } /** - * Get measurement unit + * Get measurement unit. * * @return string */ @@ -274,15 +281,16 @@ public static function getMeasurementUnit() } /** - * Set measurement unit + * Set measurement unit. * * @param string $value + * * @return bool */ public static function setMeasurementUnit($value) { - $units = array(self::UNIT_TWIP, self::UNIT_CM, self::UNIT_MM, self::UNIT_INCH, - self::UNIT_POINT, self::UNIT_PICA, ); + $units = [self::UNIT_TWIP, self::UNIT_CM, self::UNIT_MM, self::UNIT_INCH, + self::UNIT_POINT, self::UNIT_PICA, ]; if (!in_array($value, $units)) { return false; } @@ -298,7 +306,7 @@ public static function setMeasurementUnit($value) * * @param string $tempDir The user defined path to temporary directory */ - public static function setTempDir($tempDir) + public static function setTempDir($tempDir): void { self::$tempDir = $tempDir; } @@ -336,13 +344,13 @@ public static function isOutputEscapingEnabled() * * @param bool $outputEscapingEnabled */ - public static function setOutputEscapingEnabled($outputEscapingEnabled) + public static function setOutputEscapingEnabled($outputEscapingEnabled): void { self::$outputEscapingEnabled = $outputEscapingEnabled; } /** - * Get default font name + * Get default font name. * * @return string */ @@ -352,9 +360,10 @@ public static function getDefaultFontName() } /** - * Set default font name + * Set default font name. * * @param string $value + * * @return bool */ public static function setDefaultFontName($value) @@ -369,7 +378,7 @@ public static function setDefaultFontName($value) } /** - * Get default font size + * Get default font size. * * @return int */ @@ -379,9 +388,10 @@ public static function getDefaultFontSize() } /** - * Set default font size + * Set default font size. * * @param int $value + * * @return bool */ public static function setDefaultFontSize($value) @@ -397,9 +407,10 @@ public static function setDefaultFontSize($value) } /** - * Load setting from phpword.yml or phpword.yml.dist + * Load setting from phpword.yml or phpword.yml.dist. * * @param string $filename + * * @return array */ public static function loadConfig($filename = null) @@ -408,28 +419,29 @@ public static function loadConfig($filename = null) $configFile = null; $configPath = __DIR__ . '/../../'; if ($filename !== null) { - $files = array($filename); + $files = [$filename]; } else { - $files = array("{$configPath}phpword.ini", "{$configPath}phpword.ini.dist"); + $files = ["{$configPath}phpword.ini", "{$configPath}phpword.ini.dist"]; } foreach ($files as $file) { if (file_exists($file)) { $configFile = realpath($file); + break; } } // Parse config file - $config = array(); + $config = []; if ($configFile !== null) { $config = @parse_ini_file($configFile); if ($config === false) { - return array(); + return []; } } // Set config value - $appliedConfig = array(); + $appliedConfig = []; foreach ($config as $key => $value) { $method = "set{$key}"; if (method_exists(__CLASS__, $method)) { @@ -442,7 +454,7 @@ public static function loadConfig($filename = null) } /** - * Get default paper + * Get default paper. * * @return string */ @@ -452,9 +464,10 @@ public static function getDefaultPaper() } /** - * Set default paper + * Set default paper. * * @param string $value + * * @return bool */ public static function setDefaultPaper($value) @@ -469,7 +482,7 @@ public static function setDefaultPaper($value) } /** - * Return the compatibility option used by the XMLWriter + * Return the compatibility option used by the XMLWriter. * * @deprecated 0.10.0 * diff --git a/src/PhpWord/Shared/AbstractEnum.php b/src/PhpWord/Shared/AbstractEnum.php index f2375d876e..e79f4b244e 100644 --- a/src/PhpWord/Shared/AbstractEnum.php +++ b/src/PhpWord/Shared/AbstractEnum.php @@ -11,24 +11,27 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Shared; +use InvalidArgumentException; +use ReflectionClass; + abstract class AbstractEnum { - private static $constCacheArray = null; + private static $constCacheArray; private static function getConstants() { if (self::$constCacheArray == null) { - self::$constCacheArray = array(); + self::$constCacheArray = []; } - $calledClass = get_called_class(); + $calledClass = static::class; if (!array_key_exists($calledClass, self::$constCacheArray)) { - $reflect = new \ReflectionClass($calledClass); + $reflect = new ReflectionClass($calledClass); self::$constCacheArray[$calledClass] = $reflect->getConstants(); } @@ -36,7 +39,7 @@ private static function getConstants() } /** - * Returns all values for this enum + * Returns all values for this enum. * * @return array */ @@ -46,9 +49,10 @@ public static function values() } /** - * Returns true the value is valid for this enum + * Returns true the value is valid for this enum. * * @param string $value + * * @return bool true if value is valid */ public static function isValid($value) @@ -59,17 +63,17 @@ public static function isValid($value) } /** - * Validates that the value passed is a valid value + * Validates that the value passed is a valid value. * * @param string $value - * @throws \InvalidArgumentException if the value passed is not valid for this enum */ - public static function validate($value) + public static function validate($value): void { if (!self::isValid($value)) { - $calledClass = get_called_class(); + $calledClass = static::class; $values = array_values(self::getConstants()); - throw new \InvalidArgumentException("$value is not a valid value for $calledClass, possible values are " . implode(', ', $values)); + + throw new InvalidArgumentException("$value is not a valid value for $calledClass, possible values are " . implode(', ', $values)); } } } diff --git a/src/PhpWord/Shared/Converter.php b/src/PhpWord/Shared/Converter.php index 05755ef796..53891f5292 100644 --- a/src/PhpWord/Shared/Converter.php +++ b/src/PhpWord/Shared/Converter.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Shared; /** - * Common converter functions + * Common converter functions. */ class Converter { @@ -31,9 +31,10 @@ class Converter const DEGREE_TO_ANGLE = 60000; /** - * Convert centimeter to twip + * Convert centimeter to twip. * * @param float $centimeter + * * @return float */ public static function cmToTwip($centimeter = 1) @@ -42,9 +43,10 @@ public static function cmToTwip($centimeter = 1) } /** - * Convert centimeter to inch + * Convert centimeter to inch. * * @param float $centimeter + * * @return float */ public static function cmToInch($centimeter = 1) @@ -53,9 +55,10 @@ public static function cmToInch($centimeter = 1) } /** - * Convert centimeter to pixel + * Convert centimeter to pixel. * * @param float $centimeter + * * @return float */ public static function cmToPixel($centimeter = 1) @@ -64,9 +67,10 @@ public static function cmToPixel($centimeter = 1) } /** - * Convert centimeter to point + * Convert centimeter to point. * * @param float $centimeter + * * @return float */ public static function cmToPoint($centimeter = 1) @@ -75,9 +79,10 @@ public static function cmToPoint($centimeter = 1) } /** - * Convert centimeter to EMU + * Convert centimeter to EMU. * * @param float $centimeter + * * @return float */ public static function cmToEmu($centimeter = 1) @@ -86,9 +91,10 @@ public static function cmToEmu($centimeter = 1) } /** - * Convert inch to twip + * Convert inch to twip. * * @param float $inch + * * @return float */ public static function inchToTwip($inch = 1) @@ -97,9 +103,10 @@ public static function inchToTwip($inch = 1) } /** - * Convert inch to centimeter + * Convert inch to centimeter. * * @param float $inch + * * @return float */ public static function inchToCm($inch = 1) @@ -108,9 +115,10 @@ public static function inchToCm($inch = 1) } /** - * Convert inch to pixel + * Convert inch to pixel. * * @param float $inch + * * @return float */ public static function inchToPixel($inch = 1) @@ -119,9 +127,10 @@ public static function inchToPixel($inch = 1) } /** - * Convert inch to point + * Convert inch to point. * * @param float $inch + * * @return float */ public static function inchToPoint($inch = 1) @@ -130,9 +139,10 @@ public static function inchToPoint($inch = 1) } /** - * Convert inch to EMU + * Convert inch to EMU. * * @param float $inch + * * @return int */ public static function inchToEmu($inch = 1) @@ -141,9 +151,10 @@ public static function inchToEmu($inch = 1) } /** - * Convert pixel to twip + * Convert pixel to twip. * * @param float $pixel + * * @return float */ public static function pixelToTwip($pixel = 1) @@ -152,9 +163,10 @@ public static function pixelToTwip($pixel = 1) } /** - * Convert pixel to centimeter + * Convert pixel to centimeter. * * @param float $pixel + * * @return float */ public static function pixelToCm($pixel = 1) @@ -163,9 +175,10 @@ public static function pixelToCm($pixel = 1) } /** - * Convert pixel to point + * Convert pixel to point. * * @param float $pixel + * * @return float */ public static function pixelToPoint($pixel = 1) @@ -174,9 +187,10 @@ public static function pixelToPoint($pixel = 1) } /** - * Convert pixel to EMU + * Convert pixel to EMU. * * @param float $pixel + * * @return int */ public static function pixelToEmu($pixel = 1) @@ -185,9 +199,10 @@ public static function pixelToEmu($pixel = 1) } /** - * Convert point to twip unit + * Convert point to twip unit. * * @param float $point + * * @return float */ public static function pointToTwip($point = 1) @@ -196,9 +211,10 @@ public static function pointToTwip($point = 1) } /** - * Convert point to pixel + * Convert point to pixel. * * @param float $point + * * @return float */ public static function pointToPixel($point = 1) @@ -207,9 +223,10 @@ public static function pointToPixel($point = 1) } /** - * Convert point to EMU + * Convert point to EMU. * * @param float $point + * * @return float */ public static function pointToEmu($point = 1) @@ -218,9 +235,10 @@ public static function pointToEmu($point = 1) } /** - * Convert point to cm + * Convert point to cm. * * @param float $point + * * @return float */ public static function pointToCm($point = 1) @@ -229,9 +247,10 @@ public static function pointToCm($point = 1) } /** - * Convert EMU to pixel + * Convert EMU to pixel. * * @param float $emu + * * @return float */ public static function emuToPixel($emu = 1) @@ -240,9 +259,10 @@ public static function emuToPixel($emu = 1) } /** - * Convert pica to point + * Convert pica to point. * * @param float $pica + * * @return float */ public static function picaToPoint($pica = 1) @@ -251,9 +271,10 @@ public static function picaToPoint($pica = 1) } /** - * Convert degree to angle + * Convert degree to angle. * * @param float $degree + * * @return int */ public static function degreeToAngle($degree = 1) @@ -262,9 +283,10 @@ public static function degreeToAngle($degree = 1) } /** - * Convert angle to degrees + * Convert angle to degrees. * * @param float $angle + * * @return int */ public static function angleToDegree($angle = 1) @@ -273,9 +295,10 @@ public static function angleToDegree($angle = 1) } /** - * Convert colorname as string to RGB + * Convert colorname as string to RGB. * * @param string $value color name + * * @return string color as hex RGB string, or original value if unknown */ public static function stringToRgb($value) @@ -317,9 +340,10 @@ public static function stringToRgb($value) } /** - * Convert HTML hexadecimal to RGB + * Convert HTML hexadecimal to RGB. * * @param string $value HTML Color in hexadecimal + * * @return array Value in RGB */ public static function htmlToRgb($value) @@ -331,9 +355,9 @@ public static function htmlToRgb($value) } if (strlen($value) == 6) { - list($red, $green, $blue) = array($value[0] . $value[1], $value[2] . $value[3], $value[4] . $value[5]); + [$red, $green, $blue] = [$value[0] . $value[1], $value[2] . $value[3], $value[4] . $value[5]]; } elseif (strlen($value) == 3) { - list($red, $green, $blue) = array($value[0] . $value[0], $value[1] . $value[1], $value[2] . $value[2]); + [$red, $green, $blue] = [$value[0] . $value[0], $value[1] . $value[1], $value[2] . $value[2]]; } else { return false; } @@ -342,13 +366,14 @@ public static function htmlToRgb($value) $green = ctype_xdigit($green) ? hexdec($green) : 0; $blue = ctype_xdigit($blue) ? hexdec($blue) : 0; - return array($red, $green, $blue); + return [$red, $green, $blue]; } /** - * Transforms a size in CSS format (eg. 10px, 10px, ...) to points + * Transforms a size in CSS format (eg. 10px, 10px, ...) to points. * * @param string $value + * * @return float */ public static function cssToPoint($value) @@ -356,7 +381,7 @@ public static function cssToPoint($value) if ($value == '0') { return 0; } - $matches = array(); + $matches = []; if (preg_match('/^[+-]?([0-9]+\.?[0-9]*)?(px|em|ex|%|in|cm|mm|pt|pc)$/i', $value, $matches)) { $size = $matches[1]; $unit = $matches[2]; @@ -381,9 +406,10 @@ public static function cssToPoint($value) } /** - * Transforms a size in CSS format (eg. 10px, 10px, ...) to twips + * Transforms a size in CSS format (eg. 10px, 10px, ...) to twips. * * @param string $value + * * @return float */ public static function cssToTwip($value) @@ -392,9 +418,10 @@ public static function cssToTwip($value) } /** - * Transforms a size in CSS format (eg. 10px, 10px, ...) to pixel + * Transforms a size in CSS format (eg. 10px, 10px, ...) to pixel. * * @param string $value + * * @return float */ public static function cssToPixel($value) @@ -403,9 +430,10 @@ public static function cssToPixel($value) } /** - * Transforms a size in CSS format (eg. 10px, 10px, ...) to cm + * Transforms a size in CSS format (eg. 10px, 10px, ...) to cm. * * @param string $value + * * @return float */ public static function cssToCm($value) @@ -414,9 +442,10 @@ public static function cssToCm($value) } /** - * Transforms a size in CSS format (eg. 10px, 10px, ...) to emu + * Transforms a size in CSS format (eg. 10px, 10px, ...) to emu. * * @param string $value + * * @return float */ public static function cssToEmu($value) diff --git a/src/PhpWord/Shared/Drawing.php b/src/PhpWord/Shared/Drawing.php index 531ee24544..df218108d9 100644 --- a/src/PhpWord/Shared/Drawing.php +++ b/src/PhpWord/Shared/Drawing.php @@ -11,23 +11,24 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Shared; /** - * Drawing + * Drawing. */ class Drawing { const DPI_96 = 96; /** - * Convert pixels to EMU + * Convert pixels to EMU. * * @param int $pValue Value in pixels + * * @return int */ public static function pixelsToEmu($pValue = 0) @@ -36,9 +37,10 @@ public static function pixelsToEmu($pValue = 0) } /** - * Convert EMU to pixels + * Convert EMU to pixels. * * @param int $pValue Value in EMU + * * @return int */ public static function emuToPixels($pValue = 0) @@ -51,9 +53,10 @@ public static function emuToPixels($pValue = 0) } /** - * Convert pixels to points + * Convert pixels to points. * * @param int $pValue Value in pixels + * * @return float */ public static function pixelsToPoints($pValue = 0) @@ -62,9 +65,10 @@ public static function pixelsToPoints($pValue = 0) } /** - * Convert points width to centimeters + * Convert points width to centimeters. * * @param int $pValue Value in points + * * @return float */ public static function pointsToCentimeters($pValue = 0) @@ -77,9 +81,10 @@ public static function pointsToCentimeters($pValue = 0) } /** - * Convert points width to pixels + * Convert points width to pixels. * * @param int $pValue Value in points + * * @return float */ public static function pointsToPixels($pValue = 0) @@ -92,9 +97,10 @@ public static function pointsToPixels($pValue = 0) } /** - * Convert pixels to centimeters + * Convert pixels to centimeters. * * @param int $pValue Value in pixels + * * @return float */ public static function pixelsToCentimeters($pValue = 0) @@ -104,9 +110,10 @@ public static function pixelsToCentimeters($pValue = 0) } /** - * Convert centimeters width to pixels + * Convert centimeters width to pixels. * * @param int $pValue Value in centimeters + * * @return float */ public static function centimetersToPixels($pValue = 0) @@ -119,9 +126,10 @@ public static function centimetersToPixels($pValue = 0) } /** - * Convert degrees to angle + * Convert degrees to angle. * * @param int $pValue Degrees + * * @return int */ public static function degreesToAngle($pValue = 0) @@ -130,9 +138,10 @@ public static function degreesToAngle($pValue = 0) } /** - * Convert angle to degrees + * Convert angle to degrees. * * @param int $pValue Angle + * * @return int */ public static function angleToDegrees($pValue = 0) @@ -145,9 +154,10 @@ public static function angleToDegrees($pValue = 0) } /** - * Convert centimeters width to twips + * Convert centimeters width to twips. * * @param int $pValue + * * @return float */ public static function centimetersToTwips($pValue = 0) @@ -160,9 +170,10 @@ public static function centimetersToTwips($pValue = 0) } /** - * Convert twips width to centimeters + * Convert twips width to centimeters. * * @param int $pValue + * * @return float */ public static function twipsToCentimeters($pValue = 0) @@ -175,9 +186,10 @@ public static function twipsToCentimeters($pValue = 0) } /** - * Convert inches width to twips + * Convert inches width to twips. * * @param int $pValue + * * @return float */ public static function inchesToTwips($pValue = 0) @@ -190,9 +202,10 @@ public static function inchesToTwips($pValue = 0) } /** - * Convert twips width to inches + * Convert twips width to inches. * * @param int $pValue + * * @return float */ public static function twipsToInches($pValue = 0) @@ -205,9 +218,10 @@ public static function twipsToInches($pValue = 0) } /** - * Convert twips width to pixels + * Convert twips width to pixels. * * @param int $pValue + * * @return float */ public static function twipsToPixels($pValue = 0) @@ -220,9 +234,10 @@ public static function twipsToPixels($pValue = 0) } /** - * Convert HTML hexadecimal to RGB + * Convert HTML hexadecimal to RGB. * * @param string $pValue HTML Color in hexadecimal + * * @return array|false Value in RGB */ public static function htmlToRGB($pValue) @@ -232,9 +247,9 @@ public static function htmlToRGB($pValue) } if (strlen($pValue) == 6) { - list($colorR, $colorG, $colorB) = array($pValue[0] . $pValue[1], $pValue[2] . $pValue[3], $pValue[4] . $pValue[5]); + [$colorR, $colorG, $colorB] = [$pValue[0] . $pValue[1], $pValue[2] . $pValue[3], $pValue[4] . $pValue[5]]; } elseif (strlen($pValue) == 3) { - list($colorR, $colorG, $colorB) = array($pValue[0] . $pValue[0], $pValue[1] . $pValue[1], $pValue[2] . $pValue[2]); + [$colorR, $colorG, $colorB] = [$pValue[0] . $pValue[0], $pValue[1] . $pValue[1], $pValue[2] . $pValue[2]]; } else { return false; } @@ -243,6 +258,6 @@ public static function htmlToRGB($pValue) $colorG = hexdec($colorG); $colorB = hexdec($colorB); - return array($colorR, $colorG, $colorB); + return [$colorR, $colorG, $colorB]; } } diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 530074e183..d6e8a0886a 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -11,12 +11,17 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Shared; +use DOMAttr; +use DOMDocument; +use DOMNode; +use DOMXPath; +use Exception; use PhpOffice\PhpWord\Element\AbstractContainer; use PhpOffice\PhpWord\Element\Row; use PhpOffice\PhpWord\Element\Table; @@ -26,14 +31,16 @@ use PhpOffice\PhpWord\Style\Paragraph; /** - * Common Html functions + * Common Html functions. * * @SuppressWarnings(PHPMD.UnusedPrivateMethod) For readWPNode */ class Html { protected static $listIndex = 0; + protected static $xpath; + protected static $options; /** @@ -47,11 +54,8 @@ class Html * @param string $html The code to parse * @param bool $fullHTML If it's a full HTML, no need to add 'body' tag * @param bool $preserveWhiteSpace If false, the whitespaces between nodes will be removed - * @param array $options: - * + IMG_SRC_SEARCH: optional to speed up images loading from remote url when files can be found locally - * + IMG_SRC_REPLACE: optional to speed up images loading from remote url when files can be found locally */ - public static function addHtml($element, $html, $fullHTML = false, $preserveWhiteSpace = true, $options = null) + public static function addHtml($element, $html, $fullHTML = false, $preserveWhiteSpace = true, $options = null): void { /* * @todo parse $stylesheet for default styles. Should result in an array based on id, class and element, @@ -61,11 +65,11 @@ public static function addHtml($element, $html, $fullHTML = false, $preserveWhit // Preprocess: remove all line ends, decode HTML entity, // fix ampersand and angle brackets and add body tag for HTML fragments - $html = str_replace(array("\n", "\r"), '', $html); - $html = str_replace(array('<', '>', '&', '"'), array('_lt_', '_gt_', '_amp_', '_quot_'), $html); + $html = str_replace(["\n", "\r"], '', $html); + $html = str_replace(['<', '>', '&', '"'], ['_lt_', '_gt_', '_amp_', '_quot_'], $html); $html = html_entity_decode($html, ENT_QUOTES, 'UTF-8'); $html = str_replace('&', '&', $html); - $html = str_replace(array('_lt_', '_gt_', '_amp_', '_quot_'), array('<', '>', '&', '"'), $html); + $html = str_replace(['_lt_', '_gt_', '_amp_', '_quot_'], ['<', '>', '&', '"'], $html); if (false === $fullHTML) { $html = '' . $html . ''; @@ -75,10 +79,10 @@ public static function addHtml($element, $html, $fullHTML = false, $preserveWhit if (\PHP_VERSION_ID < 80000) { $orignalLibEntityLoader = libxml_disable_entity_loader(true); } - $dom = new \DOMDocument(); + $dom = new DOMDocument(); $dom->preserveWhiteSpace = $preserveWhiteSpace; $dom->loadXML($html); - self::$xpath = new \DOMXPath($dom); + self::$xpath = new DOMXPath($dom); $node = $dom->getElementsByTagName('body'); self::parseNode($node->item(0), $element); @@ -88,13 +92,14 @@ public static function addHtml($element, $html, $fullHTML = false, $preserveWhit } /** - * parse Inline style of a node + * parse Inline style of a node. * - * @param \DOMNode $node Node to check on attributes and to compile a style array + * @param DOMNode $node Node to check on attributes and to compile a style array * @param array $styles is supplied, the inline style attributes are added to the already existing style + * * @return array */ - protected static function parseInlineStyle($node, $styles = array()) + protected static function parseInlineStyle($node, $styles = []) { if (XML_ELEMENT_NODE == $node->nodeType) { $attributes = $node->attributes; // get all the attributes(eg: id, class) @@ -104,12 +109,15 @@ protected static function parseInlineStyle($node, $styles = array()) switch (strtolower($attribute->name)) { case 'style': $styles = self::parseStyle($attribute, $styles); + break; case 'align': $styles['alignment'] = self::mapAlign(trim($val)); + break; case 'lang': $styles['lang'] = $val; + break; case 'width': // tables, cells @@ -122,21 +130,25 @@ protected static function parseInlineStyle($node, $styles = array()) $styles['width'] = Converter::pixelToTwip($val); $styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::TWIP; } + break; case 'cellspacing': // tables e.g. , where "2" = 2px (always pixels) $val = (int) $val . 'px'; $styles['cellSpacing'] = Converter::cssToTwip($val); + break; case 'bgcolor': // tables, rows, cells e.g. $styles['bgColor'] = trim($val, '# '); + break; case 'valign': // cells e.g. ' . PHP_EOL; $rowCells = $rows[$i]->getCells(); $rowCellCount = count($rowCells); - for ($j = 0; $j < $rowCellCount; $j++) { + for ($j = 0; $j < $rowCellCount; ++$j) { $cellStyle = $rowCells[$j]->getStyle(); $cellBgColor = $cellStyle->getBgColor(); $cellBgColor === 'auto' && $cellBgColor = null; // auto cannot be parsed to hexadecimal number @@ -65,11 +65,11 @@ public function write() $cellVMerge = $cellStyle->getVMerge(); // If this is the first cell of the vertical merge, find out how man rows it spans if ($cellVMerge === 'restart') { - for ($k = $i + 1; $k < $rowCount; $k++) { + for ($k = $i + 1; $k < $rowCount; ++$k) { $kRowCells = $rows[$k]->getCells(); if (isset($kRowCells[$j])) { if ($kRowCells[$j]->getStyle()->getVMerge() === 'continue') { - $cellRowSpan++; + ++$cellRowSpan; } else { break; } @@ -83,14 +83,14 @@ public function write() $cellTag = $tblHeader ? 'th' : 'td'; $cellColSpanAttr = (is_numeric($cellColSpan) && ($cellColSpan > 1) ? " colspan=\"{$cellColSpan}\"" : ''); $cellRowSpanAttr = ($cellRowSpan > 1 ? " rowspan=\"{$cellRowSpan}\"" : ''); - $cellBgColorAttr = (is_null($cellBgColor) ? '' : " bgcolor=\"#{$cellBgColor}\""); - $cellFgColorAttr = (is_null($cellFgColor) ? '' : " color=\"#{$cellFgColor}\""); + $cellBgColorAttr = (null === $cellBgColor ? '' : " bgcolor=\"#{$cellBgColor}\""); + $cellFgColorAttr = (null === $cellFgColor ? '' : " color=\"#{$cellFgColor}\""); $content .= "<{$cellTag}{$cellColSpanAttr}{$cellRowSpanAttr}{$cellBgColorAttr}{$cellFgColorAttr}>" . PHP_EOL; $writer = new Container($this->parentWriter, $rowCells[$j]); $content .= $writer->write(); if ($cellRowSpan > 1) { // There shouldn't be any content in the subsequent merged cells, but lets check anyway - for ($k = $i + 1; $k < $rowCount; $k++) { + for ($k = $i + 1; $k < $rowCount; ++$k) { $kRowCells = $rows[$k]->getCells(); if (isset($kRowCells[$j])) { if ($kRowCells[$j]->getStyle()->getVMerge() === 'continue') { @@ -116,9 +116,10 @@ public function write() } /** - * Translates Table style in CSS equivalent + * Translates Table style in CSS equivalent. + * + * @param null|\PhpOffice\PhpWord\Style\Table|string $tableStyle * - * @param string|\PhpOffice\PhpWord\Style\Table|null $tableStyle * @return string */ private function getTableStyle($tableStyle = null) diff --git a/src/PhpWord/Writer/HTML/Element/Text.php b/src/PhpWord/Writer/HTML/Element/Text.php index 04d76a8327..a360f0922b 100644 --- a/src/PhpWord/Writer/HTML/Element/Text.php +++ b/src/PhpWord/Writer/HTML/Element/Text.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -25,42 +25,42 @@ use PhpOffice\PhpWord\Writer\HTML\Style\Paragraph as ParagraphStyleWriter; /** - * Text element HTML writer + * Text element HTML writer. * * @since 0.10.0 */ class Text extends AbstractElement { /** - * Text written after opening + * Text written after opening. * * @var string */ private $openingText = ''; /** - * Text written before closing + * Text written before closing. * * @var string */ private $closingText = ''; /** - * Opening tags + * Opening tags. * * @var string */ private $openingTags = ''; /** - * Closing tag + * Closing tag. * * @var string */ private $closingTags = ''; /** - * Write text + * Write text. * * @return string */ @@ -91,7 +91,7 @@ public function write() * * @param string $value */ - public function setOpeningText($value) + public function setOpeningText($value): void { $this->openingText = $value; } @@ -101,13 +101,13 @@ public function setOpeningText($value) * * @param string $value */ - public function setClosingText($value) + public function setClosingText($value): void { $this->closingText = $value; } /** - * Write opening + * Write opening. * * @return string */ @@ -129,7 +129,7 @@ protected function writeOpening() } /** - * Write ending + * Write ending. * * @return string */ @@ -154,7 +154,7 @@ protected function writeClosing() } /** - * writes the track change opening tag + * writes the track change opening tag. * * @return string the HTML, an empty string if no track change information */ @@ -172,7 +172,7 @@ private function writeTrackChangeOpening() $content .= ' array('author'=> $changed->getAuthor(), 'id' => $this->element->getElementId())); + $changedProp = ['changed' => ['author' => $changed->getAuthor(), 'id' => $this->element->getElementId()]]; if ($changed->getDate() != null) { $changedProp['changed']['date'] = $changed->getDate()->format('Y-m-d\TH:i:s\Z'); } @@ -189,7 +189,7 @@ private function writeTrackChangeOpening() } /** - * writes the track change closing tag + * writes the track change closing tag. * * @return string the HTML, an empty string if no track change information */ @@ -211,7 +211,7 @@ private function writeTrackChangeClosing() } /** - * Write paragraph style + * Write paragraph style. * * @return string */ @@ -243,7 +243,7 @@ private function getParagraphStyle() /** * Get font style. */ - private function getFontStyle() + private function getFontStyle(): void { /** @var \PhpOffice\PhpWord\Element\Text $element Type hint */ $element = $this->element; diff --git a/src/PhpWord/Writer/HTML/Element/TextBreak.php b/src/PhpWord/Writer/HTML/Element/TextBreak.php index 6ff092dbf7..af73cb4a06 100644 --- a/src/PhpWord/Writer/HTML/Element/TextBreak.php +++ b/src/PhpWord/Writer/HTML/Element/TextBreak.php @@ -11,21 +11,21 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Writer\HTML\Element; /** - * TextBreak element HTML writer + * TextBreak element HTML writer. * * @since 0.10.0 */ class TextBreak extends AbstractElement { /** - * Write text break + * Write text break. * * @return string */ diff --git a/src/PhpWord/Writer/HTML/Element/TextRun.php b/src/PhpWord/Writer/HTML/Element/TextRun.php index b2deaf25d8..abae7d303f 100644 --- a/src/PhpWord/Writer/HTML/Element/TextRun.php +++ b/src/PhpWord/Writer/HTML/Element/TextRun.php @@ -11,21 +11,21 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Writer\HTML\Element; /** - * TextRun element HTML writer + * TextRun element HTML writer. * * @since 0.10.0 */ class TextRun extends Text { /** - * Write text run + * Write text run. * * @return string */ diff --git a/src/PhpWord/Writer/HTML/Element/Title.php b/src/PhpWord/Writer/HTML/Element/Title.php index 04ed61f57d..3749505013 100644 --- a/src/PhpWord/Writer/HTML/Element/Title.php +++ b/src/PhpWord/Writer/HTML/Element/Title.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,14 +20,14 @@ use PhpOffice\PhpWord\Settings; /** - * TextRun element HTML writer + * TextRun element HTML writer. * * @since 0.10.0 */ class Title extends AbstractElement { /** - * Write heading + * Write heading. * * @return string */ diff --git a/src/PhpWord/Writer/HTML/Part/AbstractPart.php b/src/PhpWord/Writer/HTML/Part/AbstractPart.php index 97c763759a..8612e28451 100644 --- a/src/PhpWord/Writer/HTML/Part/AbstractPart.php +++ b/src/PhpWord/Writer/HTML/Part/AbstractPart.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -49,14 +49,12 @@ abstract public function write(); /** * @param \PhpOffice\PhpWord\Writer\AbstractWriter $writer */ - public function setParentWriter(AbstractWriter $writer = null) + public function setParentWriter(?AbstractWriter $writer = null): void { $this->parentWriter = $writer; } /** - * @throws \PhpOffice\PhpWord\Exception\Exception - * * @return \PhpOffice\PhpWord\Writer\AbstractWriter */ public function getParentWriter() @@ -64,6 +62,7 @@ public function getParentWriter() if ($this->parentWriter !== null) { return $this->parentWriter; } + throw new Exception('No parent WriterInterface assigned.'); } } diff --git a/src/PhpWord/Writer/HTML/Part/Body.php b/src/PhpWord/Writer/HTML/Part/Body.php index a029f96534..19aae8aa1f 100644 --- a/src/PhpWord/Writer/HTML/Part/Body.php +++ b/src/PhpWord/Writer/HTML/Part/Body.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,14 +21,14 @@ use PhpOffice\PhpWord\Writer\HTML\Element\TextRun as TextRunWriter; /** - * RTF body part writer + * RTF body part writer. * * @since 0.11.0 */ class Body extends AbstractPart { /** - * Write part + * Write part. * * @return string */ @@ -52,7 +52,7 @@ public function write() } /** - * Write footnote/endnote contents as textruns + * Write footnote/endnote contents as textruns. * * @return string */ @@ -68,7 +68,7 @@ private function writeNotes() if (!empty($notes)) { $content .= '
    ' . PHP_EOL; foreach ($notes as $noteId => $noteMark) { - list($noteType, $noteTypeId) = explode('-', $noteMark); + [$noteType, $noteTypeId] = explode('-', $noteMark); $method = 'get' . ($noteType == 'endnote' ? 'Endnotes' : 'Footnotes'); $collection = $phpWord->$method()->getItems(); diff --git a/src/PhpWord/Writer/HTML/Part/Head.php b/src/PhpWord/Writer/HTML/Part/Head.php index 1107becf84..a2541aa4b0 100644 --- a/src/PhpWord/Writer/HTML/Part/Head.php +++ b/src/PhpWord/Writer/HTML/Part/Head.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -26,30 +26,30 @@ use PhpOffice\PhpWord\Writer\HTML\Style\Paragraph as ParagraphStyleWriter; /** - * RTF head part writer + * RTF head part writer. * * @since 0.11.0 */ class Head extends AbstractPart { /** - * Write part + * Write part. * * @return string */ public function write() { $docProps = $this->getParentWriter()->getPhpWord()->getDocInfo(); - $propertiesMapping = array( - 'creator' => 'author', - 'title' => '', + $propertiesMapping = [ + 'creator' => 'author', + 'title' => '', 'description' => '', - 'subject' => '', - 'keywords' => '', - 'category' => '', - 'company' => '', - 'manager' => '', - ); + 'subject' => '', + 'keywords' => '', + 'category' => '', + 'company' => '', + 'manager' => '', + ]; $title = $docProps->getTitle(); $title = ($title != '') ? $title : 'PHPWord'; @@ -74,7 +74,7 @@ public function write() } /** - * Get styles + * Get styles. * * @return string */ @@ -83,30 +83,30 @@ private function writeStyles() $css = ' + +

    Calculator

    '; + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[2]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[2]/w:r')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[2]/w:r/w:t')); + self::assertEquals('Calculator', $doc->getElement('/w:document/w:body/w:p[2]/w:r/w:t')->nodeValue); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[2]/w:r/w:rPr')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[2]/w:r/w:rPr/w:sz')); + self::assertEquals('22.5', $doc->getElementAttribute('/w:document/w:body/w:p[2]/w:r/w:rPr/w:sz', 'w:val')); + } + /** * Test underline. */ From a771de75b9bc3fecdb086ab6348b3ae0352038b6 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Wed, 16 Nov 2022 22:02:21 +0100 Subject: [PATCH 053/246] Keep things as private as possible --- src/PhpWord/TemplateProcessor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 6f1ba92287..6b6434d8a6 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -1146,7 +1146,7 @@ protected function getDocumentContentTypesName() /** * Find the start position of the nearest table before $offset. */ - protected function findTableStart(int $offset): int + private function findTableStart(int $offset): int { $rowStart = strrpos( $this->tempDocumentMainPart, @@ -1171,7 +1171,7 @@ protected function findTableStart(int $offset): int /** * Find the end position of the nearest table row after $offset. */ - protected function findTableEnd(int $offset): int + private function findTableEnd(int $offset): int { return strpos($this->tempDocumentMainPart, '', $offset) + 7; } From d2c6b9f7903e0918bd4119e7d349a5544530689a Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Wed, 16 Nov 2022 22:27:10 +0100 Subject: [PATCH 054/246] `master` is the new default branch `master` is now the only permanent branch. Features and fixes should be merged into `master` when stable. Pull requests should be forked from `master`. `develop` branch disappear entirely in favor of temporary features/fixes branches. --- .github/ISSUE_TEMPLATE/how-to-use.md | 2 +- README.md | 15 ++++----------- composer.json | 5 ----- docs/installing.rst | 2 +- docs/intro.rst | 11 ++++------- 5 files changed, 10 insertions(+), 25 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/how-to-use.md b/.github/ISSUE_TEMPLATE/how-to-use.md index 0fef996b19..85cc47072e 100644 --- a/.github/ISSUE_TEMPLATE/how-to-use.md +++ b/.github/ISSUE_TEMPLATE/how-to-use.md @@ -9,6 +9,6 @@ labels: WontFix Documentation is available on [Read the Docs](https://phpword.readthedocs.io/en/latest/). -Sample code is in the [`/samples/` directory](https://github.com/PHPOffice/PHPWord/tree/develop/samples). +Sample code is in the [`/samples/` directory](https://github.com/PHPOffice/PHPWord/tree/master/samples). Usage questions belong on [Stack Overflow](https://stackoverflow.com/questions/tagged/phpword). diff --git a/README.md b/README.md index 6fb2e85459..22d622d316 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # ![PHPWord](https://rawgit.com/PHPOffice/PHPWord/develop/docs/images/phpword.svg "PHPWord") -Master: [![Latest Stable Version](https://poser.pugx.org/phpoffice/phpword/v/stable.png)](https://packagist.org/packages/phpoffice/phpword) [![Build Status](https://travis-ci.org/PHPOffice/PHPWord.svg?branch=master)](https://travis-ci.org/PHPOffice/PHPWord) [![Code Quality](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/) @@ -9,15 +8,9 @@ Master: [![License](https://poser.pugx.org/phpoffice/phpword/license.png)](https://packagist.org/packages/phpoffice/phpword) [![Join the chat at https://gitter.im/PHPOffice/PHPWord](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/PHPOffice/PHPWord) -Develop: -[![Latest Development Version](https://img.shields.io/badge/unstable-dev--develop-orange.svg)](https://packagist.org/packages/phpoffice/phpword#dev-develop) -[![Build Status](https://travis-ci.org/PHPOffice/PHPWord.svg?branch=develop)](https://travis-ci.org/PHPOffice/PHPWord/branches) -[![Code Quality](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/badges/quality-score.png?b=develop)](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/?branch=develop) -[![Coverage Status](https://coveralls.io/repos/github/PHPOffice/PHPWord/badge.svg?branch=develop)](https://coveralls.io/github/PHPOffice/PHPWord?branch=develop) - PHPWord is a library written in pure PHP that provides a set of classes to write to and read from different document file formats. The current version of PHPWord supports Microsoft [Office Open XML](http://en.wikipedia.org/wiki/Office_Open_XML) (OOXML or OpenXML), OASIS [Open Document Format for Office Applications](http://en.wikipedia.org/wiki/OpenDocument) (OpenDocument or ODF), [Rich Text Format](http://en.wikipedia.org/wiki/Rich_Text_Format) (RTF), HTML, and PDF. -PHPWord is an open source project licensed under the terms of [LGPL version 3](COPYING.LESSER). PHPWord is aimed to be a high quality software product by incorporating [continuous integration](https://travis-ci.org/PHPOffice/PHPWord) and [unit testing](http://phpoffice.github.io/PHPWord/coverage/develop/). You can learn more about PHPWord by reading the [Developers' Documentation](http://phpword.readthedocs.org/). +PHPWord is an open source project licensed under the terms of [LGPL version 3](COPYING.LESSER). PHPWord is aimed to be a high quality software product by incorporating [continuous integration](https://github.com/PHPOffice/PHPWord/actions) and unit testing. You can learn more about PHPWord by reading the [Developers' Documentation](http://phpword.readthedocs.org/). If you have any questions, please ask on [StackOverFlow](https://stackoverflow.com/questions/tagged/phpword) @@ -78,9 +71,9 @@ Run the following to use the latest stable version ```sh composer require phpoffice/phpword ``` -or if you want the latest develop version +or if you want the latest unreleased version ```sh -composer require phpoffice/phpword:dev-develop +composer require phpoffice/phpword:dev-master ``` ## Getting started @@ -165,6 +158,6 @@ You can also read the [Developers' Documentation](http://phpword.readthedocs.org We welcome everyone to contribute to PHPWord. Below are some of the things that you can do to contribute. - Read [our contributing guide](CONTRIBUTING.md). -- [Fork us](https://github.com/PHPOffice/PHPWord/fork) and [request a pull](https://github.com/PHPOffice/PHPWord/pulls) to the [develop](https://github.com/PHPOffice/PHPWord/tree/develop) branch. +- [Fork us](https://github.com/PHPOffice/PHPWord/fork) and [request a pull](https://github.com/PHPOffice/PHPWord/pulls) to the [master](https://github.com/PHPOffice/PHPWord/tree/master) branch. - Submit [bug reports or feature requests](https://github.com/PHPOffice/PHPWord/issues) to GitHub. - Follow [@PHPWord](https://twitter.com/PHPWord) and [@PHPOffice](https://twitter.com/PHPOffice) on Twitter. diff --git a/composer.json b/composer.json index f95fbe739e..ef511ffb10 100644 --- a/composer.json +++ b/composer.json @@ -92,10 +92,5 @@ "psr-4": { "PhpOffice\\PhpWordTests\\": "tests/PhpWordTests" } - }, - "extra": { - "branch-alias": { - "dev-develop": "0.19-dev" - } } } diff --git a/docs/installing.rst b/docs/installing.rst index bed177192d..fbdf1e2e8b 100644 --- a/docs/installing.rst +++ b/docs/installing.rst @@ -39,7 +39,7 @@ Example: .. code-block:: bash - composer require phpoffice/phpword:dev-develop + composer require phpoffice/phpword:dev-master Using samples ------------- diff --git a/docs/intro.rst b/docs/intro.rst index d88cd626dd..94cc48d19e 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -13,13 +13,10 @@ Applications `__ Format `__ (RTF). PHPWord is an open source project licensed under the terms of `LGPL -version 3 `__. -PHPWord is aimed to be a high quality software product by incorporating -`continuous integration `__ and -`unit testing `__. +version 3 `__. +PHPWord is aimed to be a high quality software product. You can learn more about PHPWord by reading this Developers' -Documentation and the `API -Documentation `__. +Documentation. Features -------- @@ -191,7 +188,7 @@ things that you can do to contribute. guide `__. - `Fork us `__ and `request a pull `__ to the - `develop `__ + `master `__ branch. - Submit `bug reports or feature requests `__ to GitHub. From 0b9f30fc77a1075be47f85b677989feccb8dfa30 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Wed, 16 Nov 2022 22:35:01 +0100 Subject: [PATCH 055/246] Remove all traces of Travis --- .gitattributes | 4 ++-- README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitattributes b/.gitattributes index f3d033a781..48edc26187 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,6 @@ # build config /.scrutinizer.yml export-ignore -/.travis.yml export-ignore +/.github export-ignore /php_cs.dist export-ignore /phpmd.xml.dist export-ignore /phpstan.neon export-ignore @@ -18,4 +18,4 @@ # tests /phpunit.xml.dist export-ignore -/tests export-ignore \ No newline at end of file +/tests export-ignore diff --git a/README.md b/README.md index 22d622d316..21e0dd4fb3 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # ![PHPWord](https://rawgit.com/PHPOffice/PHPWord/develop/docs/images/phpword.svg "PHPWord") [![Latest Stable Version](https://poser.pugx.org/phpoffice/phpword/v/stable.png)](https://packagist.org/packages/phpoffice/phpword) -[![Build Status](https://travis-ci.org/PHPOffice/PHPWord.svg?branch=master)](https://travis-ci.org/PHPOffice/PHPWord) +[![CI](https://github.com/PHPOffice/PHPWord/actions/workflows/ci.yml/badge.svg)](https://github.com/PHPOffice/PHPWord/actions/workflows/ci.yml) [![Code Quality](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/) -[![Coverage Status](https://coveralls.io/repos/github/PHPOffice/PHPWord/badge.svg?branch=master)](https://coveralls.io/github/PHPOffice/PHPWord?branch=master) +[![Code Coverage](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/) [![Total Downloads](https://poser.pugx.org/phpoffice/phpword/downloads.png)](https://packagist.org/packages/phpoffice/phpword) [![License](https://poser.pugx.org/phpoffice/phpword/license.png)](https://packagist.org/packages/phpoffice/phpword) [![Join the chat at https://gitter.im/PHPOffice/PHPWord](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/PHPOffice/PHPWord) From 28ca75eca4592d908f3e0181a450db64b2fa77bd Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Wed, 16 Nov 2022 22:55:44 +0100 Subject: [PATCH 056/246] Close oldest stale issues first --- .github/workflows/stale.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 548bf23d0c..805ad13324 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -13,6 +13,7 @@ jobs: steps: - uses: actions/stale@v5 with: + ascending: true # oldest issues first days-before-stale: 90 days-before-close: 60 exempt-issue-labels: 'pinned,security' From c37be288a50dacb81af7560162f14efd27c1088c Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Thu, 17 Nov 2022 09:45:21 +0100 Subject: [PATCH 057/246] Consume half of the 1000 operations per hour limit of GitHub API --- .github/workflows/stale.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 805ad13324..f0c7534ece 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -13,6 +13,7 @@ jobs: steps: - uses: actions/stale@v5 with: + operations-per-run: 500 # allow to consume half of the 1000 operations per hour limit of GitHub API ascending: true # oldest issues first days-before-stale: 90 days-before-close: 60 From 95ce9986514b3c7e7dacc8d79129366b87dae463 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Thu, 17 Nov 2022 09:53:27 +0100 Subject: [PATCH 058/246] Drop obsolete coverall references Instead, we've been using Scrutinizer for a while --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index ef511ffb10..ccb42ccaf2 100644 --- a/composer.json +++ b/composer.json @@ -70,7 +70,6 @@ "ext-libxml": "*", "dompdf/dompdf": "^2.0", "mpdf/mpdf": "^8.1", - "php-coveralls/php-coveralls": "^2.5", "phpmd/phpmd": "^2.13", "phpunit/phpunit": ">=7.0", "tecnickcom/tcpdf": "^6.5", From 6deea59905be18d91b2150725598a25de0ac1cfe Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Thu, 17 Nov 2022 14:39:30 +0100 Subject: [PATCH 059/246] Update GitHub Actions --- .github/workflows/ci.yml | 12 ++++++------ .github/workflows/github-pages.yml | 2 +- .github/workflows/stale.yml | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d9b2596624..e50faea084 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 @@ -33,7 +33,7 @@ jobs: run: echo "::set-output name=dir::$(composer config cache-files-dir)" - name: Cache composer dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} @@ -58,7 +58,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 @@ -73,7 +73,7 @@ jobs: run: echo "::set-output name=dir::$(composer config cache-files-dir)" - name: Cache composer dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} @@ -92,7 +92,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 @@ -106,7 +106,7 @@ jobs: run: echo "::set-output name=dir::$(composer config cache-files-dir)" - name: Cache composer dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml index a7850833a3..aa35f57f87 100644 --- a/.github/workflows/github-pages.yml +++ b/.github/workflows/github-pages.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index f0c7534ece..762f637b24 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -11,7 +11,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v5 + - uses: actions/stale@v6 with: operations-per-run: 500 # allow to consume half of the 1000 operations per hour limit of GitHub API ascending: true # oldest issues first From 228bada97269c0e08fa6b671c58eb1e4ce711fdd Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Fri, 18 Nov 2022 10:37:07 +0100 Subject: [PATCH 060/246] Remove stale Github Actions --- .github/workflows/stale.yml | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 .github/workflows/stale.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml deleted file mode 100644 index 762f637b24..0000000000 --- a/.github/workflows/stale.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: 'Close stale issues and PRs' -on: - schedule: - - cron: '30 1 * * *' - -permissions: - issues: write - pull-requests: write - -jobs: - stale: - runs-on: ubuntu-latest - steps: - - uses: actions/stale@v6 - with: - operations-per-run: 500 # allow to consume half of the 1000 operations per hour limit of GitHub API - ascending: true # oldest issues first - days-before-stale: 90 - days-before-close: 60 - exempt-issue-labels: 'pinned,security' - exempt-pr-labels: 'pinned,security' - stale-issue-message: 'This issue has been automatically marked as stale because it has not had -recent activity. It will be closed if no further activity occurs. - -If this is still an issue for you, please try to help by debugging it -further and sharing your results. - -Thank you for your contributions.' - stale-pr-message: 'This PR has been automatically marked as stale because it has not had -recent activity. It will be closed if no further activity occurs. - -If this is still an issue for you, please try to complete the PR by adding tests and making sure that the CI is green. - -Thank you for your contributions.' From 9ed82d1f5a8eff662d942d19c3686fc39f8ece7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franck=20Bou=C3=A9?= Date: Fri, 18 Nov 2022 13:31:04 +0100 Subject: [PATCH 061/246] delete blank lines --- src/PhpWord/Shared/Html.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 96caff7610..c21048ba73 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -536,11 +536,9 @@ protected static function parseList($node, $element, &$styles, &$data) switch ($attribute->name) { case 'start': $start = (int) $attribute->value; - break; case 'type': $type = $attribute->value; - break; } } From ecd2fcbda8a4747660c10d9ab7f5a25efcdf34ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franck=20Bou=C3=A9?= Date: Fri, 18 Nov 2022 13:34:21 +0100 Subject: [PATCH 062/246] add blank lines --- src/PhpWord/Shared/Html.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index c21048ba73..99e5400205 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -536,9 +536,11 @@ protected static function parseList($node, $element, &$styles, &$data) switch ($attribute->name) { case 'start': $start = (int) $attribute->value; + break; case 'type': $type = $attribute->value; + break; } } From a075740e32d60867e1c0bdc503cb48f8172c3489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franck=20Bou=C3=A9?= Date: Fri, 18 Nov 2022 13:38:18 +0100 Subject: [PATCH 063/246] remove espaces --- src/PhpWord/Shared/Html.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 99e5400205..fefd62b614 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -536,11 +536,11 @@ protected static function parseList($node, $element, &$styles, &$data) switch ($attribute->name) { case 'start': $start = (int) $attribute->value; - +- break; case 'type': $type = $attribute->value; - +- break; } } From 9afd53d6223b576258821af937310c9103998981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franck=20Bou=C3=A9?= Date: Fri, 18 Nov 2022 13:44:35 +0100 Subject: [PATCH 064/246] remove - --- src/PhpWord/Shared/Html.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index fefd62b614..96caff7610 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -536,11 +536,11 @@ protected static function parseList($node, $element, &$styles, &$data) switch ($attribute->name) { case 'start': $start = (int) $attribute->value; -- + break; case 'type': $type = $attribute->value; -- + break; } } From 01899777432d19739d0c5a5b367f27a09d4efc45 Mon Sep 17 00:00:00 2001 From: Nicolas Dermine Date: Sun, 20 Nov 2022 06:49:42 +0100 Subject: [PATCH 065/246] improve phpdoc The `tempDocumentHeaders` and `tempDocumentFooters` array attributes are passed to this method parameter --- src/PhpWord/TemplateProcessor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 6b6434d8a6..f525cf497f 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -1027,7 +1027,7 @@ function ($match) { * * @param mixed $search * @param mixed $replace - * @param string $documentPartXML + * @param array|string $documentPartXML * @param int $limit * * @return string From 573f1c3ea1c22e12a8d461def96af6e8740653bd Mon Sep 17 00:00:00 2001 From: Artem Vasilev Date: Tue, 22 Nov 2022 13:43:03 +0300 Subject: [PATCH 066/246] set default value on empty value attribute --- src/PhpWord/Reader/Word2007/AbstractPart.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 7d4209953b..14b94fb9df 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -626,7 +626,7 @@ protected function readStyleDefs(XMLReader $xmlReader, ?DOMElement $parentNode = $styles = []; foreach ($styleDefs as $styleProp => $styleVal) { - [$method, $element, $attribute, $expected] = array_pad($styleVal, 4, null); + [$method, $element, $attribute, $expected, $default] = array_pad($styleVal, 5, null); $element = $this->findPossibleElement($xmlReader, $parentNode, $element); if ($element === null) { @@ -640,7 +640,7 @@ protected function readStyleDefs(XMLReader $xmlReader, ?DOMElement $parentNode = // Use w:val as default if no attribute assigned $attribute = ($attribute === null) ? 'w:val' : $attribute; - $attributeValue = $xmlReader->getAttribute($attribute, $node); + $attributeValue = $xmlReader->getAttribute($attribute, $node) ?? $default; $styleValue = $this->readStyleDef($method, $attributeValue, $expected); if ($styleValue !== null) { From b457ff5f7fadf28f4d62d1fcd5b9ee3424392835 Mon Sep 17 00:00:00 2001 From: Artem Vasilev Date: Tue, 22 Nov 2022 13:45:55 +0300 Subject: [PATCH 067/246] set default value for vMerge --- src/PhpWord/Reader/Word2007/AbstractPart.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 14b94fb9df..df3cfed709 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -558,7 +558,7 @@ private function readCellStyle(XMLReader $xmlReader, DOMElement $domNode) 'valign' => [self::READ_VALUE, 'w:vAlign'], 'textDirection' => [self::READ_VALUE, 'w:textDirection'], 'gridSpan' => [self::READ_VALUE, 'w:gridSpan'], - 'vMerge' => [self::READ_VALUE, 'w:vMerge'], + 'vMerge' => [self::READ_VALUE, 'w:vMerge', null, null, 'continue'], 'bgColor' => [self::READ_VALUE, 'w:shd', 'w:fill'], ]; From 02a92c89241a0d28b84077e1910fc068a9f22a06 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Tue, 22 Nov 2022 21:38:41 +0100 Subject: [PATCH 068/246] HTML Reader : Set style name from the CSS class --- src/PhpWord/Shared/Html.php | 6 ++++++ tests/PhpWordTests/Shared/HtmlTest.php | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index b2c99d0336..c937d29918 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -162,6 +162,7 @@ protected static function parseInlineStyle($node, $styles = []) $attributeClass = $attributes->getNamedItem('class'); if ($attributeClass && self::$css) { $styles = self::parseStyleDeclarations(self::$css->getStyle('.' . $attributeClass->value), $styles); + $styles['className'] = $attributeClass->value; } $attributeStyle = $attributes->getNamedItem('style'); @@ -411,6 +412,11 @@ protected static function parseTable($node, $element, &$styles) $newElement = $element->addTable($elementStyles); + // Add style name from CSS Class + if (isset($elementStyles['className'])) { + $newElement->getStyle()->setStyleName($elementStyles['className']); + } + $attributes = $node->attributes; if ($attributes->getNamedItem('border') !== null) { $border = (int) $attributes->getNamedItem('border')->value; diff --git a/tests/PhpWordTests/Shared/HtmlTest.php b/tests/PhpWordTests/Shared/HtmlTest.php index 7c02581a97..8da6ccc61e 100644 --- a/tests/PhpWordTests/Shared/HtmlTest.php +++ b/tests/PhpWordTests/Shared/HtmlTest.php @@ -19,6 +19,7 @@ use Exception; use PhpOffice\PhpWord\Element\Section; +use PhpOffice\PhpWord\Element\Table; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Shared\Html; use PhpOffice\PhpWord\SimpleType\Jc; @@ -134,6 +135,17 @@ public function testParseStyle(): void self::assertEquals('22.5', $doc->getElementAttribute('/w:document/w:body/w:p[2]/w:r/w:rPr/w:sz', 'w:val')); } + public function testParseStyleTableClassName(): void + { + $html = '
    if (preg_match('#(?:top|bottom|middle|baseline)#i', $val, $matches)) { $styles['valign'] = self::mapAlignVertical($matches[0]); } + break; } } @@ -148,71 +160,71 @@ protected static function parseInlineStyle($node, $styles = array()) /** * Parse a node and add a corresponding element to the parent element. * - * @param \DOMNode $node node to parse + * @param DOMNode $node node to parse * @param \PhpOffice\PhpWord\Element\AbstractContainer $element object to add an element corresponding with the node * @param array $styles Array with all styles * @param array $data Array to transport data to a next level in the DOM tree, for example level of listitems */ - protected static function parseNode($node, $element, $styles = array(), $data = array()) + protected static function parseNode($node, $element, $styles = [], $data = []): void { // Populate styles array - $styleTypes = array('font', 'paragraph', 'list', 'table', 'row', 'cell'); + $styleTypes = ['font', 'paragraph', 'list', 'table', 'row', 'cell']; foreach ($styleTypes as $styleType) { if (!isset($styles[$styleType])) { - $styles[$styleType] = array(); + $styles[$styleType] = []; } } // Node mapping table - $nodes = array( - // $method $node $element $styles $data $argument1 $argument2 - 'p' => array('Paragraph', $node, $element, $styles, null, null, null), - 'h1' => array('Heading', null, $element, $styles, null, 'Heading1', null), - 'h2' => array('Heading', null, $element, $styles, null, 'Heading2', null), - 'h3' => array('Heading', null, $element, $styles, null, 'Heading3', null), - 'h4' => array('Heading', null, $element, $styles, null, 'Heading4', null), - 'h5' => array('Heading', null, $element, $styles, null, 'Heading5', null), - 'h6' => array('Heading', null, $element, $styles, null, 'Heading6', null), - '#text' => array('Text', $node, $element, $styles, null, null, null), - 'strong' => array('Property', null, null, $styles, null, 'bold', true), - 'b' => array('Property', null, null, $styles, null, 'bold', true), - 'em' => array('Property', null, null, $styles, null, 'italic', true), - 'i' => array('Property', null, null, $styles, null, 'italic', true), - 'u' => array('Property', null, null, $styles, null, 'underline', 'single'), - 'sup' => array('Property', null, null, $styles, null, 'superScript', true), - 'sub' => array('Property', null, null, $styles, null, 'subScript', true), - 'span' => array('Span', $node, null, $styles, null, null, null), - 'font' => array('Span', $node, null, $styles, null, null, null), - 'table' => array('Table', $node, $element, $styles, null, null, null), - 'tr' => array('Row', $node, $element, $styles, null, null, null), - 'td' => array('Cell', $node, $element, $styles, null, null, null), - 'th' => array('Cell', $node, $element, $styles, null, null, null), - 'ul' => array('List', $node, $element, $styles, $data, null, null), - 'ol' => array('List', $node, $element, $styles, $data, null, null), - 'li' => array('ListItem', $node, $element, $styles, $data, null, null), - 'img' => array('Image', $node, $element, $styles, null, null, null), - 'br' => array('LineBreak', null, $element, $styles, null, null, null), - 'a' => array('Link', $node, $element, $styles, null, null, null), - 'input' => array('Input', $node, $element, $styles, null, null, null), - 'hr' => array('HorizRule', $node, $element, $styles, null, null, null), - ); + $nodes = [ + // $method $node $element $styles $data $argument1 $argument2 + 'p' => ['Paragraph', $node, $element, $styles, null, null, null], + 'h1' => ['Heading', null, $element, $styles, null, 'Heading1', null], + 'h2' => ['Heading', null, $element, $styles, null, 'Heading2', null], + 'h3' => ['Heading', null, $element, $styles, null, 'Heading3', null], + 'h4' => ['Heading', null, $element, $styles, null, 'Heading4', null], + 'h5' => ['Heading', null, $element, $styles, null, 'Heading5', null], + 'h6' => ['Heading', null, $element, $styles, null, 'Heading6', null], + '#text' => ['Text', $node, $element, $styles, null, null, null], + 'strong' => ['Property', null, null, $styles, null, 'bold', true], + 'b' => ['Property', null, null, $styles, null, 'bold', true], + 'em' => ['Property', null, null, $styles, null, 'italic', true], + 'i' => ['Property', null, null, $styles, null, 'italic', true], + 'u' => ['Property', null, null, $styles, null, 'underline', 'single'], + 'sup' => ['Property', null, null, $styles, null, 'superScript', true], + 'sub' => ['Property', null, null, $styles, null, 'subScript', true], + 'span' => ['Span', $node, null, $styles, null, null, null], + 'font' => ['Span', $node, null, $styles, null, null, null], + 'table' => ['Table', $node, $element, $styles, null, null, null], + 'tr' => ['Row', $node, $element, $styles, null, null, null], + 'td' => ['Cell', $node, $element, $styles, null, null, null], + 'th' => ['Cell', $node, $element, $styles, null, null, null], + 'ul' => ['List', $node, $element, $styles, $data, null, null], + 'ol' => ['List', $node, $element, $styles, $data, null, null], + 'li' => ['ListItem', $node, $element, $styles, $data, null, null], + 'img' => ['Image', $node, $element, $styles, null, null, null], + 'br' => ['LineBreak', null, $element, $styles, null, null, null], + 'a' => ['Link', $node, $element, $styles, null, null, null], + 'input' => ['Input', $node, $element, $styles, null, null, null], + 'hr' => ['HorizRule', $node, $element, $styles, null, null, null], + ]; $newElement = null; - $keys = array('node', 'element', 'styles', 'data', 'argument1', 'argument2'); + $keys = ['node', 'element', 'styles', 'data', 'argument1', 'argument2']; if (isset($nodes[$node->nodeName])) { // Execute method based on node mapping table and return $newElement or null // Arguments are passed by reference - $arguments = array(); - $args = array(); - list($method, $args[0], $args[1], $args[2], $args[3], $args[4], $args[5]) = $nodes[$node->nodeName]; - for ($i = 0; $i <= 5; $i++) { + $arguments = []; + $args = []; + [$method, $args[0], $args[1], $args[2], $args[3], $args[4], $args[5]] = $nodes[$node->nodeName]; + for ($i = 0; $i <= 5; ++$i) { if ($args[$i] !== null) { $arguments[$keys[$i]] = &$args[$i]; } } $method = "parse{$method}"; - $newElement = call_user_func_array(array('PhpOffice\PhpWord\Shared\Html', $method), array_values($arguments)); + $newElement = call_user_func_array(['PhpOffice\PhpWord\Shared\Html', $method], array_values($arguments)); // Retrieve back variables from arguments foreach ($keys as $key) { @@ -232,12 +244,12 @@ protected static function parseNode($node, $element, $styles = array(), $data = /** * Parse child nodes. * - * @param \DOMNode $node + * @param DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element * @param array $styles * @param array $data */ - protected static function parseChildNodes($node, $element, $styles, $data) + protected static function parseChildNodes($node, $element, $styles, $data): void { if ('li' != $node->nodeName) { $cNodes = $node->childNodes; @@ -252,12 +264,13 @@ protected static function parseChildNodes($node, $element, $styles, $data) } /** - * Parse paragraph node + * Parse paragraph node. * - * @param \DOMNode $node + * @param DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element * @param array &$styles - * @return \PhpOffice\PhpWord\Element\TextRun|\PhpOffice\PhpWord\Element\PageBreak + * + * @return \PhpOffice\PhpWord\Element\PageBreak|\PhpOffice\PhpWord\Element\TextRun */ protected static function parseParagraph($node, $element, &$styles) { @@ -270,13 +283,13 @@ protected static function parseParagraph($node, $element, &$styles) } /** - * Parse input node + * Parse input node. * - * @param \DOMNode $node + * @param DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element * @param array &$styles */ - protected static function parseInput($node, $element, &$styles) + protected static function parseInput($node, $element, &$styles): void { $attributes = $node->attributes; if (null === $attributes->getNamedItem('type')) { @@ -289,16 +302,18 @@ protected static function parseInput($node, $element, &$styles) $checked = ($checked = $attributes->getNamedItem('checked')) && $checked->value === 'true' ? true : false; $textrun = $element->addTextRun($styles['paragraph']); $textrun->addFormField('checkbox')->setValue($checked); + break; } } /** - * Parse heading node + * Parse heading node. * * @param \PhpOffice\PhpWord\Element\AbstractContainer $element * @param array &$styles * @param string $argument1 Name of heading style + * * @return \PhpOffice\PhpWord\Element\TextRun * * @todo Think of a clever way of defining header styles, now it is only based on the assumption, that @@ -313,13 +328,13 @@ protected static function parseHeading($element, &$styles, $argument1) } /** - * Parse text node + * Parse text node. * - * @param \DOMNode $node + * @param DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element * @param array &$styles */ - protected static function parseText($node, $element, &$styles) + protected static function parseText($node, $element, &$styles): void { $styles['font'] = self::recursiveParseStylesInHierarchy($node, $styles['font']); @@ -328,40 +343,41 @@ protected static function parseText($node, $element, &$styles) $styles['paragraph']['alignment'] = $styles['font']['alignment']; } - if (is_callable(array($element, 'addText'))) { + if (is_callable([$element, 'addText'])) { $element->addText($node->nodeValue, $styles['font'], $styles['paragraph']); } } /** - * Parse property node + * Parse property node. * * @param array &$styles * @param string $argument1 Style name * @param string $argument2 Style value */ - protected static function parseProperty(&$styles, $argument1, $argument2) + protected static function parseProperty(&$styles, $argument1, $argument2): void { $styles['font'][$argument1] = $argument2; } /** - * Parse span node + * Parse span node. * - * @param \DOMNode $node + * @param DOMNode $node * @param array &$styles */ - protected static function parseSpan($node, &$styles) + protected static function parseSpan($node, &$styles): void { self::parseInlineStyle($node, $styles['font']); } /** - * Parse table node + * Parse table node. * - * @param \DOMNode $node + * @param DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element * @param array &$styles + * * @return Table $element * * @todo As soon as TableItem, RowItem and CellItem support relative width and height @@ -382,11 +398,12 @@ protected static function parseTable($node, $element, &$styles) } /** - * Parse a table row + * Parse a table row. * - * @param \DOMNode $node + * @param DOMNode $node * @param \PhpOffice\PhpWord\Element\Table $element * @param array &$styles + * * @return Row $element */ protected static function parseRow($node, $element, &$styles) @@ -400,11 +417,12 @@ protected static function parseRow($node, $element, &$styles) } /** - * Parse table cell + * Parse table cell. * - * @param \DOMNode $node + * @param DOMNode $node * @param \PhpOffice\PhpWord\Element\Table $element * @param array &$styles + * * @return \PhpOffice\PhpWord\Element\Cell|\PhpOffice\PhpWord\Element\TextRun $element */ protected static function parseCell($node, $element, &$styles) @@ -417,7 +435,7 @@ protected static function parseCell($node, $element, &$styles) } // set cell width to control column widths - $width = isset($cellStyles['width']) ? $cellStyles['width'] : null; + $width = $cellStyles['width'] ?? null; unset($cellStyles['width']); // would not apply $cell = $element->addCell($width, $cellStyles); @@ -429,12 +447,11 @@ protected static function parseCell($node, $element, &$styles) } /** - * Checks if $node contains an HTML element that cannot be added to TextRun + * Checks if $node contains an HTML element that cannot be added to TextRun. * - * @param \DOMNode $node * @return bool Returns true if the node contains an HTML element that cannot be added to TextRun */ - protected static function shouldAddTextRun(\DOMNode $node) + protected static function shouldAddTextRun(DOMNode $node) { $containsBlockElement = self::$xpath->query('.//table|./p|./ul|./ol|./h1|./h2|./h3|./h4|./h5|./h6', $node)->length > 0; if ($containsBlockElement) { @@ -447,15 +464,12 @@ protected static function shouldAddTextRun(\DOMNode $node) /** * Recursively parses styles on parent nodes * TODO if too slow, add caching of parent nodes, !! everything is static here so watch out for concurrency !! - * - * @param \DOMNode $node - * @param array &$styles */ - protected static function recursiveParseStylesInHierarchy(\DOMNode $node, array $style) + protected static function recursiveParseStylesInHierarchy(DOMNode $node, array $style) { - $parentStyle = array(); + $parentStyle = []; if ($node->parentNode != null && XML_ELEMENT_NODE == $node->parentNode->nodeType) { - $parentStyle = self::recursiveParseStylesInHierarchy($node->parentNode, array()); + $parentStyle = self::recursiveParseStylesInHierarchy($node->parentNode, []); } if ($node->nodeName === '#text') { $parentStyle = array_merge($parentStyle, $style); @@ -468,13 +482,11 @@ protected static function recursiveParseStylesInHierarchy(\DOMNode $node, array } /** - * Removes non-inherited styles from array - * - * @param array &$styles + * Removes non-inherited styles from array. */ protected static function filterOutNonInheritedStyles(array $styles) { - $nonInheritedStyles = array( + $nonInheritedStyles = [ 'borderSize', 'borderTopSize', 'borderRightSize', @@ -491,7 +503,7 @@ protected static function filterOutNonInheritedStyles(array $styles) 'underline', 'strikethrough', 'hidden', - ); + ]; $styles = array_diff_key($styles, array_flip($nonInheritedStyles)); @@ -499,9 +511,9 @@ protected static function filterOutNonInheritedStyles(array $styles) } /** - * Parse list node + * Parse list node. * - * @param \DOMNode $node + * @param DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element * @param array &$styles * @param array &$data @@ -510,7 +522,7 @@ protected static function parseList($node, $element, &$styles, &$data) { $isOrderedList = $node->nodeName === 'ol'; if (isset($data['listdepth'])) { - $data['listdepth']++; + ++$data['listdepth']; } else { $data['listdepth'] = 0; $styles['list'] = 'listStyle_' . self::$listIndex++; @@ -523,9 +535,11 @@ protected static function parseList($node, $element, &$styles, &$data) switch ($attribute->name) { case 'start': $start = (int) $attribute->value; + break; case 'type': $type = $attribute->value; + break; } } @@ -548,47 +562,48 @@ protected static function parseList($node, $element, &$styles, &$data) /** * @param bool $isOrderedList + * * @return array */ protected static function getListStyle($isOrderedList) { if ($isOrderedList) { - return array( - 'type' => 'multilevel', - 'levels' => array( - array('format' => NumberFormat::DECIMAL, 'text' => '%1.', 'alignment' => 'left', 'tabPos' => 720, 'left' => 720, 'hanging' => 360), - array('format' => NumberFormat::LOWER_LETTER, 'text' => '%2.', 'alignment' => 'left', 'tabPos' => 1440, 'left' => 1440, 'hanging' => 360), - array('format' => NumberFormat::LOWER_ROMAN, 'text' => '%3.', 'alignment' => 'right', 'tabPos' => 2160, 'left' => 2160, 'hanging' => 180), - array('format' => NumberFormat::DECIMAL, 'text' => '%4.', 'alignment' => 'left', 'tabPos' => 2880, 'left' => 2880, 'hanging' => 360), - array('format' => NumberFormat::LOWER_LETTER, 'text' => '%5.', 'alignment' => 'left', 'tabPos' => 3600, 'left' => 3600, 'hanging' => 360), - array('format' => NumberFormat::LOWER_ROMAN, 'text' => '%6.', 'alignment' => 'right', 'tabPos' => 4320, 'left' => 4320, 'hanging' => 180), - array('format' => NumberFormat::DECIMAL, 'text' => '%7.', 'alignment' => 'left', 'tabPos' => 5040, 'left' => 5040, 'hanging' => 360), - array('format' => NumberFormat::LOWER_LETTER, 'text' => '%8.', 'alignment' => 'left', 'tabPos' => 5760, 'left' => 5760, 'hanging' => 360), - array('format' => NumberFormat::LOWER_ROMAN, 'text' => '%9.', 'alignment' => 'right', 'tabPos' => 6480, 'left' => 6480, 'hanging' => 180), - ), - ); + return [ + 'type' => 'multilevel', + 'levels' => [ + ['format' => NumberFormat::DECIMAL, 'text' => '%1.', 'alignment' => 'left', 'tabPos' => 720, 'left' => 720, 'hanging' => 360], + ['format' => NumberFormat::LOWER_LETTER, 'text' => '%2.', 'alignment' => 'left', 'tabPos' => 1440, 'left' => 1440, 'hanging' => 360], + ['format' => NumberFormat::LOWER_ROMAN, 'text' => '%3.', 'alignment' => 'right', 'tabPos' => 2160, 'left' => 2160, 'hanging' => 180], + ['format' => NumberFormat::DECIMAL, 'text' => '%4.', 'alignment' => 'left', 'tabPos' => 2880, 'left' => 2880, 'hanging' => 360], + ['format' => NumberFormat::LOWER_LETTER, 'text' => '%5.', 'alignment' => 'left', 'tabPos' => 3600, 'left' => 3600, 'hanging' => 360], + ['format' => NumberFormat::LOWER_ROMAN, 'text' => '%6.', 'alignment' => 'right', 'tabPos' => 4320, 'left' => 4320, 'hanging' => 180], + ['format' => NumberFormat::DECIMAL, 'text' => '%7.', 'alignment' => 'left', 'tabPos' => 5040, 'left' => 5040, 'hanging' => 360], + ['format' => NumberFormat::LOWER_LETTER, 'text' => '%8.', 'alignment' => 'left', 'tabPos' => 5760, 'left' => 5760, 'hanging' => 360], + ['format' => NumberFormat::LOWER_ROMAN, 'text' => '%9.', 'alignment' => 'right', 'tabPos' => 6480, 'left' => 6480, 'hanging' => 180], + ], + ]; } - return array( - 'type' => 'hybridMultilevel', - 'levels' => array( - array('format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 720, 'left' => 720, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'), - array('format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 1440, 'left' => 1440, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'), - array('format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2160, 'left' => 2160, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'), - array('format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2880, 'left' => 2880, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'), - array('format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 3600, 'left' => 3600, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'), - array('format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 4320, 'left' => 4320, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'), - array('format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 5040, 'left' => 5040, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'), - array('format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 5760, 'left' => 5760, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'), - array('format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 6480, 'left' => 6480, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'), - ), - ); + return [ + 'type' => 'hybridMultilevel', + 'levels' => [ + ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 720, 'left' => 720, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 1440, 'left' => 1440, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2160, 'left' => 2160, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2880, 'left' => 2880, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 3600, 'left' => 3600, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 4320, 'left' => 4320, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 5040, 'left' => 5040, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 5760, 'left' => 5760, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 6480, 'left' => 6480, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'], + ], + ]; } /** - * Parse list item node + * Parse list item node. * - * @param \DOMNode $node + * @param DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element * @param array &$styles * @param array $data @@ -596,7 +611,7 @@ protected static function getListStyle($isOrderedList) * @todo This function is almost the same like `parseChildNodes`. Merged? * @todo As soon as ListItem inherits from AbstractContainer or TextRun delete parsing part of childNodes */ - protected static function parseListItem($node, $element, &$styles, $data) + protected static function parseListItem($node, $element, &$styles, $data): void { $cNodes = $node->childNodes; if (!empty($cNodes)) { @@ -608,10 +623,11 @@ protected static function parseListItem($node, $element, &$styles, $data) } /** - * Parse style + * Parse style. * - * @param \DOMAttr $attribute + * @param DOMAttr $attribute * @param array $styles + * * @return array */ protected static function parseStyle($attribute, $styles) @@ -619,7 +635,7 @@ protected static function parseStyle($attribute, $styles) $properties = explode(';', trim($attribute->value, " \t\n\r\0\x0B;")); foreach ($properties as $property) { - list($cKey, $cValue) = array_pad(explode(':', $property, 2), 2, null); + [$cKey, $cValue] = array_pad(explode(':', $property, 2), 2, null); $cValue = trim($cValue ?? ''); $cKey = strtolower(trim($cKey)); switch ($cKey) { @@ -627,36 +643,46 @@ protected static function parseStyle($attribute, $styles) switch ($cValue) { case 'underline': $styles['underline'] = 'single'; + break; case 'line-through': $styles['strikethrough'] = true; + break; } + break; case 'text-align': $styles['alignment'] = self::mapAlign($cValue); + break; case 'display': $styles['hidden'] = $cValue === 'none' || $cValue === 'hidden'; + break; case 'direction': $styles['rtl'] = $cValue === 'rtl'; + break; case 'font-size': $styles['size'] = Converter::cssToPoint($cValue); + break; case 'font-family': $cValue = array_map('trim', explode(',', $cValue)); $styles['name'] = ucwords($cValue[0]); + break; case 'color': $styles['color'] = trim($cValue, '#'); + break; case 'background-color': $styles['bgColor'] = trim($cValue, '#'); + break; case 'line-height': - $matches = array(); + $matches = []; if ($cValue === 'normal') { $spacingLineRule = \PhpOffice\PhpWord\SimpleType\LineSpacingRule::AUTO; $spacing = 0; @@ -677,12 +703,15 @@ protected static function parseStyle($attribute, $styles) } $styles['spacingLineRule'] = $spacingLineRule; $styles['line-spacing'] = $spacing; + break; case 'letter-spacing': $styles['letter-spacing'] = Converter::cssToTwip($cValue); + break; case 'text-indent': $styles['indentation']['firstLine'] = Converter::cssToTwip($cValue); + break; case 'font-weight': $tValue = false; @@ -690,6 +719,7 @@ protected static function parseStyle($attribute, $styles) $tValue = true; // also match bolder } $styles['bold'] = $tValue; + break; case 'font-style': $tValue = false; @@ -697,28 +727,35 @@ protected static function parseStyle($attribute, $styles) $tValue = true; } $styles['italic'] = $tValue; + break; case 'margin': $cValue = Converter::cssToTwip($cValue); $styles['spaceBefore'] = $cValue; $styles['spaceAfter'] = $cValue; + break; case 'margin-top': // BC change: up to ver. 0.17.0 incorrectly converted to points - Converter::cssToPoint($cValue) $styles['spaceBefore'] = Converter::cssToTwip($cValue); + break; case 'margin-bottom': // BC change: up to ver. 0.17.0 incorrectly converted to points - Converter::cssToPoint($cValue) $styles['spaceAfter'] = Converter::cssToTwip($cValue); + break; case 'border-color': self::mapBorderColor($styles, $cValue); + break; case 'border-width': $styles['borderSize'] = Converter::cssToPoint($cValue); + break; case 'border-style': $styles['borderStyle'] = self::mapBorderStyle($cValue); + break; case 'width': if (preg_match('/([0-9]+[a-z]+)/', $cValue, $matches)) { @@ -731,6 +768,7 @@ protected static function parseStyle($attribute, $styles) $styles['width'] = $matches[1]; $styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::AUTO; } + break; case 'border': case 'border-top': @@ -760,17 +798,20 @@ protected static function parseStyle($attribute, $styles) $styles["border{$which}Color"] = trim($matches[2], '#'); $styles["border{$which}Style"] = self::mapBorderStyle($matches[3]); } + break; case 'vertical-align': // https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align if (preg_match('#(?:top|bottom|middle|sub|baseline)#i', $cValue, $matches)) { $styles['valign'] = self::mapAlignVertical($matches[0]); } + break; case 'page-break-after': if ($cValue == 'always') { $styles['isPageBreak'] = true; } + break; } } @@ -779,37 +820,40 @@ protected static function parseStyle($attribute, $styles) } /** - * Parse image node + * Parse image node. * - * @param \DOMNode $node + * @param DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element * * @return \PhpOffice\PhpWord\Element\Image - **/ + */ protected static function parseImage($node, $element) { - $style = array(); + $style = []; $src = null; foreach ($node->attributes as $attribute) { switch ($attribute->name) { case 'src': $src = $attribute->value; + break; case 'width': $width = $attribute->value; $style['width'] = $width; $style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX; + break; case 'height': $height = $attribute->value; $style['height'] = $height; $style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX; + break; case 'style': $styleattr = explode(';', $attribute->value); foreach ($styleattr as $attr) { if (strpos($attr, ':')) { - list($k, $v) = explode(':', $attr); + [$k, $v] = explode(':', $attr); switch ($k) { case 'float': if (trim($v) == 'right') { @@ -826,10 +870,12 @@ protected static function parseImage($node, $element) $style['wrap'] = \PhpOffice\PhpWord\Style\Image::WRAP_TIGHT; $style['overlap'] = true; } + break; } } } + break; } } @@ -837,7 +883,7 @@ protected static function parseImage($node, $element) if (strpos($src, 'data:image') !== false) { $tmpDir = Settings::getTempDir() . '/'; - $match = array(); + $match = []; preg_match('/data:image\/(\w+);base64,(.+)/', $src, $match); $src = $imgFile = $tmpDir . uniqid() . '.' . $match[1]; @@ -852,16 +898,16 @@ protected static function parseImage($node, $element) $src = urldecode($src); if (!is_file($src) - && !is_null(self::$options) - && isset(self::$options['IMG_SRC_SEARCH']) - && isset(self::$options['IMG_SRC_REPLACE'])) { + && null !== self::$options + && isset(self::$options['IMG_SRC_SEARCH'], self::$options['IMG_SRC_REPLACE']) + ) { $src = str_replace(self::$options['IMG_SRC_SEARCH'], self::$options['IMG_SRC_REPLACE'], $src); } if (!is_file($src)) { if ($imgBlob = @file_get_contents($src)) { $tmpDir = Settings::getTempDir() . '/'; - $match = array(); + $match = []; preg_match('/.+\.(\w+)$/', $src, $match); $src = $tmpDir . uniqid() . '.' . $match[1]; @@ -877,16 +923,17 @@ protected static function parseImage($node, $element) if (is_file($src)) { $newElement = $element->addImage($src, $style); } else { - throw new \Exception("Could not load image $originSrc"); + throw new Exception("Could not load image $originSrc"); } return $newElement; } /** - * Transforms a CSS border style into a word border style + * Transforms a CSS border style into a word border style. * * @param string $cssBorderStyle + * * @return null|string */ protected static function mapBorderStyle($cssBorderStyle) @@ -902,25 +949,26 @@ protected static function mapBorderStyle($cssBorderStyle) } } - protected static function mapBorderColor(&$styles, $cssBorderColor) + protected static function mapBorderColor(&$styles, $cssBorderColor): void { $numColors = substr_count($cssBorderColor, '#'); if ($numColors === 1) { $styles['borderColor'] = trim($cssBorderColor, '#'); } elseif ($numColors > 1) { $colors = explode(' ', $cssBorderColor); - $borders = array('borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor'); - for ($i = 0; $i < min(4, $numColors, count($colors)); $i++) { + $borders = ['borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor']; + for ($i = 0; $i < min(4, $numColors, count($colors)); ++$i) { $styles[$borders[$i]] = trim($colors[$i], '#'); } } } /** - * Transforms a HTML/CSS alignment into a \PhpOffice\PhpWord\SimpleType\Jc + * Transforms a HTML/CSS alignment into a \PhpOffice\PhpWord\SimpleType\Jc. * * @param string $cssAlignment - * @return string|null + * + * @return null|string */ protected static function mapAlign($cssAlignment) { @@ -937,10 +985,11 @@ protected static function mapAlign($cssAlignment) } /** - * Transforms a HTML/CSS vertical alignment + * Transforms a HTML/CSS vertical alignment. * * @param string $alignment - * @return string|null + * + * @return null|string */ protected static function mapAlignVertical($alignment) { @@ -967,7 +1016,7 @@ protected static function mapAlignVertical($alignment) } /** - * Map list style for ordered list + * Map list style for ordered list. * * @param string $cssListType */ @@ -989,19 +1038,19 @@ protected static function mapListType($cssListType) } /** - * Parse line break + * Parse line break. * * @param \PhpOffice\PhpWord\Element\AbstractContainer $element */ - protected static function parseLineBreak($element) + protected static function parseLineBreak($element): void { $element->addTextBreak(); } /** - * Parse link node + * Parse link node. * - * @param \DOMNode $node + * @param DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element * @param array $styles */ @@ -1012,6 +1061,7 @@ protected static function parseLink($node, $element, &$styles) switch ($attribute->name) { case 'href': $target = $attribute->value; + break; } } @@ -1026,29 +1076,29 @@ protected static function parseLink($node, $element, &$styles) /** * Render horizontal rule - * Note: Word rule is not the same as HTML's
    since it does not support width and thus neither alignment + * Note: Word rule is not the same as HTML's
    since it does not support width and thus neither alignment. * - * @param \DOMNode $node + * @param DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element */ - protected static function parseHorizRule($node, $element) + protected static function parseHorizRule($node, $element): void { $styles = self::parseInlineStyle($node); //
    is implemented as an empty paragraph - extending 100% inside the section // Some properties may be controlled, e.g.
    - $fontStyle = $styles + array('size' => 3); + $fontStyle = $styles + ['size' => 3]; - $paragraphStyle = $styles + array( - 'lineHeight' => 0.25, // multiply default line height - e.g. 1, 1.5 etc - 'spacing' => 0, // twip - 'spaceBefore' => 120, // twip, 240/2 (default line height) - 'spaceAfter' => 120, // twip - 'borderBottomSize' => empty($styles['line-height']) ? 1 : $styles['line-height'], + $paragraphStyle = $styles + [ + 'lineHeight' => 0.25, // multiply default line height - e.g. 1, 1.5 etc + 'spacing' => 0, // twip + 'spaceBefore' => 120, // twip, 240/2 (default line height) + 'spaceAfter' => 120, // twip + 'borderBottomSize' => empty($styles['line-height']) ? 1 : $styles['line-height'], 'borderBottomColor' => empty($styles['color']) ? '000000' : $styles['color'], 'borderBottomStyle' => 'single', // same as "solid" - ); + ]; $element->addText('', $fontStyle, $paragraphStyle); diff --git a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php b/src/PhpWord/Shared/Microsoft/PasswordEncoder.php index fc0c7ecdf8..5ff42e49b9 100644 --- a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php +++ b/src/PhpWord/Shared/Microsoft/PasswordEncoder.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Shared\Microsoft; /** - * Password encoder for microsoft office applications + * Password encoder for microsoft office applications. */ class PasswordEncoder { @@ -35,26 +35,27 @@ class PasswordEncoder const ALGORITHM_HMAC = 'HMAC'; /** - * Mapping between algorithm name and algorithm ID + * Mapping between algorithm name and algorithm ID. * * @var array + * * @see https://msdn.microsoft.com/en-us/library/documentformat.openxml.wordprocessing.writeprotection.cryptographicalgorithmsid(v=office.14).aspx */ - private static $algorithmMapping = array( - self::ALGORITHM_MD2 => array(1, 'md2'), - self::ALGORITHM_MD4 => array(2, 'md4'), - self::ALGORITHM_MD5 => array(3, 'md5'), - self::ALGORITHM_SHA_1 => array(4, 'sha1'), - self::ALGORITHM_MAC => array(5, ''), // 'mac' -> not possible with hash() - self::ALGORITHM_RIPEMD => array(6, 'ripemd'), - self::ALGORITHM_RIPEMD_160 => array(7, 'ripemd160'), - self::ALGORITHM_HMAC => array(9, ''), //'hmac' -> not possible with hash() - self::ALGORITHM_SHA_256 => array(12, 'sha256'), - self::ALGORITHM_SHA_384 => array(13, 'sha384'), - self::ALGORITHM_SHA_512 => array(14, 'sha512'), - ); - - private static $initialCodeArray = array( + private static $algorithmMapping = [ + self::ALGORITHM_MD2 => [1, 'md2'], + self::ALGORITHM_MD4 => [2, 'md4'], + self::ALGORITHM_MD5 => [3, 'md5'], + self::ALGORITHM_SHA_1 => [4, 'sha1'], + self::ALGORITHM_MAC => [5, ''], // 'mac' -> not possible with hash() + self::ALGORITHM_RIPEMD => [6, 'ripemd'], + self::ALGORITHM_RIPEMD_160 => [7, 'ripemd160'], + self::ALGORITHM_HMAC => [9, ''], //'hmac' -> not possible with hash() + self::ALGORITHM_SHA_256 => [12, 'sha256'], + self::ALGORITHM_SHA_384 => [13, 'sha384'], + self::ALGORITHM_SHA_512 => [14, 'sha512'], + ]; + + private static $initialCodeArray = [ 0xE1F0, 0x1D0F, 0xCC9C, @@ -70,36 +71,38 @@ class PasswordEncoder 0x280C, 0xA96A, 0x4EC3, - ); - - private static $encryptionMatrix = array( - array(0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09), - array(0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF), - array(0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0), - array(0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40), - array(0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5), - array(0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A), - array(0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9), - array(0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0), - array(0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC), - array(0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10), - array(0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168), - array(0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C), - array(0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD), - array(0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC), - array(0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4), - ); + ]; + + private static $encryptionMatrix = [ + [0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09], + [0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF], + [0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0], + [0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40], + [0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5], + [0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A], + [0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9], + [0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0], + [0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC], + [0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10], + [0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168], + [0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C], + [0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD], + [0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC], + [0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4], + ]; private static $passwordMaxLength = 15; /** - * Create a hashed password that MS Word will be able to work with + * Create a hashed password that MS Word will be able to work with. + * * @see https://blogs.msdn.microsoft.com/vsod/2010/04/05/how-to-set-the-editing-restrictions-in-word-using-open-xml-sdk-2-0/ * * @param string $password * @param string $algorithmName * @param string $salt * @param int $spinCount + * * @return string */ public static function hashPassword($password, $algorithmName = self::ALGORITHM_SHA_1, $salt = null, $spinCount = 10000) @@ -112,9 +115,9 @@ public static function hashPassword($password, $algorithmName = self::ALGORITHM_ // Get the single-byte values by iterating through the Unicode characters of the truncated password. // For each character, if the low byte is not equal to 0, take it. Otherwise, take the high byte. $passUtf8 = mb_convert_encoding($password, 'UCS-2LE', 'UTF-8'); - $byteChars = array(); + $byteChars = []; - for ($i = 0; $i < mb_strlen($password); $i++) { + for ($i = 0; $i < mb_strlen($password); ++$i) { $byteChars[$i] = ord(substr($passUtf8, $i * 2, 1)); if ($byteChars[$i] == 0) { @@ -136,7 +139,7 @@ public static function hashPassword($password, $algorithmName = self::ALGORITHM_ $algorithm = self::getAlgorithm($algorithmName); $generatedKey = hash($algorithm, $salt . $generatedKey, true); - for ($i = 0; $i < $spinCount; $i++) { + for ($i = 0; $i < $spinCount; ++$i) { $generatedKey = hash($algorithm, $generatedKey . pack('CCCC', $i, $i >> 8, $i >> 16, $i >> 24), true); } $generatedKey = base64_encode($generatedKey); @@ -147,9 +150,10 @@ public static function hashPassword($password, $algorithmName = self::ALGORITHM_ } /** - * Get algorithm from self::$algorithmMapping + * Get algorithm from self::$algorithmMapping. * * @param string $algorithmName + * * @return string */ private static function getAlgorithm($algorithmName) @@ -163,9 +167,10 @@ private static function getAlgorithm($algorithmName) } /** - * Returns the algorithm ID + * Returns the algorithm ID. * * @param string $algorithmName + * * @return int */ public static function getAlgorithmId($algorithmName) @@ -174,9 +179,10 @@ public static function getAlgorithmId($algorithmName) } /** - * Build combined key from low-order word and high-order word + * Build combined key from low-order word and high-order word. * * @param array $byteChars byte array representation of password + * * @return int */ private static function buildCombinedKey($byteChars) @@ -190,10 +196,10 @@ private static function buildCombinedKey($byteChars) // For every bit in the character, starting with the least significant and progressing to (but excluding) // the most significant, if the bit is set, XOR the key’s high-order word with the corresponding word from // the Encryption Matrix - for ($i = 0; $i < $byteCharsLength; $i++) { + for ($i = 0; $i < $byteCharsLength; ++$i) { $tmp = self::$passwordMaxLength - $byteCharsLength + $i; $matrixRow = self::$encryptionMatrix[$tmp]; - for ($intBit = 0; $intBit < 7; $intBit++) { + for ($intBit = 0; $intBit < 7; ++$intBit) { if (($byteChars[$i] & (0x0001 << $intBit)) != 0) { $highOrderWord = ($highOrderWord ^ $matrixRow[$intBit]); } @@ -204,7 +210,7 @@ private static function buildCombinedKey($byteChars) // Initialize with 0 $lowOrderWord = 0; // For each character in the password, going backwards - for ($i = $byteCharsLength - 1; $i >= 0; $i--) { + for ($i = $byteCharsLength - 1; $i >= 0; --$i) { // low-order word = (((low-order word SHR 14) AND 0x0001) OR (low-order word SHL 1) AND 0x7FFF)) XOR character $lowOrderWord = (((($lowOrderWord >> 14) & 0x0001) | (($lowOrderWord << 1) & 0x7FFF)) ^ $byteChars[$i]); } @@ -216,10 +222,12 @@ private static function buildCombinedKey($byteChars) } /** - * Simulate behaviour of (signed) int32 + * Simulate behaviour of (signed) int32. * * @codeCoverageIgnore + * * @param int $value + * * @return int */ private static function int32($value) diff --git a/src/PhpWord/Shared/Text.php b/src/PhpWord/Shared/Text.php index c4a1ad620f..667d67ab4a 100644 --- a/src/PhpWord/Shared/Text.php +++ b/src/PhpWord/Shared/Text.php @@ -11,28 +11,28 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Shared; /** - * Text + * Text. */ class Text { /** - * Control characters array + * Control characters array. * * @var string[] */ - private static $controlCharacters = array(); + private static $controlCharacters = []; /** - * Build control characters array + * Build control characters array. */ - private static function buildControlCharacters() + private static function buildControlCharacters(): void { for ($i = 0; $i <= 19; ++$i) { if ($i != 9 && $i != 10 && $i != 13) { @@ -44,7 +44,7 @@ private static function buildControlCharacters() } /** - * Convert from PHP control character to OpenXML escaped control character + * Convert from PHP control character to OpenXML escaped control character. * * Excel 2007 team: * ---------------- @@ -55,6 +55,7 @@ private static function buildControlCharacters() * element or in the shared string element. * * @param string $value Value to escape + * * @return string */ public static function controlCharacterPHP2OOXML($value = '') @@ -67,9 +68,11 @@ public static function controlCharacterPHP2OOXML($value = '') } /** - * Return a number formatted for being integrated in xml files + * Return a number formatted for being integrated in xml files. + * * @param float $number * @param int $decimals + * * @return string */ public static function numberFormat($number, $decimals) @@ -79,8 +82,11 @@ public static function numberFormat($number, $decimals) /** * @param int $dec + * * @see http://stackoverflow.com/a/7153133/2235790 + * * @author velcrow + * * @return string */ public static function chr($dec) @@ -102,9 +108,10 @@ public static function chr($dec) } /** - * Convert from OpenXML escaped control character to PHP control character + * Convert from OpenXML escaped control character to PHP control character. * * @param string $value Value to unescape + * * @return string */ public static function controlCharacterOOXML2PHP($value = '') @@ -117,9 +124,10 @@ public static function controlCharacterOOXML2PHP($value = '') } /** - * Check if a string contains UTF-8 data + * Check if a string contains UTF-8 data. * * @param string $value + * * @return bool */ public static function isUTF8($value = '') @@ -128,14 +136,15 @@ public static function isUTF8($value = '') } /** - * Return UTF8 encoded value + * Return UTF8 encoded value. * * @param string $value + * * @return string */ public static function toUTF8($value = '') { - if (!is_null($value) && !self::isUTF8($value)) { + if (null !== $value && !self::isUTF8($value)) { $value = utf8_encode($value); } @@ -143,12 +152,14 @@ public static function toUTF8($value = '') } /** - * Returns unicode from UTF8 text + * Returns unicode from UTF8 text. * * The function is splitted to reduce cyclomatic complexity * * @param string $text UTF8 text + * * @return string Unicode text + * * @since 0.11.0 */ public static function toUnicode($text) @@ -157,21 +168,23 @@ public static function toUnicode($text) } /** - * Returns unicode array from UTF8 text + * Returns unicode array from UTF8 text. * * @param string $text UTF8 text + * * @return array + * * @since 0.11.0 * @see http://www.randomchaos.com/documents/?source=php_and_unicode */ public static function utf8ToUnicode($text) { - $unicode = array(); - $values = array(); + $unicode = []; + $values = []; $lookingFor = 1; // Gets unicode for each character - for ($i = 0; $i < strlen($text); $i++) { + for ($i = 0; $i < strlen($text); ++$i) { $thisValue = ord($text[$i]); if ($thisValue < 128) { $unicode[] = $thisValue; @@ -187,7 +200,7 @@ public static function utf8ToUnicode($text) $number = (($values[0] % 32) * 64) + ($values[1] % 64); } $unicode[] = $number; - $values = array(); + $values = []; $lookingFor = 1; } } @@ -197,10 +210,12 @@ public static function utf8ToUnicode($text) } /** - * Returns entites from unicode array + * Returns entites from unicode array. * * @param array $unicode + * * @return string + * * @since 0.11.0 * @see http://www.randomchaos.com/documents/?source=php_and_unicode */ @@ -218,14 +233,15 @@ private static function unicodeToEntities($unicode) } /** - * Return name without underscore for < 0.10.0 variable name compatibility + * Return name without underscore for < 0.10.0 variable name compatibility. * * @param string $value + * * @return string */ public static function removeUnderscorePrefix($value) { - if (!is_null($value)) { + if (null !== $value) { if (substr($value, 0, 1) == '_') { $value = substr($value, 1); } diff --git a/src/PhpWord/Shared/XMLReader.php b/src/PhpWord/Shared/XMLReader.php index 3905c52f19..73762db2ea 100644 --- a/src/PhpWord/Shared/XMLReader.php +++ b/src/PhpWord/Shared/XMLReader.php @@ -11,48 +11,56 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Shared; +use DOMDocument; +use DOMElement; +use DOMNodeList; +use DOMXpath; +use Exception; +use InvalidArgumentException; +use ZipArchive; + /** - * XML Reader wrapper + * XML Reader wrapper. * * @since 0.2.1 */ class XMLReader { /** - * DOMDocument object + * DOMDocument object. * - * @var \DOMDocument + * @var DOMDocument */ - private $dom = null; + private $dom; /** - * DOMXpath object + * DOMXpath object. * - * @var \DOMXpath + * @var DOMXpath */ - private $xpath = null; + private $xpath; /** - * Get DOMDocument from ZipArchive + * Get DOMDocument from ZipArchive. * * @param string $zipFile * @param string $xmlFile - * @throws \Exception - * @return \DOMDocument|false + * + * @return DOMDocument|false */ public function getDomFromZip($zipFile, $xmlFile) { if (file_exists($zipFile) === false) { - throw new \Exception('Cannot find archive file.'); + throw new Exception('Cannot find archive file.'); } - $zip = new \ZipArchive(); + $zip = new ZipArchive(); $zip->open($zipFile); $content = $zip->getFromName($xmlFile); $zip->close(); @@ -65,17 +73,18 @@ public function getDomFromZip($zipFile, $xmlFile) } /** - * Get DOMDocument from content string + * Get DOMDocument from content string. * * @param string $content - * @return \DOMDocument + * + * @return DOMDocument */ public function getDomFromString($content) { if (\PHP_VERSION_ID < 80000) { $originalLibXMLEntityValue = libxml_disable_entity_loader(true); } - $this->dom = new \DOMDocument(); + $this->dom = new DOMDocument(); $this->dom->loadXML($content); if (\PHP_VERSION_ID < 80000) { libxml_disable_entity_loader($originalLibXMLEntityValue); @@ -85,22 +94,23 @@ public function getDomFromString($content) } /** - * Get elements + * Get elements. * * @param string $path - * @param \DOMElement $contextNode - * @return \DOMNodeList + * @param DOMElement $contextNode + * + * @return DOMNodeList */ - public function getElements($path, \DOMElement $contextNode = null) + public function getElements($path, ?DOMElement $contextNode = null) { if ($this->dom === null) { - return array(); + return []; } if ($this->xpath === null) { - $this->xpath = new \DOMXpath($this->dom); + $this->xpath = new DOMXpath($this->dom); } - if (is_null($contextNode)) { + if (null === $contextNode) { return $this->xpath->query($path); } @@ -108,33 +118,34 @@ public function getElements($path, \DOMElement $contextNode = null) } /** - * Registers the namespace with the DOMXPath object + * Registers the namespace with the DOMXPath object. * * @param string $prefix The prefix * @param string $namespaceURI The URI of the namespace - * @throws \InvalidArgumentException If called before having loaded the DOM document + * * @return bool true on success or false on failure */ public function registerNamespace($prefix, $namespaceURI) { if ($this->dom === null) { - throw new \InvalidArgumentException('Dom needs to be loaded before registering a namespace'); + throw new InvalidArgumentException('Dom needs to be loaded before registering a namespace'); } if ($this->xpath === null) { - $this->xpath = new \DOMXpath($this->dom); + $this->xpath = new DOMXpath($this->dom); } return $this->xpath->registerNamespace($prefix, $namespaceURI); } /** - * Get element + * Get element. * * @param string $path - * @param \DOMElement $contextNode - * @return \DOMElement|null + * @param DOMElement $contextNode + * + * @return null|DOMElement */ - public function getElement($path, \DOMElement $contextNode = null) + public function getElement($path, ?DOMElement $contextNode = null) { $elements = $this->getElements($path, $contextNode); if ($elements->length > 0) { @@ -145,20 +156,21 @@ public function getElement($path, \DOMElement $contextNode = null) } /** - * Get element attribute + * Get element attribute. * * @param string $attribute - * @param \DOMElement $contextNode + * @param DOMElement $contextNode * @param string $path - * @return string|null + * + * @return null|string */ - public function getAttribute($attribute, \DOMElement $contextNode = null, $path = null) + public function getAttribute($attribute, ?DOMElement $contextNode = null, $path = null) { $return = null; if ($path !== null) { $elements = $this->getElements($path, $contextNode); if ($elements->length > 0) { - /** @var \DOMElement $node Type hint */ + /** @var DOMElement $node Type hint */ $node = $elements->item(0); $return = $node->getAttribute($attribute); } @@ -172,13 +184,14 @@ public function getAttribute($attribute, \DOMElement $contextNode = null, $path } /** - * Get element value + * Get element value. * * @param string $path - * @param \DOMElement $contextNode - * @return string|null + * @param DOMElement $contextNode + * + * @return null|string */ - public function getValue($path, \DOMElement $contextNode = null) + public function getValue($path, ?DOMElement $contextNode = null) { $elements = $this->getElements($path, $contextNode); if ($elements->length > 0) { @@ -189,13 +202,14 @@ public function getValue($path, \DOMElement $contextNode = null) } /** - * Count elements + * Count elements. * * @param string $path - * @param \DOMElement $contextNode + * @param DOMElement $contextNode + * * @return int */ - public function countElements($path, \DOMElement $contextNode = null) + public function countElements($path, ?DOMElement $contextNode = null) { $elements = $this->getElements($path, $contextNode); @@ -203,13 +217,14 @@ public function countElements($path, \DOMElement $contextNode = null) } /** - * Element exists + * Element exists. * * @param string $path - * @param \DOMElement $contextNode + * @param DOMElement $contextNode + * * @return bool */ - public function elementExists($path, \DOMElement $contextNode = null) + public function elementExists($path, ?DOMElement $contextNode = null) { return $this->getElements($path, $contextNode)->length > 0; } diff --git a/src/PhpWord/Shared/XMLWriter.php b/src/PhpWord/Shared/XMLWriter.php index 4d0afc5e13..9f51c0e514 100644 --- a/src/PhpWord/Shared/XMLWriter.php +++ b/src/PhpWord/Shared/XMLWriter.php @@ -11,14 +11,17 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Shared; +use Exception; +use ReturnTypeWillChange; + /** - * XMLWriter + * XMLWriter. * * @method bool endElement() * @method mixed flush(bool $empty = null) @@ -40,14 +43,14 @@ class XMLWriter extends \XMLWriter const STORAGE_DISK = 2; /** - * Temporary filename + * Temporary filename. * * @var string */ private $tempFileName = ''; /** - * Create a new \PhpOffice\PhpWord\Shared\XMLWriter instance + * Create a new \PhpOffice\PhpWord\Shared\XMLWriter instance. * * @param int $pTemporaryStorage Temporary storage location * @param string $pTemporaryStorageDir Temporary storage folder @@ -79,7 +82,7 @@ public function __construct($pTemporaryStorage = self::STORAGE_MEMORY, $pTempora } /** - * Destructor + * Destructor. */ public function __destruct() { @@ -88,12 +91,12 @@ public function __destruct() return; } if (PHP_OS != 'WINNT' && @unlink($this->tempFileName) === false) { - throw new \Exception('The file ' . $this->tempFileName . ' could not be deleted.'); + throw new Exception('The file ' . $this->tempFileName . ' could not be deleted.'); } } /** - * Get written data + * Get written data. * * @return string */ @@ -109,21 +112,21 @@ public function getData() } /** - * Write simple element and attribute(s) block + * Write simple element and attribute(s) block. * * There are two options: * 1. If the `$attributes` is an array, then it's an associative array of attributes * 2. If not, then it's a simple attribute-value pair * * @param string $element - * @param string|array $attributes + * @param array|string $attributes * @param string $value */ - public function writeElementBlock($element, $attributes, $value = null) + public function writeElementBlock($element, $attributes, $value = null): void { $this->startElement($element); if (!is_array($attributes)) { - $attributes = array($attributes => $value); + $attributes = [$attributes => $value]; } foreach ($attributes as $attribute => $value) { $this->writeAttribute($attribute, $value); @@ -139,10 +142,10 @@ public function writeElementBlock($element, $attributes, $value = null) * @param string $attribute * @param mixed $value */ - public function writeElementIf($condition, $element, $attribute = null, $value = null) + public function writeElementIf($condition, $element, $attribute = null, $value = null): void { if ($condition == true) { - if (is_null($attribute)) { + if (null === $attribute) { $this->writeElement($element, $value); } else { $this->startElement($element); @@ -159,7 +162,7 @@ public function writeElementIf($condition, $element, $attribute = null, $value = * @param string $attribute * @param mixed $value */ - public function writeAttributeIf($condition, $attribute, $value) + public function writeAttributeIf($condition, $attribute, $value): void { if ($condition == true) { $this->writeAttribute($attribute, $value); @@ -169,9 +172,10 @@ public function writeAttributeIf($condition, $attribute, $value) /** * @param string $name * @param mixed $value + * * @return bool */ - #[\ReturnTypeWillChange] + #[ReturnTypeWillChange] public function writeAttribute($name, $value) { if (is_float($value)) { diff --git a/src/PhpWord/Shared/ZipArchive.php b/src/PhpWord/Shared/ZipArchive.php index 6517ca8abf..74922b2c2b 100644 --- a/src/PhpWord/Shared/ZipArchive.php +++ b/src/PhpWord/Shared/ZipArchive.php @@ -11,17 +11,18 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Shared; +use PclZip; use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\Settings; /** - * ZipArchive wrapper + * ZipArchive wrapper. * * Wraps zip archive functionality of PHP ZipArchive and PCLZip. PHP ZipArchive * properties and methods are bypassed and used as the model for the PCLZip @@ -41,42 +42,42 @@ class ZipArchive const OVERWRITE = 8; // Emulate \ZipArchive::OVERWRITE /** - * Number of files (emulate ZipArchive::$numFiles) + * Number of files (emulate ZipArchive::$numFiles). * * @var int */ public $numFiles = 0; /** - * Archive filename (emulate ZipArchive::$filename) + * Archive filename (emulate ZipArchive::$filename). * * @var string */ public $filename; /** - * Temporary storage directory + * Temporary storage directory. * * @var string */ private $tempDir; /** - * Internal zip archive object + * Internal zip archive object. * - * @var \ZipArchive|\PclZip + * @var PclZip|\ZipArchive */ private $zip; /** - * Use PCLZip (default behaviour) + * Use PCLZip (default behaviour). * * @var bool */ private $usePclzip = true; /** - * Create new instance + * Create new instance. */ public function __construct() { @@ -90,12 +91,13 @@ public function __construct() } /** - * Catch function calls: pass to ZipArchive or PCLZip + * Catch function calls: pass to ZipArchive or PCLZip. * * `call_user_func_array` can only used for public function, hence the `public` in all `pcl...` methods * * @param mixed $function * @param mixed $args + * * @return mixed */ public function __call($function, $args) @@ -112,17 +114,18 @@ public function __call($function, $args) // Run function $result = false; if (method_exists($zipObject, $zipFunction)) { - $result = @call_user_func_array(array($zipObject, $zipFunction), $args); + $result = @call_user_func_array([$zipObject, $zipFunction], $args); } return $result; } /** - * Open a new zip archive + * Open a new zip archive. * * @param string $filename The file name of the ZIP archive to open * @param int $flags The mode to use to open the archive + * * @return bool */ public function open($filename, $flags = null) @@ -146,7 +149,7 @@ public function open($filename, $flags = null) // See https://github.com/scrutinizer-ci/php-analyzer/issues/190 $this->numFiles = $zip->numFiles; } else { - $zip = new \PclZip($this->filename); + $zip = new PclZip($this->filename); $zipContent = $zip->listContent(); $this->numFiles = is_array($zipContent) ? count($zipContent) : 0; } @@ -156,9 +159,7 @@ public function open($filename, $flags = null) } /** - * Close the active archive - * - * @throws \PhpOffice\PhpWord\Exception\Exception + * Close the active archive. * * @return bool * @@ -176,11 +177,13 @@ public function close() } /** - * Extract the archive contents (emulate \ZipArchive) + * Extract the archive contents (emulate \ZipArchive). * * @param string $destination - * @param string|array $entries + * @param array|string $entries + * * @return bool + * * @since 0.10.0 */ public function extractTo($destination, $entries = null) @@ -197,9 +200,10 @@ public function extractTo($destination, $entries = null) } /** - * Extract file from archive by given file name (emulate \ZipArchive) + * Extract file from archive by given file name (emulate \ZipArchive). * * @param string $filename Filename for the file in zip archive + * * @return string $contents File string contents */ public function getFromName($filename) @@ -218,15 +222,16 @@ public function getFromName($filename) } /** - * Add a new file to the zip archive (emulate \ZipArchive) + * Add a new file to the zip archive (emulate \ZipArchive). * * @param string $filename Directory/Name of the file to add to the zip archive * @param string $localname Directory/Name of the file added to the zip + * * @return bool */ public function pclzipAddFile($filename, $localname = null) { - /** @var \PclZip $zip Type hint */ + /** @var PclZip $zip Type hint */ $zip = $this->zip; // Bugfix GH-261 https://github.com/PHPOffice/PHPWord/pull/261 @@ -269,15 +274,16 @@ public function pclzipAddFile($filename, $localname = null) } /** - * Add a new file to the zip archive from a string of raw data (emulate \ZipArchive) + * Add a new file to the zip archive from a string of raw data (emulate \ZipArchive). * * @param string $localname Directory/Name of the file to add to the zip archive * @param string $contents String of data to add to the zip archive + * * @return bool */ public function pclzipAddFromString($localname, $contents) { - /** @var \PclZip $zip Type hint */ + /** @var PclZip $zip Type hint */ $zip = $this->zip; $filenameParts = pathinfo($localname); @@ -300,20 +306,22 @@ public function pclzipAddFromString($localname, $contents) } /** - * Extract the archive contents (emulate \ZipArchive) + * Extract the archive contents (emulate \ZipArchive). * * @param string $destination - * @param string|array $entries + * @param array|string $entries + * * @return bool + * * @since 0.10.0 */ public function pclzipExtractTo($destination, $entries = null) { - /** @var \PclZip $zip Type hint */ + /** @var PclZip $zip Type hint */ $zip = $this->zip; // Extract all files - if (is_null($entries)) { + if (null === $entries) { $result = $zip->extract(PCLZIP_OPT_PATH, $destination); return $result > 0; @@ -321,7 +329,7 @@ public function pclzipExtractTo($destination, $entries = null) // Extract by entries if (!is_array($entries)) { - $entries = array($entries); + $entries = [$entries]; } foreach ($entries as $entry) { $entryIndex = $this->locateName($entry); @@ -335,14 +343,15 @@ public function pclzipExtractTo($destination, $entries = null) } /** - * Extract file from archive by given file name (emulate \ZipArchive) + * Extract file from archive by given file name (emulate \ZipArchive). * * @param string $filename Filename for the file in zip archive + * * @return string $contents File string contents */ public function pclzipGetFromName($filename) { - /** @var \PclZip $zip Type hint */ + /** @var PclZip $zip Type hint */ $zip = $this->zip; $listIndex = $this->pclzipLocateName($filename); $contents = false; @@ -362,15 +371,17 @@ public function pclzipGetFromName($filename) } /** - * Returns the name of an entry using its index (emulate \ZipArchive) + * Returns the name of an entry using its index (emulate \ZipArchive). * * @param int $index - * @return string|bool + * + * @return bool|string + * * @since 0.10.0 */ public function pclzipGetNameIndex($index) { - /** @var \PclZip $zip Type hint */ + /** @var PclZip $zip Type hint */ $zip = $this->zip; $list = $zip->listContent(); if (isset($list[$index])) { @@ -381,14 +392,15 @@ public function pclzipGetNameIndex($index) } /** - * Returns the index of the entry in the archive (emulate \ZipArchive) + * Returns the index of the entry in the archive (emulate \ZipArchive). * * @param string $filename Filename for the file in zip archive + * * @return int */ public function pclzipLocateName($filename) { - /** @var \PclZip $zip Type hint */ + /** @var PclZip $zip Type hint */ $zip = $this->zip; $list = $zip->listContent(); $listCount = count($list); @@ -397,6 +409,7 @@ public function pclzipLocateName($filename) if (strtolower($list[$i]['filename']) == strtolower($filename) || strtolower($list[$i]['stored_filename']) == strtolower($filename)) { $listIndex = $i; + break; } } diff --git a/src/PhpWord/SimpleType/Border.php b/src/PhpWord/SimpleType/Border.php index a73c7b4a67..6cb42f0467 100644 --- a/src/PhpWord/SimpleType/Border.php +++ b/src/PhpWord/SimpleType/Border.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -23,7 +23,6 @@ * Border Styles. * * @since 0.18.0 - * * @see http://www.datypic.com/sc/ooxml/t-w_ST_Border.html */ final class Border extends AbstractEnum diff --git a/src/PhpWord/SimpleType/DocProtect.php b/src/PhpWord/SimpleType/DocProtect.php index e386913d53..2d13485493 100644 --- a/src/PhpWord/SimpleType/DocProtect.php +++ b/src/PhpWord/SimpleType/DocProtect.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,36 +20,35 @@ use PhpOffice\PhpWord\Shared\AbstractEnum; /** - * Document Protection Types + * Document Protection Types. * * @since 0.14.0 - * * @see http://www.datypic.com/sc/ooxml/t-w_ST_DocProtect.html */ final class DocProtect extends AbstractEnum { /** - * No Editing Restrictions + * No Editing Restrictions. */ const NONE = 'none'; /** - * Allow No Editing + * Allow No Editing. */ const READ_ONLY = 'readOnly'; /** - * Allow Editing of Comments + * Allow Editing of Comments. */ const COMMENTS = 'comments'; /** - * Allow Editing With Revision Tracking + * Allow Editing With Revision Tracking. */ const TRACKED_CHANGES = 'trackedChanges'; /** - * Allow Editing of Form Fields + * Allow Editing of Form Fields. */ const FORMS = 'forms'; } diff --git a/src/PhpWord/SimpleType/Jc.php b/src/PhpWord/SimpleType/Jc.php index e55f824d14..ab665822c4 100644 --- a/src/PhpWord/SimpleType/Jc.php +++ b/src/PhpWord/SimpleType/Jc.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -26,7 +26,6 @@ * Since ISO/IEC-29500:2008 the type must not be used for table alignment. * * @since 0.13.0 - * * @see \PhpOffice\PhpWord\SimpleType\JcTable For table alignment modes available since ISO/IEC-29500:2008. * @see http://www.datypic.com/sc/ooxml/t-w_ST_Jc.html */ diff --git a/src/PhpWord/SimpleType/JcTable.php b/src/PhpWord/SimpleType/JcTable.php index 924a4f2014..86a1b03462 100644 --- a/src/PhpWord/SimpleType/JcTable.php +++ b/src/PhpWord/SimpleType/JcTable.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/SimpleType/LineSpacingRule.php b/src/PhpWord/SimpleType/LineSpacingRule.php index 8fd8340c43..833b626953 100644 --- a/src/PhpWord/SimpleType/LineSpacingRule.php +++ b/src/PhpWord/SimpleType/LineSpacingRule.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,26 +20,25 @@ use PhpOffice\PhpWord\Shared\AbstractEnum; /** - * Line Spacing Rule + * Line Spacing Rule. * * @since 0.14.0 - * * @see http://www.datypic.com/sc/ooxml/t-w_ST_LineSpacingRule.html */ final class LineSpacingRule extends AbstractEnum { /** - * Automatically Determined Line Height + * Automatically Determined Line Height. */ const AUTO = 'auto'; /** - * Exact Line Height + * Exact Line Height. */ const EXACT = 'exact'; /** - * Minimum Line Height + * Minimum Line Height. */ const AT_LEAST = 'atLeast'; } diff --git a/src/PhpWord/SimpleType/NumberFormat.php b/src/PhpWord/SimpleType/NumberFormat.php index 83da66fa3f..36a678e8ce 100644 --- a/src/PhpWord/SimpleType/NumberFormat.php +++ b/src/PhpWord/SimpleType/NumberFormat.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -23,7 +23,6 @@ * Numbering Format. * * @since 0.14.0 - * * @see http://www.datypic.com/sc/ooxml/t-w_ST_NumberFormat.html. */ final class NumberFormat extends AbstractEnum diff --git a/src/PhpWord/SimpleType/TblWidth.php b/src/PhpWord/SimpleType/TblWidth.php index 7fd753deb0..28ba0db2d1 100644 --- a/src/PhpWord/SimpleType/TblWidth.php +++ b/src/PhpWord/SimpleType/TblWidth.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,10 +20,9 @@ use PhpOffice\PhpWord\Shared\AbstractEnum; /** - * Table Width Units + * Table Width Units. * * @since 0.15.0 - * * @see http://www.datypic.com/sc/ooxml/t-w_ST_TblWidth.html */ final class TblWidth extends AbstractEnum diff --git a/src/PhpWord/SimpleType/TextAlignment.php b/src/PhpWord/SimpleType/TextAlignment.php index 838b0c5e0e..1f2af0fd89 100644 --- a/src/PhpWord/SimpleType/TextAlignment.php +++ b/src/PhpWord/SimpleType/TextAlignment.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,10 +20,9 @@ use PhpOffice\PhpWord\Shared\AbstractEnum; /** - * Magnification Preset Values + * Magnification Preset Values. * * @since 0.14.0 - * * @see http://www.datypic.com/sc/ooxml/t-w_ST_TextAlignment.html */ final class TextAlignment extends AbstractEnum diff --git a/src/PhpWord/SimpleType/VerticalJc.php b/src/PhpWord/SimpleType/VerticalJc.php index 2a37de417d..147cd20910 100644 --- a/src/PhpWord/SimpleType/VerticalJc.php +++ b/src/PhpWord/SimpleType/VerticalJc.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/SimpleType/Zoom.php b/src/PhpWord/SimpleType/Zoom.php index 02c38fdb6a..fc53ec8ff3 100644 --- a/src/PhpWord/SimpleType/Zoom.php +++ b/src/PhpWord/SimpleType/Zoom.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,10 +20,9 @@ use PhpOffice\PhpWord\Shared\AbstractEnum; /** - * Magnification Preset Values + * Magnification Preset Values. * * @since 0.14.0 - * * @see http://www.datypic.com/sc/ooxml/t-w_ST_Zoom.html */ final class Zoom extends AbstractEnum diff --git a/src/PhpWord/Style.php b/src/PhpWord/Style.php index 62783b6301..23107ef535 100644 --- a/src/PhpWord/Style.php +++ b/src/PhpWord/Style.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -24,22 +24,23 @@ use PhpOffice\PhpWord\Style\Table; /** - * Style collection + * Style collection. */ class Style { /** - * Style register + * Style register. * * @var array */ - private static $styles = array(); + private static $styles = []; /** - * Add paragraph style + * Add paragraph style. * * @param string $styleName * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styles + * * @return \PhpOffice\PhpWord\Style\Paragraph */ public static function addParagraphStyle($styleName, $styles) @@ -48,11 +49,12 @@ public static function addParagraphStyle($styleName, $styles) } /** - * Add font style + * Add font style. * * @param string $styleName * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $fontStyle * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $paragraphStyle + * * @return \PhpOffice\PhpWord\Style\Font */ public static function addFontStyle($styleName, $fontStyle, $paragraphStyle = null) @@ -61,10 +63,11 @@ public static function addFontStyle($styleName, $fontStyle, $paragraphStyle = nu } /** - * Add link style + * Add link style. * * @param string $styleName * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styles + * * @return \PhpOffice\PhpWord\Style\Font */ public static function addLinkStyle($styleName, $styles) @@ -73,11 +76,13 @@ public static function addLinkStyle($styleName, $styles) } /** - * Add numbering style + * Add numbering style. * * @param string $styleName * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styleValues + * * @return \PhpOffice\PhpWord\Style\Numbering + * * @since 0.10.0 */ public static function addNumberingStyle($styleName, $styleValues) @@ -86,11 +91,12 @@ public static function addNumberingStyle($styleName, $styleValues) } /** - * Add title style + * Add title style. * - * @param int|null $depth Provide null to set title font + * @param null|int $depth Provide null to set title font * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $fontStyle * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $paragraphStyle + * * @return \PhpOffice\PhpWord\Style\Font */ public static function addTitleStyle($depth, $fontStyle, $paragraphStyle = null) @@ -105,11 +111,12 @@ public static function addTitleStyle($depth, $fontStyle, $paragraphStyle = null) } /** - * Add table style + * Add table style. * * @param string $styleName * @param array $styleTable - * @param array|null $styleFirstRow + * @param null|array $styleFirstRow + * * @return \PhpOffice\PhpWord\Style\Table */ public static function addTableStyle($styleName, $styleTable, $styleFirstRow = null) @@ -118,9 +125,10 @@ public static function addTableStyle($styleName, $styleTable, $styleFirstRow = n } /** - * Count styles + * Count styles. * * @return int + * * @since 0.10.0 */ public static function countStyles() @@ -133,15 +141,16 @@ public static function countStyles() * * @since 0.10.0 */ - public static function resetStyles() + public static function resetStyles(): void { - self::$styles = array(); + self::$styles = []; } /** - * Set default paragraph style + * Set default paragraph style. * * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styles Paragraph style definition + * * @return \PhpOffice\PhpWord\Style\Paragraph */ public static function setDefaultParagraphStyle($styles) @@ -150,7 +159,7 @@ public static function setDefaultParagraphStyle($styles) } /** - * Get all styles + * Get all styles. * * @return \PhpOffice\PhpWord\Style\AbstractStyle[] */ @@ -160,9 +169,10 @@ public static function getStyles() } /** - * Get style by name + * Get style by name. * * @param string $styleName + * * @return \PhpOffice\PhpWord\Style\AbstractStyle Paragraph|Font|Table|Numbering */ public static function getStyle($styleName) @@ -175,13 +185,14 @@ public static function getStyle($styleName) } /** - * Set style values and put it to static style collection + * Set style values and put it to static style collection. * * 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($name, $style, $value = null) diff --git a/src/PhpWord/Style/AbstractStyle.php b/src/PhpWord/Style/AbstractStyle.php index aca6635faa..d3e1e81877 100644 --- a/src/PhpWord/Style/AbstractStyle.php +++ b/src/PhpWord/Style/AbstractStyle.php @@ -11,54 +11,56 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; +use InvalidArgumentException; use PhpOffice\PhpWord\Shared\Text; /** - * Abstract style class + * Abstract style class. * * @since 0.10.0 */ abstract class AbstractStyle { /** - * Style name + * Style name. * * @var string */ protected $styleName; /** - * Index number in Style collection for named style + * Index number in Style collection for named style. * * This number starts from one and defined in Style::setStyleValues() * - * @var int|null + * @var null|int */ protected $index; /** - * Aliases + * Aliases. * * @var array */ - protected $aliases = array(); + protected $aliases = []; /** - * Is this an automatic style? (Used primarily in OpenDocument driver) + * Is this an automatic style? (Used primarily in OpenDocument driver). * * @var bool + * * @since 0.11.0 */ private $isAuto = false; /** - * Get style name + * Get style name. * * @return string */ @@ -68,9 +70,10 @@ public function getStyleName() } /** - * Set style name + * Set style name. * * @param string $value + * * @return self */ public function setStyleName($value) @@ -81,9 +84,9 @@ public function setStyleName($value) } /** - * Get index number + * Get index number. * - * @return int|null + * @return null|int */ public function getIndex() { @@ -91,9 +94,10 @@ public function getIndex() } /** - * Set index number + * Set index number. + * + * @param null|int $value * - * @param int|null $value * @return self */ public function setIndex($value = null) @@ -104,7 +108,7 @@ public function setIndex($value = null) } /** - * Get is automatic style flag + * Get is automatic style flag. * * @return bool */ @@ -114,9 +118,10 @@ public function isAuto() } /** - * Set is automatic style flag + * Set is automatic style flag. * * @param bool $value + * * @return self */ public function setAuto($value = true) @@ -127,11 +132,13 @@ public function setAuto($value = true) } /** - * Return style value of child style object, e.g. `left` from `Indentation` child style of `Paragraph` + * Return style value of child style object, e.g. `left` from `Indentation` child style of `Paragraph`. * * @param \PhpOffice\PhpWord\Style\AbstractStyle $substyleObject * @param string $substyleProperty + * * @return mixed + * * @since 0.12.0 */ public function getChildStyleValue($substyleObject, $substyleProperty) @@ -146,7 +153,7 @@ public function getChildStyleValue($substyleObject, $substyleProperty) } /** - * Set style value template method + * Set style value template method. * * Some child classes have their own specific overrides. * Backward compability check for versions < 0.10.0 which use underscore @@ -155,6 +162,7 @@ public function getChildStyleValue($substyleObject, $substyleProperty) * * @param string $key * @param string $value + * * @return self */ public function setStyleValue($key, $value) @@ -171,12 +179,13 @@ public function setStyleValue($key, $value) } /** - * Set style by using associative array + * Set style by using associative array. * * @param array $values + * * @return self */ - public function setStyleByArray($values = array()) + public function setStyleByArray($values = []) { foreach ($values as $key => $value) { $this->setStyleValue($key, $value); @@ -186,10 +195,11 @@ public function setStyleByArray($values = array()) } /** - * Set default for null and empty value + * Set default for null and empty value. * * @param string $value (was: mixed) * @param string $default (was: mixed) + * * @return string (was: mixed) */ protected function setNonEmptyVal($value, $default) @@ -202,10 +212,11 @@ protected function setNonEmptyVal($value, $default) } /** - * Set bool value + * Set bool value. * * @param bool $value * @param bool $default + * * @return bool */ protected function setBoolVal($value, $default) @@ -218,11 +229,12 @@ protected function setBoolVal($value, $default) } /** - * Set numeric value + * Set numeric value. * * @param mixed $value - * @param int|float|null $default - * @return int|float|null + * @param null|float|int $default + * + * @return null|float|int */ protected function setNumericVal($value, $default = null) { @@ -234,11 +246,12 @@ protected function setNumericVal($value, $default = null) } /** - * Set integer value: Convert string that contains only numeric into integer + * Set integer value: Convert string that contains only numeric into integer. + * + * @param null|int $value + * @param null|int $default * - * @param int|null $value - * @param int|null $default - * @return int|null + * @return null|int */ protected function setIntVal($value, $default = null) { @@ -255,11 +268,12 @@ protected function setIntVal($value, $default = null) } /** - * Set float value: Convert string that contains only numeric into float + * Set float value: Convert string that contains only numeric into float. * * @param mixed $value - * @param float|null $default - * @return float|null + * @param null|float $default + * + * @return null|float */ protected function setFloatVal($value, $default = null) { @@ -274,19 +288,18 @@ protected function setFloatVal($value, $default = null) } /** - * Set enum value + * Set enum value. * * @param mixed $value * @param array $enum * @param mixed $default * - * @throws \InvalidArgumentException * @return mixed */ - protected function setEnumVal($value = null, $enum = array(), $default = null) + protected function setEnumVal($value = null, $enum = [], $default = null) { if ($value != null && trim($value) != '' && !empty($enum) && !in_array($value, $enum)) { - throw new \InvalidArgumentException("Invalid style value: {$value} Options:" . implode(',', $enum)); + throw new InvalidArgumentException("Invalid style value: {$value} Options:" . implode(',', $enum)); } elseif ($value === null || trim($value) == '') { $value = $default; } @@ -295,16 +308,17 @@ protected function setEnumVal($value = null, $enum = array(), $default = null) } /** - * Set object value + * Set object value. * * @param mixed $value * @param string $styleName * @param mixed &$style + * * @return mixed */ protected function setObjectVal($value, $styleName, &$style) { - $styleClass = substr(get_class($this), 0, strrpos(get_class($this), '\\')) . '\\' . $styleName; + $styleClass = substr(static::class, 0, strrpos(static::class, '\\')) . '\\' . $styleName; if (is_array($value)) { /** @var \PhpOffice\PhpWord\Style\AbstractStyle $style Type hint */ if (!$style instanceof $styleClass) { @@ -319,11 +333,12 @@ protected function setObjectVal($value, $styleName, &$style) } /** - * Set $property value and set $pairProperty = false when $value = true + * Set $property value and set $pairProperty = false when $value = true. * * @param bool &$property * @param bool &$pairProperty * @param bool $value + * * @return self */ protected function setPairedVal(&$property, &$pairProperty, $value) @@ -337,17 +352,15 @@ protected function setPairedVal(&$property, &$pairProperty, $value) } /** - * Set style using associative array + * Set style using associative array. * * @deprecated 0.11.0 * - * @param array $style - * * @return self * * @codeCoverageIgnore */ - public function setArrayStyle(array $style = array()) + public function setArrayStyle(array $style = []) { return $this->setStyleByArray($style); } diff --git a/src/PhpWord/Style/Border.php b/src/PhpWord/Style/Border.php index d032d07faa..2ee69be56f 100644 --- a/src/PhpWord/Style/Border.php +++ b/src/PhpWord/Style/Border.php @@ -11,120 +11,121 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * Border style + * Border style. */ class Border extends AbstractStyle { /** - * Border Top Size + * Border Top Size. * - * @var int|float + * @var float|int */ protected $borderTopSize; /** - * Border Top Color + * Border Top Color. * * @var string */ protected $borderTopColor; /** - * Border Top Style + * Border Top Style. * * @var string */ protected $borderTopStyle; /** - * Border Left Size + * Border Left Size. * - * @var int|float + * @var float|int */ protected $borderLeftSize; /** - * Border Left Color + * Border Left Color. * * @var string */ protected $borderLeftColor; /** - * Border Left Style + * Border Left Style. * * @var string */ protected $borderLeftStyle; /** - * Border Right Size + * Border Right Size. * - * @var int|float + * @var float|int */ protected $borderRightSize; /** - * Border Right Color + * Border Right Color. * * @var string */ protected $borderRightColor; /** - * Border Right Style + * Border Right Style. * * @var string */ protected $borderRightStyle; /** - * Border Bottom Size + * Border Bottom Size. * - * @var int|float + * @var float|int */ protected $borderBottomSize; /** - * Border Bottom Color + * Border Bottom Color. * * @var string */ protected $borderBottomColor; /** - * Border Bottom Style + * Border Bottom Style. * * @var string */ protected $borderBottomStyle; /** - * Get border size + * Get border size. * * @return int[] */ public function getBorderSize() { - return array( + return [ $this->getBorderTopSize(), $this->getBorderLeftSize(), $this->getBorderRightSize(), $this->getBorderBottomSize(), - ); + ]; } /** - * Set border size + * Set border size. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setBorderSize($value = null) @@ -138,24 +139,25 @@ public function setBorderSize($value = null) } /** - * Get border color + * Get border color. * * @return string[] */ public function getBorderColor() { - return array( + return [ $this->getBorderTopColor(), $this->getBorderLeftColor(), $this->getBorderRightColor(), $this->getBorderBottomColor(), - ); + ]; } /** - * Set border color + * Set border color. * * @param string $value + * * @return self */ public function setBorderColor($value = null) @@ -169,24 +171,25 @@ public function setBorderColor($value = null) } /** - * Get border style + * Get border style. * * @return string[] */ public function getBorderStyle() { - return array( + return [ $this->getBorderTopStyle(), $this->getBorderLeftStyle(), $this->getBorderRightStyle(), $this->getBorderBottomStyle(), - ); + ]; } /** - * Set border style + * Set border style. * * @param string $value + * * @return self */ public function setBorderStyle($value = null) @@ -200,9 +203,9 @@ public function setBorderStyle($value = null) } /** - * Get border top size + * Get border top size. * - * @return int|float + * @return float|int */ public function getBorderTopSize() { @@ -210,9 +213,10 @@ public function getBorderTopSize() } /** - * Set border top size + * Set border top size. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setBorderTopSize($value = null) @@ -223,7 +227,7 @@ public function setBorderTopSize($value = null) } /** - * Get border top color + * Get border top color. * * @return string */ @@ -233,9 +237,10 @@ public function getBorderTopColor() } /** - * Set border top color + * Set border top color. * * @param string $value + * * @return self */ public function setBorderTopColor($value = null) @@ -246,7 +251,7 @@ public function setBorderTopColor($value = null) } /** - * Get border top style + * Get border top style. * * @return string */ @@ -256,9 +261,10 @@ public function getBorderTopStyle() } /** - * Set border top Style + * Set border top Style. * * @param string $value + * * @return self */ public function setBorderTopStyle($value = null) @@ -269,9 +275,9 @@ public function setBorderTopStyle($value = null) } /** - * Get border left size + * Get border left size. * - * @return int|float + * @return float|int */ public function getBorderLeftSize() { @@ -279,9 +285,10 @@ public function getBorderLeftSize() } /** - * Set border left size + * Set border left size. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setBorderLeftSize($value = null) @@ -292,7 +299,7 @@ public function setBorderLeftSize($value = null) } /** - * Get border left color + * Get border left color. * * @return string */ @@ -302,9 +309,10 @@ public function getBorderLeftColor() } /** - * Set border left color + * Set border left color. * * @param string $value + * * @return self */ public function setBorderLeftColor($value = null) @@ -315,7 +323,7 @@ public function setBorderLeftColor($value = null) } /** - * Get border left style + * Get border left style. * * @return string */ @@ -325,9 +333,10 @@ public function getBorderLeftStyle() } /** - * Set border left style + * Set border left style. * * @param string $value + * * @return self */ public function setBorderLeftStyle($value = null) @@ -338,9 +347,9 @@ public function setBorderLeftStyle($value = null) } /** - * Get border right size + * Get border right size. * - * @return int|float + * @return float|int */ public function getBorderRightSize() { @@ -348,9 +357,10 @@ public function getBorderRightSize() } /** - * Set border right size + * Set border right size. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setBorderRightSize($value = null) @@ -361,7 +371,7 @@ public function setBorderRightSize($value = null) } /** - * Get border right color + * Get border right color. * * @return string */ @@ -371,9 +381,10 @@ public function getBorderRightColor() } /** - * Set border right color + * Set border right color. * * @param string $value + * * @return self */ public function setBorderRightColor($value = null) @@ -384,7 +395,7 @@ public function setBorderRightColor($value = null) } /** - * Get border right style + * Get border right style. * * @return string */ @@ -394,9 +405,10 @@ public function getBorderRightStyle() } /** - * Set border right style + * Set border right style. * * @param string $value + * * @return self */ public function setBorderRightStyle($value = null) @@ -407,9 +419,9 @@ public function setBorderRightStyle($value = null) } /** - * Get border bottom size + * Get border bottom size. * - * @return int|float + * @return float|int */ public function getBorderBottomSize() { @@ -417,9 +429,10 @@ public function getBorderBottomSize() } /** - * Set border bottom size + * Set border bottom size. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setBorderBottomSize($value = null) @@ -430,7 +443,7 @@ public function setBorderBottomSize($value = null) } /** - * Get border bottom color + * Get border bottom color. * * @return string */ @@ -440,9 +453,10 @@ public function getBorderBottomColor() } /** - * Set border bottom color + * Set border bottom color. * * @param string $value + * * @return self */ public function setBorderBottomColor($value = null) @@ -453,7 +467,7 @@ public function setBorderBottomColor($value = null) } /** - * Get border bottom style + * Get border bottom style. * * @return string */ @@ -463,9 +477,10 @@ public function getBorderBottomStyle() } /** - * Set border bottom style + * Set border bottom style. * * @param string $value + * * @return self */ public function setBorderBottomStyle($value = null) @@ -476,7 +491,7 @@ public function setBorderBottomStyle($value = null) } /** - * Check if any of the border is not null + * Check if any of the border is not null. * * @return bool */ diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index 1276b5b59a..420f8dc50c 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,14 +21,15 @@ use PhpOffice\PhpWord\SimpleType\VerticalJc; /** - * Table cell style + * Table cell style. */ class Cell extends Border { /** - * Vertical alignment constants + * Vertical alignment constants. * * @const string + * * @deprecated Use \PhpOffice\PhpWord\SimpleType\VerticalJc::TOP instead */ const VALIGN_TOP = 'top'; @@ -47,32 +48,32 @@ class Cell extends Border //Text direction constants /** - * Left to Right, Top to Bottom + * Left to Right, Top to Bottom. */ const TEXT_DIR_LRTB = 'lrTb'; /** - * Top to Bottom, Right to Left + * Top to Bottom, Right to Left. */ const TEXT_DIR_TBRL = 'tbRl'; /** - * Bottom to Top, Left to Right + * Bottom to Top, Left to Right. */ const TEXT_DIR_BTLR = 'btLr'; /** - * Left to Right, Top to Bottom Rotated + * Left to Right, Top to Bottom Rotated. */ const TEXT_DIR_LRTBV = 'lrTbV'; /** - * Top to Bottom, Right to Left Rotated + * Top to Bottom, Right to Left Rotated. */ const TEXT_DIR_TBRLV = 'tbRlV'; /** - * Top to Bottom, Left to Right Rotated + * Top to Bottom, Left to Right Rotated. */ const TEXT_DIR_TBLRV = 'tbLrV'; /** - * Vertical merge (rowspan) constants + * Vertical merge (rowspan) constants. * * @const string */ @@ -80,35 +81,35 @@ class Cell extends Border const VMERGE_CONTINUE = 'continue'; /** - * Default border color + * Default border color. * * @const string */ const DEFAULT_BORDER_COLOR = '000000'; /** - * Vertical align (top, center, both, bottom) + * Vertical align (top, center, both, bottom). * * @var string */ private $vAlign; /** - * Text Direction + * Text Direction. * * @var string */ private $textDirection; /** - * colspan + * colspan. * * @var int */ private $gridSpan; /** - * rowspan (restart, continue) + * rowspan (restart, continue). * * - restart: Start/restart merged region * - continue: Continue merged region @@ -118,21 +119,21 @@ class Cell extends Border private $vMerge; /** - * Shading + * Shading. * * @var \PhpOffice\PhpWord\Style\Shading */ private $shading; /** - * Width + * Width. * * @var int */ private $width; /** - * Width unit + * Width unit. * * @var string */ @@ -149,9 +150,10 @@ public function getVAlign() } /** - * Set vertical align + * Set vertical align. * * @param string $value + * * @return self */ public function setVAlign($value = null) @@ -173,21 +175,22 @@ public function getTextDirection() } /** - * Set text direction + * Set text direction. * * @param string $value + * * @return self */ public function setTextDirection($value = null) { - $enum = array(self::TEXT_DIR_BTLR, self::TEXT_DIR_TBRL); + $enum = [self::TEXT_DIR_BTLR, self::TEXT_DIR_TBRL]; $this->textDirection = $this->setEnumVal($value, $enum, $this->textDirection); return $this; } /** - * Get background + * Get background. * * @return string */ @@ -201,14 +204,15 @@ public function getBgColor() } /** - * Set background + * Set background. * * @param string $value + * * @return self */ public function setBgColor($value = null) { - return $this->setShading(array('fill' => $value)); + return $this->setShading(['fill' => $value]); } /** @@ -222,9 +226,10 @@ public function getGridSpan() } /** - * Set grid span (colspan) + * Set grid span (colspan). * * @param int $value + * * @return self */ public function setGridSpan($value = null) @@ -245,21 +250,22 @@ public function getVMerge() } /** - * Set vertical merge (rowspan) + * Set vertical merge (rowspan). * * @param string $value + * * @return self */ public function setVMerge($value = null) { - $enum = array(self::VMERGE_RESTART, self::VMERGE_CONTINUE); + $enum = [self::VMERGE_RESTART, self::VMERGE_CONTINUE]; $this->vMerge = $this->setEnumVal($value, $enum, $this->vMerge); return $this; } /** - * Get shading + * Get shading. * * @return \PhpOffice\PhpWord\Style\Shading */ @@ -269,9 +275,10 @@ public function getShading() } /** - * Set shading + * Set shading. * * @param mixed $value + * * @return self */ public function setShading($value = null) @@ -282,7 +289,7 @@ public function setShading($value = null) } /** - * Get cell width + * Get cell width. * * @return int */ @@ -292,9 +299,10 @@ public function getWidth() } /** - * Set cell width + * Set cell width. * * @param int $value + * * @return self */ public function setWidth($value) @@ -305,7 +313,7 @@ public function setWidth($value) } /** - * Get width unit + * Get width unit. * * @return string */ @@ -315,19 +323,19 @@ public function getUnit() } /** - * Set width unit + * Set width unit. * * @param string $value */ public function setUnit($value) { - $this->unit = $this->setEnumVal($value, array(TblWidth::AUTO, TblWidth::PERCENT, TblWidth::TWIP), TblWidth::TWIP); + $this->unit = $this->setEnumVal($value, [TblWidth::AUTO, TblWidth::PERCENT, TblWidth::TWIP], TblWidth::TWIP); return $this; } /** - * Get default border color + * Get default border color. * * @deprecated 0.10.0 * diff --git a/src/PhpWord/Style/Chart.php b/src/PhpWord/Style/Chart.php index c02c0af4d8..9dbc8db0a6 100644 --- a/src/PhpWord/Style/Chart.php +++ b/src/PhpWord/Style/Chart.php @@ -11,56 +11,56 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * Chart style + * Chart style. * * @since 0.12.0 */ class Chart extends AbstractStyle { /** - * Width (in EMU) + * Width (in EMU). * * @var int */ private $width = 1000000; /** - * Height (in EMU) + * Height (in EMU). * * @var int */ private $height = 1000000; /** - * Is 3D; applies to pie, bar, line, area + * Is 3D; applies to pie, bar, line, area. * * @var bool */ private $is3d = false; /** - * A list of colors to use in the chart + * A list of colors to use in the chart. * * @var array */ - private $colors = array(); + private $colors = []; /** - * Chart title + * Chart title. * * @var string */ - private $title = null; + private $title; /** - * Chart legend visibility + * Chart legend visibility. * * @var bool */ @@ -68,32 +68,32 @@ class Chart extends AbstractStyle /** * Chart legend Position. - * Possible values are 'r', 't', 'b', 'l', 'tr' + * Possible values are 'r', 't', 'b', 'l', 'tr'. * * @var string */ private $legendPosition = 'r'; /** - * A list of display options for data labels + * A list of display options for data labels. * * @var array */ - private $dataLabelOptions = array( - 'showVal' => true, // value - 'showCatName' => true, // category name - 'showLegendKey' => false, //show the cart legend - 'showSerName' => false, // series name - 'showPercent' => false, - 'showLeaderLines' => false, - 'showBubbleSize' => false, - ); + private $dataLabelOptions = [ + 'showVal' => true, // value + 'showCatName' => true, // category name + 'showLegendKey' => false, //show the cart legend + 'showSerName' => false, // series name + 'showPercent' => false, + 'showLeaderLines' => false, + 'showBubbleSize' => false, + ]; /** * A string that tells the writer where to write chart labels or to skip * "nextTo" - sets labels next to the axis (bar graphs on the left) (default) * "low" - labels on the left side of the graph - * "high" - labels on the right side of the graph + * "high" - labels on the right side of the graph. * * @var string */ @@ -103,7 +103,7 @@ class Chart extends AbstractStyle * A string that tells the writer where to write chart labels or to skip * "nextTo" - sets labels next to the axis (bar graphs on the bottom) (default) * "low" - labels are below the graph - * "high" - labels above the graph + * "high" - labels above the graph. * * @var string */ @@ -121,45 +121,45 @@ class Chart extends AbstractStyle /** * The position for major tick marks - * Possible values are 'in', 'out', 'cross', 'none' + * Possible values are 'in', 'out', 'cross', 'none'. * * @var string */ private $majorTickMarkPos = 'none'; /** - * Show labels for axis + * Show labels for axis. * * @var bool */ private $showAxisLabels = false; /** - * Show Gridlines for Y-Axis + * Show Gridlines for Y-Axis. * * @var bool */ private $gridY = false; /** - * Show Gridlines for X-Axis + * Show Gridlines for X-Axis. * * @var bool */ private $gridX = false; /** - * Create a new instance + * Create a new instance. * * @param array $style */ - public function __construct($style = array()) + public function __construct($style = []) { $this->setStyleByArray($style); } /** - * Get width + * Get width. * * @return int */ @@ -169,9 +169,10 @@ public function getWidth() } /** - * Set width + * Set width. * * @param int $value + * * @return self */ public function setWidth($value = null) @@ -182,7 +183,7 @@ public function setWidth($value = null) } /** - * Get height + * Get height. * * @return int */ @@ -192,9 +193,10 @@ public function getHeight() } /** - * Set height + * Set height. * * @param int $value + * * @return self */ public function setHeight($value = null) @@ -205,7 +207,7 @@ public function setHeight($value = null) } /** - * Is 3D + * Is 3D. * * @return bool */ @@ -215,9 +217,10 @@ public function is3d() } /** - * Set 3D + * Set 3D. * * @param bool $value + * * @return self */ public function set3d($value = true) @@ -241,9 +244,10 @@ public function getColors() * Set the colors to use in a chart. * * @param array $value a list of colors to use in the chart + * * @return self */ - public function setColors($value = array()) + public function setColors($value = []) { $this->colors = $value; @@ -251,7 +255,7 @@ public function setColors($value = array()) } /** - * Get the chart title + * Get the chart title. * * @return string */ @@ -261,9 +265,10 @@ public function getTitle() } /** - * Set the chart title + * Set the chart title. * * @param string $value + * * @return self */ public function setTitle($value = null) @@ -274,7 +279,7 @@ public function setTitle($value = null) } /** - * Get chart legend visibility + * Get chart legend visibility. * * @return bool */ @@ -284,9 +289,10 @@ public function isShowLegend() } /** - * Set chart legend visibility + * Set chart legend visibility. * * @param bool $value + * * @return self */ public function setShowLegend($value = false) @@ -297,7 +303,7 @@ public function setShowLegend($value = false) } /** - * Get chart legend position + * Get chart legend position. * * @return string */ @@ -312,16 +318,17 @@ public function getLegendPosition() * "b" - bottom of chart * "t" - top of chart * "l" - left of chart - * "tr" - top right of chart + * "tr" - top right of chart. * * default: right * * @param string $legendPosition + * * @return self */ public function setLegendPosition($legendPosition = 'r') { - $enum = array('r', 'b', 't', 'l', 'tr'); + $enum = ['r', 'b', 't', 'l', 'tr']; $this->legendPosition = $this->setEnumVal($legendPosition, $enum, $this->legendPosition); return $this; @@ -338,9 +345,10 @@ public function showAxisLabels() } /** - * Set show Gridlines for Y-Axis + * Set show Gridlines for Y-Axis. * * @param bool $value + * * @return self */ public function setShowAxisLabels($value = true) @@ -351,7 +359,7 @@ public function setShowAxisLabels($value = true) } /** - * get the list of options for data labels + * get the list of options for data labels. * * @return array */ @@ -366,7 +374,7 @@ public function getDataLabelOptions() * * @param array $values [description] */ - public function setDataLabelOptions($values = array()) + public function setDataLabelOptions($values = []): void { foreach (array_keys($this->dataLabelOptions) as $option) { if (isset($values[$option])) { @@ -389,9 +397,10 @@ public function showGridY() } /** - * Set show Gridlines for Y-Axis + * Set show Gridlines for Y-Axis. * * @param bool $value + * * @return self */ public function setShowGridY($value = true) @@ -402,7 +411,7 @@ public function setShowGridY($value = true) } /** - * Get the categoryLabelPosition setting + * Get the categoryLabelPosition setting. * * @return string */ @@ -416,21 +425,22 @@ public function getCategoryLabelPosition() * "none" - skips writing labels * "nextTo" - sets labels next to the (bar graphs on the left) * "low" - labels on the left side of the graph - * "high" - labels on the right side of the graph + * "high" - labels on the right side of the graph. * * @param mixed $labelPosition + * * @return self */ public function setCategoryLabelPosition($labelPosition) { - $enum = array('nextTo', 'low', 'high'); + $enum = ['nextTo', 'low', 'high']; $this->categoryLabelPosition = $this->setEnumVal($labelPosition, $enum, $this->categoryLabelPosition); return $this; } /** - * Get the valueAxisLabelPosition setting + * Get the valueAxisLabelPosition setting. * * @return string */ @@ -444,21 +454,22 @@ public function getValueLabelPosition() * "none" - skips writing labels * "nextTo" - sets labels next to the value * "low" - sets labels are below the graph - * "high" - sets labels above the graph + * "high" - sets labels above the graph. * * @param string * @param mixed $labelPosition */ public function setValueLabelPosition($labelPosition) { - $enum = array('nextTo', 'low', 'high'); + $enum = ['nextTo', 'low', 'high']; $this->valueLabelPosition = $this->setEnumVal($labelPosition, $enum, $this->valueLabelPosition); return $this; } /** - * Get the categoryAxisTitle + * Get the categoryAxisTitle. + * * @return string */ public function getCategoryAxisTitle() @@ -467,7 +478,8 @@ public function getCategoryAxisTitle() } /** - * Set the title that appears on the category side of the chart + * Set the title that appears on the category side of the chart. + * * @param string $axisTitle */ public function setCategoryAxisTitle($axisTitle) @@ -478,7 +490,8 @@ public function setCategoryAxisTitle($axisTitle) } /** - * Get the valueAxisTitle + * Get the valueAxisTitle. + * * @return string */ public function getValueAxisTitle() @@ -487,7 +500,8 @@ public function getValueAxisTitle() } /** - * Set the title that appears on the value side of the chart + * Set the title that appears on the value side of the chart. + * * @param string $axisTitle */ public function setValueAxisTitle($axisTitle) @@ -503,17 +517,18 @@ public function getMajorTickPosition() } /** - * Set the position for major tick marks + * Set the position for major tick marks. + * * @param string $position */ - public function setMajorTickPosition($position) + public function setMajorTickPosition($position): void { - $enum = array('in', 'out', 'cross', 'none'); + $enum = ['in', 'out', 'cross', 'none']; $this->majorTickMarkPos = $this->setEnumVal($position, $enum, $this->majorTickMarkPos); } /** - * Show Gridlines for X-Axis + * Show Gridlines for X-Axis. * * @return bool */ @@ -523,9 +538,10 @@ public function showGridX() } /** - * Set show Gridlines for X-Axis + * Set show Gridlines for X-Axis. * * @param bool $value + * * @return self */ public function setShowGridX($value = true) diff --git a/src/PhpWord/Style/Extrusion.php b/src/PhpWord/Style/Extrusion.php index 4c860bcd63..dd00231223 100644 --- a/src/PhpWord/Style/Extrusion.php +++ b/src/PhpWord/Style/Extrusion.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * 3D extrusion style + * 3D extrusion style. * * @see http://www.schemacentral.com/sc/ooxml/t-o_CT_Extrusion.html * @since 0.12.0 @@ -26,7 +26,7 @@ class Extrusion extends AbstractStyle { /** - * Type constants + * Type constants. * * @const string */ @@ -34,31 +34,31 @@ class Extrusion extends AbstractStyle const EXTRUSION_PERSPECTIVE = 'perspective'; /** - * Type: parallel|perspective + * Type: parallel|perspective. * * @var string */ private $type; /** - * Color + * Color. * * @var string */ private $color; /** - * Create a new instance + * Create a new instance. * * @param array $style */ - public function __construct($style = array()) + public function __construct($style = []) { $this->setStyleByArray($style); } /** - * Get type + * Get type. * * @return string */ @@ -68,21 +68,22 @@ public function getType() } /** - * Set pattern + * Set pattern. * * @param string $value + * * @return self */ public function setType($value = null) { - $enum = array(self::EXTRUSION_PARALLEL, self::EXTRUSION_PERSPECTIVE); + $enum = [self::EXTRUSION_PARALLEL, self::EXTRUSION_PERSPECTIVE]; $this->type = $this->setEnumVal($value, $enum, null); return $this; } /** - * Get color + * Get color. * * @return string */ @@ -92,9 +93,10 @@ public function getColor() } /** - * Set color + * Set color. * * @param string $value + * * @return self */ public function setColor($value = null) diff --git a/src/PhpWord/Style/Fill.php b/src/PhpWord/Style/Fill.php index 360bcf3f0c..af0149d0fe 100644 --- a/src/PhpWord/Style/Fill.php +++ b/src/PhpWord/Style/Fill.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * Fill style + * Fill style. * * There are still lot of interesting things for this style that can be added, including gradient. See @see . * @@ -28,24 +28,24 @@ class Fill extends AbstractStyle { /** - * Color + * Color. * * @var string */ private $color; /** - * Create a new instance + * Create a new instance. * * @param array $style */ - public function __construct($style = array()) + public function __construct($style = []) { $this->setStyleByArray($style); } /** - * Get color + * Get color. * * @return string */ @@ -55,9 +55,10 @@ public function getColor() } /** - * Set color + * Set color. * * @param string $value + * * @return self */ public function setColor($value = null) diff --git a/src/PhpWord/Style/Font.php b/src/PhpWord/Style/Font.php index 09e6f1a2f3..ea072c6a2d 100644 --- a/src/PhpWord/Style/Font.php +++ b/src/PhpWord/Style/Font.php @@ -11,19 +11,19 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * Font style + * Font style. */ class Font extends AbstractStyle { /** - * Underline types + * Underline types. * * @const string */ @@ -55,7 +55,7 @@ class Font extends AbstractStyle const UNDERLINE_WORDS = 'words'; /** - * Foreground colors + * Foreground colors. * * @const string */ @@ -76,169 +76,174 @@ class Font extends AbstractStyle const FGCOLOR_BLACK = 'black'; /** - * Aliases + * Aliases. * * @var array */ - protected $aliases = array('line-height' => 'lineHeight', 'letter-spacing' => 'spacing'); + protected $aliases = ['line-height' => 'lineHeight', 'letter-spacing' => 'spacing']; /** - * Font style type + * Font style type. * * @var string */ private $type; /** - * Font name + * Font name. * * @var string */ private $name; /** - * Font Content Type + * Font Content Type. * * @var string */ private $hint; /** - * Font size + * Font size. * - * @var int|float + * @var float|int */ private $size; /** - * Font color + * Font color. * * @var string */ private $color; /** - * Bold + * Bold. * * @var bool */ private $bold; /** - * Italic + * Italic. * * @var bool */ private $italic; /** - * Undeline + * Undeline. * * @var string */ private $underline = self::UNDERLINE_NONE; /** - * Superscript + * Superscript. * * @var bool */ private $superScript = false; /** - * Subscript + * Subscript. * * @var bool */ private $subScript = false; /** - * Strikethrough + * Strikethrough. * * @var bool */ private $strikethrough; /** - * Double strikethrough + * Double strikethrough. * * @var bool */ private $doubleStrikethrough; /** - * Small caps + * Small caps. * * @var bool + * * @see http://www.schemacentral.com/sc/ooxml/e-w_smallCaps-1.html */ private $smallCaps; /** - * All caps + * All caps. * * @var bool + * * @see http://www.schemacentral.com/sc/ooxml/e-w_caps-1.html */ private $allCaps; /** - * Foreground/highlight + * Foreground/highlight. * * @var string */ private $fgColor; /** - * Expanded/compressed text: 0-600 (percent) + * Expanded/compressed text: 0-600 (percent). * * @var int + * * @since 0.12.0 * @see http://www.schemacentral.com/sc/ooxml/e-w_w-1.html */ private $scale; /** - * Character spacing adjustment: twip + * Character spacing adjustment: twip. + * + * @var float|int * - * @var int|float * @since 0.12.0 * @see http://www.schemacentral.com/sc/ooxml/e-w_spacing-2.html */ private $spacing; /** - * Font kerning: halfpoint + * Font kerning: halfpoint. + * + * @var float|int * - * @var int|float * @since 0.12.0 * @see http://www.schemacentral.com/sc/ooxml/e-w_kern-1.html */ private $kerning; /** - * Paragraph style + * Paragraph style. * * @var \PhpOffice\PhpWord\Style\Paragraph */ private $paragraph; /** - * Shading + * Shading. * * @var \PhpOffice\PhpWord\Style\Shading */ private $shading; /** - * Right to left languages + * Right to left languages. * * @var bool */ private $rtl; /** - * noProof (disables AutoCorrect) + * noProof (disables AutoCorrect). * * @var bool * http://www.datypic.com/sc/ooxml/e-w_noProof-1.html @@ -246,33 +251,35 @@ class Font extends AbstractStyle private $noProof; /** - * Languages + * Languages. * * @var \PhpOffice\PhpWord\Style\Language */ private $lang; /** - * Hidden text + * Hidden text. * * @var bool + * * @see http://www.datypic.com/sc/ooxml/e-w_vanish-1.html */ private $hidden; /** - * Vertically Raised or Lowered Text + * Vertically Raised or Lowered Text. * * @var int Signed Half-Point Measurement + * * @see http://www.datypic.com/sc/ooxml/e-w_position-1.html */ private $position; /** - * Create new font style + * Create new font style. * * @param string $type Type of font - * @param array|string|\PhpOffice\PhpWord\Style\AbstractStyle $paragraph Paragraph styles definition + * @param array|\PhpOffice\PhpWord\Style\AbstractStyle|string $paragraph Paragraph styles definition */ public function __construct($type = 'text', $paragraph = null) { @@ -281,51 +288,52 @@ public function __construct($type = 'text', $paragraph = null) } /** - * Get style values + * Get style values. * * @return array + * * @since 0.12.0 */ public function getStyleValues() { - $styles = array( - 'name' => $this->getStyleName(), - 'basic' => array( - 'name' => $this->getName(), - 'size' => $this->getSize(), - 'color' => $this->getColor(), - 'hint' => $this->getHint(), - ), - 'style' => array( - 'bold' => $this->isBold(), - 'italic' => $this->isItalic(), + $styles = [ + 'name' => $this->getStyleName(), + 'basic' => [ + 'name' => $this->getName(), + 'size' => $this->getSize(), + 'color' => $this->getColor(), + 'hint' => $this->getHint(), + ], + 'style' => [ + 'bold' => $this->isBold(), + 'italic' => $this->isItalic(), 'underline' => $this->getUnderline(), - 'strike' => $this->isStrikethrough(), - 'dStrike' => $this->isDoubleStrikethrough(), - 'super' => $this->isSuperScript(), - 'sub' => $this->isSubScript(), + 'strike' => $this->isStrikethrough(), + 'dStrike' => $this->isDoubleStrikethrough(), + 'super' => $this->isSuperScript(), + 'sub' => $this->isSubScript(), 'smallCaps' => $this->isSmallCaps(), - 'allCaps' => $this->isAllCaps(), - 'fgColor' => $this->getFgColor(), - 'hidden' => $this->isHidden(), - ), - 'spacing' => array( - 'scale' => $this->getScale(), - 'spacing' => $this->getSpacing(), - 'kerning' => $this->getKerning(), - 'position' => $this->getPosition(), - ), - 'paragraph' => $this->getParagraph(), - 'rtl' => $this->isRTL(), - 'shading' => $this->getShading(), - 'lang' => $this->getLang(), - ); + 'allCaps' => $this->isAllCaps(), + 'fgColor' => $this->getFgColor(), + 'hidden' => $this->isHidden(), + ], + 'spacing' => [ + 'scale' => $this->getScale(), + 'spacing' => $this->getSpacing(), + 'kerning' => $this->getKerning(), + 'position' => $this->getPosition(), + ], + 'paragraph' => $this->getParagraph(), + 'rtl' => $this->isRTL(), + 'shading' => $this->getShading(), + 'lang' => $this->getLang(), + ]; return $styles; } /** - * Get style type + * Get style type. * * @return string */ @@ -335,7 +343,7 @@ public function getStyleType() } /** - * Get font name + * Get font name. * * @return string */ @@ -345,9 +353,10 @@ public function getName() } /** - * Set font name + * Set font name. * * @param string $value + * * @return self */ public function setName($value = null) @@ -358,7 +367,7 @@ public function setName($value = null) } /** - * Get Font Content Type + * Get Font Content Type. * * @return string */ @@ -368,9 +377,10 @@ public function getHint() } /** - * Set Font Content Type + * Set Font Content Type. * * @param string $value + * * @return self */ public function setHint($value = null) @@ -381,9 +391,9 @@ public function setHint($value = null) } /** - * Get font size + * Get font size. * - * @return int|float + * @return float|int */ public function getSize() { @@ -391,9 +401,10 @@ public function getSize() } /** - * Set font size + * Set font size. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setSize($value = null) @@ -404,7 +415,7 @@ public function setSize($value = null) } /** - * Get font color + * Get font color. * * @return string */ @@ -414,9 +425,10 @@ public function getColor() } /** - * Set font color + * Set font color. * * @param string $value + * * @return self */ public function setColor($value = null) @@ -427,7 +439,7 @@ public function setColor($value = null) } /** - * Get bold + * Get bold. * * @return bool */ @@ -437,9 +449,10 @@ public function isBold() } /** - * Set bold + * Set bold. * * @param bool $value + * * @return self */ public function setBold($value = true) @@ -450,7 +463,7 @@ public function setBold($value = true) } /** - * Get italic + * Get italic. * * @return bool */ @@ -460,9 +473,10 @@ public function isItalic() } /** - * Set italic + * Set italic. * * @param bool $value + * * @return self */ public function setItalic($value = true) @@ -473,7 +487,7 @@ public function setItalic($value = true) } /** - * Get underline + * Get underline. * * @return string */ @@ -483,9 +497,10 @@ public function getUnderline() } /** - * Set underline + * Set underline. * * @param string $value + * * @return self */ public function setUnderline($value = self::UNDERLINE_NONE) @@ -496,7 +511,7 @@ public function setUnderline($value = self::UNDERLINE_NONE) } /** - * Get superscript + * Get superscript. * * @return bool */ @@ -506,9 +521,10 @@ public function isSuperScript() } /** - * Set superscript + * Set superscript. * * @param bool $value + * * @return self */ public function setSuperScript($value = true) @@ -517,7 +533,7 @@ public function setSuperScript($value = true) } /** - * Get subscript + * Get subscript. * * @return bool */ @@ -527,9 +543,10 @@ public function isSubScript() } /** - * Set subscript + * Set subscript. * * @param bool $value + * * @return self */ public function setSubScript($value = true) @@ -538,7 +555,7 @@ public function setSubScript($value = true) } /** - * Get strikethrough + * Get strikethrough. * * @return bool */ @@ -548,9 +565,10 @@ public function isStrikethrough() } /** - * Set strikethrough + * Set strikethrough. * * @param bool $value + * * @return self */ public function setStrikethrough($value = true) @@ -559,7 +577,7 @@ public function setStrikethrough($value = true) } /** - * Get double strikethrough + * Get double strikethrough. * * @return bool */ @@ -569,9 +587,10 @@ public function isDoubleStrikethrough() } /** - * Set double strikethrough + * Set double strikethrough. * * @param bool $value + * * @return self */ public function setDoubleStrikethrough($value = true) @@ -580,7 +599,7 @@ public function setDoubleStrikethrough($value = true) } /** - * Get small caps + * Get small caps. * * @return bool */ @@ -590,9 +609,10 @@ public function isSmallCaps() } /** - * Set small caps + * Set small caps. * * @param bool $value + * * @return self */ public function setSmallCaps($value = true) @@ -601,7 +621,7 @@ public function setSmallCaps($value = true) } /** - * Get all caps + * Get all caps. * * @return bool */ @@ -611,9 +631,10 @@ public function isAllCaps() } /** - * Set all caps + * Set all caps. * * @param bool $value + * * @return self */ public function setAllCaps($value = true) @@ -622,7 +643,7 @@ public function setAllCaps($value = true) } /** - * Get foreground/highlight color + * Get foreground/highlight color. * * @return string */ @@ -632,9 +653,10 @@ public function getFgColor() } /** - * Set foreground/highlight color + * Set foreground/highlight color. * * @param string $value + * * @return self */ public function setFgColor($value = null) @@ -645,7 +667,7 @@ public function setFgColor($value = null) } /** - * Get background + * Get background. * * @return string */ @@ -655,18 +677,19 @@ public function getBgColor() } /** - * Set background + * Set background. * * @param string $value + * * @return \PhpOffice\PhpWord\Style\Table */ public function setBgColor($value = null) { - $this->setShading(array('fill' => $value)); + $this->setShading(['fill' => $value]); } /** - * Get scale + * Get scale. * * @return int */ @@ -676,9 +699,10 @@ public function getScale() } /** - * Set scale + * Set scale. * * @param int $value + * * @return self */ public function setScale($value = null) @@ -689,9 +713,9 @@ public function setScale($value = null) } /** - * Get font spacing + * Get font spacing. * - * @return int|float + * @return float|int */ public function getSpacing() { @@ -699,9 +723,10 @@ public function getSpacing() } /** - * Set font spacing + * Set font spacing. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setSpacing($value = null) @@ -712,9 +737,9 @@ public function setSpacing($value = null) } /** - * Get font kerning + * Get font kerning. * - * @return int|float + * @return float|int */ public function getKerning() { @@ -722,9 +747,10 @@ public function getKerning() } /** - * Set font kerning + * Set font kerning. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setKerning($value = null) @@ -735,7 +761,7 @@ public function setKerning($value = null) } /** - * Get noProof (disables autocorrect) + * Get noProof (disables autocorrect). * * @return bool */ @@ -745,9 +771,10 @@ public function isNoProof() } /** - * Set noProof (disables autocorrect) + * Set noProof (disables autocorrect). * * @param bool $value + * * @return $this */ public function setNoProof($value = false) @@ -758,9 +785,9 @@ public function setNoProof($value = false) } /** - * Get line height + * Get line height. * - * @return int|float + * @return float|int */ public function getLineHeight() { @@ -768,20 +795,21 @@ public function getLineHeight() } /** - * Set lineheight + * Set lineheight. + * + * @param float|int|string $value * - * @param int|float|string $value * @return self */ public function setLineHeight($value) { - $this->setParagraph(array('lineHeight' => $value)); + $this->setParagraph(['lineHeight' => $value]); return $this; } /** - * Get paragraph style + * Get paragraph style. * * @return \PhpOffice\PhpWord\Style\Paragraph */ @@ -791,9 +819,10 @@ public function getParagraph() } /** - * Set Paragraph + * Set Paragraph. * * @param mixed $value + * * @return self */ public function setParagraph($value = null) @@ -804,7 +833,7 @@ public function setParagraph($value = null) } /** - * Get rtl + * Get rtl. * * @return bool */ @@ -814,9 +843,10 @@ public function isRTL() } /** - * Set rtl + * Set rtl. * * @param bool $value + * * @return self */ public function setRTL($value = true) @@ -827,7 +857,7 @@ public function setRTL($value = true) } /** - * Get shading + * Get shading. * * @return \PhpOffice\PhpWord\Style\Shading */ @@ -837,9 +867,10 @@ public function getShading() } /** - * Set shading + * Set shading. * * @param mixed $value + * * @return self */ public function setShading($value = null) @@ -850,7 +881,7 @@ public function setShading($value = null) } /** - * Get language + * Get language. * * @return \PhpOffice\PhpWord\Style\Language */ @@ -860,9 +891,10 @@ public function getLang() } /** - * Set language + * Set language. * * @param mixed $value + * * @return self */ public function setLang($value = null) @@ -876,7 +908,7 @@ public function setLang($value = null) } /** - * Get bold + * Get bold. * * @deprecated 0.10.0 * @@ -888,7 +920,7 @@ public function getBold() } /** - * Get italic + * Get italic. * * @deprecated 0.10.0 * @@ -900,7 +932,7 @@ public function getItalic() } /** - * Get superscript + * Get superscript. * * @deprecated 0.10.0 * @@ -912,7 +944,7 @@ public function getSuperScript() } /** - * Get subscript + * Get subscript. * * @deprecated 0.10.0 * @@ -924,7 +956,7 @@ public function getSubScript() } /** - * Get strikethrough + * Get strikethrough. * * @deprecated 0.10.0 * @@ -936,7 +968,7 @@ public function getStrikethrough() } /** - * Get paragraph style + * Get paragraph style. * * @deprecated 0.11.0 * @@ -948,7 +980,7 @@ public function getParagraphStyle() } /** - * Get hidden text + * Get hidden text. * * @return bool */ @@ -958,9 +990,10 @@ public function isHidden() } /** - * Set hidden text + * Set hidden text. * * @param bool $value + * * @return self */ public function setHidden($value = true) @@ -971,7 +1004,7 @@ public function setHidden($value = true) } /** - * Get position + * Get position. * * @return int */ @@ -981,9 +1014,10 @@ public function getPosition() } /** - * Set position + * Set position. * * @param int $value + * * @return self */ public function setPosition($value = null) diff --git a/src/PhpWord/Style/Frame.php b/src/PhpWord/Style/Frame.php index e87b7a803a..489c56b26f 100644 --- a/src/PhpWord/Style/Frame.php +++ b/src/PhpWord/Style/Frame.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,17 +20,18 @@ use PhpOffice\PhpWord\SimpleType\Jc; /** - * Frame defines the size and position of an object + * Frame defines the size and position of an object. * * Width, height, left/hpos, top/vpos, hrel, vrel, wrap, zindex * * @since 0.12.0 + * * @todo Make existing style (image, textbox, etc) use this style */ class Frame extends AbstractStyle { /** - * Length unit + * Length unit. * * @const string */ @@ -46,7 +47,7 @@ class Frame extends AbstractStyle const POS_RELATIVE = 'relative'; /** - * Horizontal/vertical value + * Horizontal/vertical value. * * @const string */ @@ -59,7 +60,7 @@ class Frame extends AbstractStyle const POS_OUTSIDE = 'outside'; /** - * Position relative to + * Position relative to. * * @const string */ @@ -77,7 +78,7 @@ class Frame extends AbstractStyle const POS_RELTO_OMARGIN = 'outer-margin-area'; /** - * Wrap type + * Wrap type. * * @const string */ @@ -95,124 +96,125 @@ class Frame extends AbstractStyle private $alignment = ''; /** - * Unit + * Unit. * * @var string */ private $unit = 'pt'; /** - * Width + * Width. * - * @var int|float + * @var float|int */ private $width; /** - * Height + * Height. * - * @var int|float + * @var float|int */ private $height; /** - * Leftmost (horizontal) position + * Leftmost (horizontal) position. * - * @var int|float + * @var float|int */ private $left = 0; /** - * Topmost (vertical) position + * Topmost (vertical) position. * - * @var int|float + * @var float|int */ private $top = 0; /** - * Position type: absolute|relative + * Position type: absolute|relative. * * @var string */ private $pos; /** - * Horizontal position + * Horizontal position. * * @var string */ private $hPos; /** - * Horizontal position relative to + * Horizontal position relative to. * * @var string */ private $hPosRelTo; /** - * Vertical position + * Vertical position. * * @var string */ private $vPos; /** - * Vertical position relative to + * Vertical position relative to. * * @var string */ private $vPosRelTo; /** - * Wrap type + * Wrap type. * * @var string */ private $wrap; /** - * Top wrap distance + * Top wrap distance. * * @var float */ private $wrapDistanceTop; /** - * Bottom wrap distance + * Bottom wrap distance. * * @var float */ private $wrapDistanceBottom; /** - * Left wrap distance + * Left wrap distance. * * @var float */ private $wrapDistanceLeft; /** - * Right wrap distance + * Right wrap distance. * * @var float */ private $wrapDistanceRight; /** - * Vertically raised or lowered text + * Vertically raised or lowered text. * * @var int + * * @see http://www.datypic.com/sc/ooxml/e-w_position-1.html */ private $position; /** - * Create a new instance + * Create a new instance. * * @param array $style */ - public function __construct($style = array()) + public function __construct($style = []) { $this->setStyleByArray($style); } @@ -270,7 +272,7 @@ public function setAlign($value = null) } /** - * Get unit + * Get unit. * * @return string */ @@ -280,9 +282,10 @@ public function getUnit() } /** - * Set unit + * Set unit. * * @param string $value + * * @return self */ public function setUnit($value) @@ -293,9 +296,9 @@ public function setUnit($value) } /** - * Get width + * Get width. * - * @return int|float + * @return float|int */ public function getWidth() { @@ -303,9 +306,10 @@ public function getWidth() } /** - * Set width + * Set width. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setWidth($value = null) @@ -316,9 +320,9 @@ public function setWidth($value = null) } /** - * Get height + * Get height. * - * @return int|float + * @return float|int */ public function getHeight() { @@ -326,9 +330,10 @@ public function getHeight() } /** - * Set height + * Set height. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setHeight($value = null) @@ -339,9 +344,9 @@ public function setHeight($value = null) } /** - * Get left + * Get left. * - * @return int|float + * @return float|int */ public function getLeft() { @@ -349,9 +354,10 @@ public function getLeft() } /** - * Set left + * Set left. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setLeft($value = 0) @@ -362,9 +368,9 @@ public function setLeft($value = 0) } /** - * Get topmost position + * Get topmost position. * - * @return int|float + * @return float|int */ public function getTop() { @@ -372,9 +378,10 @@ public function getTop() } /** - * Set topmost position + * Set topmost position. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setTop($value = 0) @@ -385,7 +392,7 @@ public function setTop($value = 0) } /** - * Get position type + * Get position type. * * @return string */ @@ -395,24 +402,25 @@ public function getPos() } /** - * Set position type + * Set position type. * * @param string $value + * * @return self */ public function setPos($value) { - $enum = array( + $enum = [ self::POS_ABSOLUTE, self::POS_RELATIVE, - ); + ]; $this->pos = $this->setEnumVal($value, $enum, $this->pos); return $this; } /** - * Get horizontal position + * Get horizontal position. * * @return string */ @@ -422,30 +430,31 @@ public function getHPos() } /** - * Set horizontal position + * Set horizontal position. * * @since 0.12.0 "absolute" option is available. * * @param string $value + * * @return self */ public function setHPos($value) { - $enum = array( + $enum = [ self::POS_ABSOLUTE, self::POS_LEFT, self::POS_CENTER, self::POS_RIGHT, self::POS_INSIDE, self::POS_OUTSIDE, - ); + ]; $this->hPos = $this->setEnumVal($value, $enum, $this->hPos); return $this; } /** - * Get vertical position + * Get vertical position. * * @return string */ @@ -455,30 +464,31 @@ public function getVPos() } /** - * Set vertical position + * Set vertical position. * * @since 0.12.0 "absolute" option is available. * * @param string $value + * * @return self */ public function setVPos($value) { - $enum = array( + $enum = [ self::POS_ABSOLUTE, self::POS_TOP, self::POS_CENTER, self::POS_BOTTOM, self::POS_INSIDE, self::POS_OUTSIDE, - ); + ]; $this->vPos = $this->setEnumVal($value, $enum, $this->vPos); return $this; } /** - * Get horizontal position relative to + * Get horizontal position relative to. * * @return string */ @@ -488,14 +498,15 @@ public function getHPosRelTo() } /** - * Set horizontal position relative to + * Set horizontal position relative to. * * @param string $value + * * @return self */ public function setHPosRelTo($value) { - $enum = array( + $enum = [ self::POS_RELTO_MARGIN, self::POS_RELTO_PAGE, self::POS_RELTO_COLUMN, @@ -504,14 +515,14 @@ public function setHPosRelTo($value) self::POS_RELTO_RMARGIN, self::POS_RELTO_IMARGIN, self::POS_RELTO_OMARGIN, - ); + ]; $this->hPosRelTo = $this->setEnumVal($value, $enum, $this->hPosRelTo); return $this; } /** - * Get vertical position relative to + * Get vertical position relative to. * * @return string */ @@ -521,14 +532,15 @@ public function getVPosRelTo() } /** - * Set vertical position relative to + * Set vertical position relative to. * * @param string $value + * * @return self */ public function setVPosRelTo($value) { - $enum = array( + $enum = [ self::POS_RELTO_MARGIN, self::POS_RELTO_PAGE, self::POS_RELTO_TEXT, @@ -537,14 +549,14 @@ public function setVPosRelTo($value) self::POS_RELTO_BMARGIN, self::POS_RELTO_IMARGIN, self::POS_RELTO_OMARGIN, - ); + ]; $this->vPosRelTo = $this->setEnumVal($value, $enum, $this->vPosRelTo); return $this; } /** - * Get wrap type + * Get wrap type. * * @return string */ @@ -554,14 +566,15 @@ public function getWrap() } /** - * Set wrap type + * Set wrap type. * * @param string $value + * * @return self */ public function setWrap($value) { - $enum = array( + $enum = [ self::WRAP_INLINE, self::WRAP_SQUARE, self::WRAP_TIGHT, @@ -569,14 +582,14 @@ public function setWrap($value) self::WRAP_TOPBOTTOM, self::WRAP_BEHIND, self::WRAP_INFRONT, - ); + ]; $this->wrap = $this->setEnumVal($value, $enum, $this->wrap); return $this; } /** - * Get top distance from text wrap + * Get top distance from text wrap. * * @return float */ @@ -586,9 +599,10 @@ public function getWrapDistanceTop() } /** - * Set top distance from text wrap + * Set top distance from text wrap. * * @param int $value + * * @return self */ public function setWrapDistanceTop($value = null) @@ -599,7 +613,7 @@ public function setWrapDistanceTop($value = null) } /** - * Get bottom distance from text wrap + * Get bottom distance from text wrap. * * @return float */ @@ -609,9 +623,10 @@ public function getWrapDistanceBottom() } /** - * Set bottom distance from text wrap + * Set bottom distance from text wrap. * * @param float $value + * * @return self */ public function setWrapDistanceBottom($value = null) @@ -622,7 +637,7 @@ public function setWrapDistanceBottom($value = null) } /** - * Get left distance from text wrap + * Get left distance from text wrap. * * @return float */ @@ -632,9 +647,10 @@ public function getWrapDistanceLeft() } /** - * Set left distance from text wrap + * Set left distance from text wrap. * * @param float $value + * * @return self */ public function setWrapDistanceLeft($value = null) @@ -645,7 +661,7 @@ public function setWrapDistanceLeft($value = null) } /** - * Get right distance from text wrap + * Get right distance from text wrap. * * @return float */ @@ -655,9 +671,10 @@ public function getWrapDistanceRight() } /** - * Set right distance from text wrap + * Set right distance from text wrap. * * @param float $value + * * @return self */ public function setWrapDistanceRight($value = null) @@ -668,7 +685,7 @@ public function setWrapDistanceRight($value = null) } /** - * Get position + * Get position. * * @return int */ @@ -678,9 +695,10 @@ public function getPosition() } /** - * Set position + * Set position. * * @param int $value + * * @return self */ public function setPosition($value = null) diff --git a/src/PhpWord/Style/Image.php b/src/PhpWord/Style/Image.php index 70aafe12cd..dbb8572f99 100644 --- a/src/PhpWord/Style/Image.php +++ b/src/PhpWord/Style/Image.php @@ -11,19 +11,19 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * Image and memory image style + * Image and memory image style. */ class Image extends Frame { /** - * Backward compatibility constants + * Backward compatibility constants. * * @const string */ @@ -56,7 +56,7 @@ class Image extends Frame const POSITION_RELATIVE = self::POS_RELATIVE; /** - * Create new instance + * Create new instance. */ public function __construct() { @@ -73,9 +73,9 @@ public function __construct() } /** - * Get margin top + * Get margin top. * - * @return int|float + * @return float|int */ public function getMarginTop() { @@ -83,10 +83,12 @@ public function getMarginTop() } /** - * Set margin top + * Set margin top. * * @ignoreScrutinizerPatch - * @param int|float $value + * + * @param float|int $value + * * @return self */ public function setMarginTop($value = 0) @@ -97,9 +99,9 @@ public function setMarginTop($value = 0) } /** - * Get margin left + * Get margin left. * - * @return int|float + * @return float|int */ public function getMarginLeft() { @@ -107,10 +109,12 @@ public function getMarginLeft() } /** - * Set margin left + * Set margin left. * * @ignoreScrutinizerPatch - * @param int|float $value + * + * @param float|int $value + * * @return self */ public function setMarginLeft($value = 0) @@ -121,7 +125,7 @@ public function setMarginLeft($value = 0) } /** - * Get wrapping style + * Get wrapping style. * * @return string */ @@ -131,12 +135,10 @@ public function getWrappingStyle() } /** - * Set wrapping style + * Set wrapping style. * * @param string $wrappingStyle * - * @throws \InvalidArgumentException - * * @return self */ public function setWrappingStyle($wrappingStyle) @@ -147,7 +149,7 @@ public function setWrappingStyle($wrappingStyle) } /** - * Get positioning type + * Get positioning type. * * @return string */ @@ -157,12 +159,10 @@ public function getPositioning() } /** - * Set positioning type + * Set positioning type. * * @param string $positioning * - * @throws \InvalidArgumentException - * * @return self */ public function setPositioning($positioning) @@ -173,7 +173,7 @@ public function setPositioning($positioning) } /** - * Get horizontal alignment + * Get horizontal alignment. * * @return string */ @@ -183,12 +183,10 @@ public function getPosHorizontal() } /** - * Set horizontal alignment + * Set horizontal alignment. * * @param string $alignment * - * @throws \InvalidArgumentException - * * @return self */ public function setPosHorizontal($alignment) @@ -199,7 +197,7 @@ public function setPosHorizontal($alignment) } /** - * Get vertical alignment + * Get vertical alignment. * * @return string */ @@ -209,12 +207,10 @@ public function getPosVertical() } /** - * Set vertical alignment + * Set vertical alignment. * * @param string $alignment * - * @throws \InvalidArgumentException - * * @return self */ public function setPosVertical($alignment) @@ -225,7 +221,7 @@ public function setPosVertical($alignment) } /** - * Get horizontal relation + * Get horizontal relation. * * @return string */ @@ -235,12 +231,10 @@ public function getPosHorizontalRel() } /** - * Set horizontal relation + * Set horizontal relation. * * @param string $relto * - * @throws \InvalidArgumentException - * * @return self */ public function setPosHorizontalRel($relto) @@ -251,7 +245,7 @@ public function setPosHorizontalRel($relto) } /** - * Get vertical relation + * Get vertical relation. * * @return string */ @@ -261,12 +255,10 @@ public function getPosVerticalRel() } /** - * Set vertical relation + * Set vertical relation. * * @param string $relto * - * @throws \InvalidArgumentException - * * @return self */ public function setPosVerticalRel($relto) diff --git a/src/PhpWord/Style/Indentation.php b/src/PhpWord/Style/Indentation.php index e422395c80..87277b4b81 100644 --- a/src/PhpWord/Style/Indentation.php +++ b/src/PhpWord/Style/Indentation.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * Paragraph indentation style + * Paragraph indentation style. * * @see http://www.schemacentral.com/sc/ooxml/t-w_CT_Ind.html * @since 0.10.0 @@ -26,47 +26,47 @@ class Indentation extends AbstractStyle { /** - * Left indentation (twip) + * Left indentation (twip). * - * @var int|float + * @var float|int */ private $left = 0; /** - * Right indentation (twip) + * Right indentation (twip). * - * @var int|float + * @var float|int */ private $right = 0; /** - * Additional first line indentation (twip) + * Additional first line indentation (twip). * - * @var int|float + * @var float|int */ private $firstLine; /** - * Indentation removed from first line (twip) + * Indentation removed from first line (twip). * - * @var int|float + * @var float|int */ private $hanging; /** - * Create a new instance + * Create a new instance. * * @param array $style */ - public function __construct($style = array()) + public function __construct($style = []) { $this->setStyleByArray($style); } /** - * Get left + * Get left. * - * @return int|float + * @return float|int */ public function getLeft() { @@ -74,9 +74,10 @@ public function getLeft() } /** - * Set left + * Set left. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setLeft($value = null) @@ -87,9 +88,9 @@ public function setLeft($value = null) } /** - * Get right + * Get right. * - * @return int|float + * @return float|int */ public function getRight() { @@ -97,9 +98,10 @@ public function getRight() } /** - * Set right + * Set right. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setRight($value = null) @@ -110,9 +112,9 @@ public function setRight($value = null) } /** - * Get first line + * Get first line. * - * @return int|float + * @return float|int */ public function getFirstLine() { @@ -120,9 +122,10 @@ public function getFirstLine() } /** - * Set first line + * Set first line. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setFirstLine($value = null) @@ -133,9 +136,9 @@ public function setFirstLine($value = null) } /** - * Get hanging + * Get hanging. * - * @return int|float + * @return float|int */ public function getHanging() { @@ -143,9 +146,10 @@ public function getHanging() } /** - * Set hanging + * Set hanging. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setHanging($value = null) diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index 7f3dbec767..fd63eb143e 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -11,15 +11,17 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; +use InvalidArgumentException; + /** * Language - * A couple of predefined values are defined here, see the websites below for more values + * A couple of predefined values are defined here, see the websites below for more values. * * @see http://www.datypic.com/sc/ooxml/t-w_CT_Language.html * @see https://technet.microsoft.com/en-us/library/cc287874(v=office.12).aspx @@ -75,40 +77,41 @@ final class Language extends AbstractStyle const RU_RU_ID = 1049; /** - * Language ID, used for RTF document generation + * Language ID, used for RTF document generation. * * @var int + * * @see https://technet.microsoft.com/en-us/library/cc179219.aspx */ private $langId; /** - * Latin Language + * Latin Language. * * @var string */ private $latin; /** - * East Asian Language + * East Asian Language. * * @var string */ private $eastAsia; /** - * Complex Script Language + * Complex Script Language. * * @var string */ private $bidirectional; /** - * Constructor + * Constructor. * - * @param string|null $latin - * @param string|null $eastAsia - * @param string|null $bidirectional + * @param null|string $latin + * @param null|string $eastAsia + * @param null|string $bidirectional */ public function __construct($latin = null, $eastAsia = null, $bidirectional = null) { @@ -124,10 +127,11 @@ public function __construct($latin = null, $eastAsia = null, $bidirectional = nu } /** - * Set the Latin Language + * Set the Latin Language. * * @param string $latin * The value for the latin language + * * @return self */ public function setLatin($latin) @@ -138,9 +142,9 @@ public function setLatin($latin) } /** - * Get the Latin Language + * Get the Latin Language. * - * @return string|null + * @return null|string */ public function getLatin() { @@ -148,11 +152,13 @@ public function getLatin() } /** - * Set the Language ID + * Set the Language ID. * * @param int $langId * The value for the language ID + * * @return self + * * @see https://technet.microsoft.com/en-us/library/cc287874(v=office.12).aspx */ public function setLangId($langId) @@ -163,7 +169,7 @@ public function setLangId($langId) } /** - * Get the Language ID + * Get the Language ID. * * @return int */ @@ -173,10 +179,11 @@ public function getLangId() } /** - * Set the East Asian Language + * Set the East Asian Language. * * @param string $eastAsia * The value for the east asian language + * * @return self */ public function setEastAsia($eastAsia) @@ -187,9 +194,9 @@ public function setEastAsia($eastAsia) } /** - * Get the East Asian Language + * Get the East Asian Language. * - * @return string|null + * @return null|string */ public function getEastAsia() { @@ -197,10 +204,11 @@ public function getEastAsia() } /** - * Set the Complex Script Language + * Set the Complex Script Language. * * @param string $bidirectional * The value for the complex script language + * * @return self */ public function setBidirectional($bidirectional) @@ -211,9 +219,9 @@ public function setBidirectional($bidirectional) } /** - * Get the Complex Script Language + * Get the Complex Script Language. * - * @return string|null + * @return null|string */ public function getBidirectional() { @@ -221,9 +229,10 @@ public function getBidirectional() } /** - * Validates that the language passed is in the format xx-xx + * Validates that the language passed is in the format xx-xx. * * @param string $locale + * * @return string */ private function validateLocale($locale) @@ -237,7 +246,7 @@ private function validateLocale($locale) } if ($locale !== null && $locale !== 'zxx' && strstr($locale, '-') === false) { - throw new \InvalidArgumentException($locale . ' is not a valid language code'); + throw new InvalidArgumentException($locale . ' is not a valid language code'); } return $locale; diff --git a/src/PhpWord/Style/Line.php b/src/PhpWord/Style/Line.php index a9952eec0b..2aeefa5ae5 100644 --- a/src/PhpWord/Style/Line.php +++ b/src/PhpWord/Style/Line.php @@ -11,26 +11,26 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * Line style + * Line style. */ class Line extends Image { /** - * Connector types + * Connector types. * * @const string */ const CONNECTOR_TYPE_STRAIGHT = 'straight'; /** - * Arrow styles + * Arrow styles. * * @const string */ @@ -41,7 +41,7 @@ class Line extends Image const ARROW_STYLE_OVAL = 'oval'; /** - * Dash styles + * Dash styles. * * @const string */ @@ -54,56 +54,56 @@ class Line extends Image const DASH_STYLE_LONG_DASH_DOT_DOT = 'longdashdotdot'; /** - * flip Line + * flip Line. * * @var bool */ private $flip = false; /** - * connectorType + * connectorType. * * @var string */ private $connectorType = self::CONNECTOR_TYPE_STRAIGHT; /** - * Line Weight + * Line Weight. * * @var int */ private $weight; /** - * Line color + * Line color. * * @var string */ private $color; /** - * Dash style + * Dash style. * * @var string */ private $dash; /** - * Begin arrow + * Begin arrow. * * @var string */ private $beginArrow; /** - * End arrow + * End arrow. * * @var string */ private $endArrow; /** - * Get flip + * Get flip. * * @return bool */ @@ -113,9 +113,10 @@ public function isFlip() } /** - * Set flip + * Set flip. * * @param bool $value + * * @return self */ public function setFlip($value = false) @@ -126,7 +127,7 @@ public function setFlip($value = false) } /** - * Get connectorType + * Get connectorType. * * @return string */ @@ -136,23 +137,24 @@ public function getConnectorType() } /** - * Set connectorType + * Set connectorType. * * @param string $value + * * @return self */ public function setConnectorType($value = null) { - $enum = array( + $enum = [ self::CONNECTOR_TYPE_STRAIGHT, - ); + ]; $this->connectorType = $this->setEnumVal($value, $enum, $this->connectorType); return $this; } /** - * Get weight + * Get weight. * * @return int */ @@ -162,9 +164,10 @@ public function getWeight() } /** - * Set weight + * Set weight. * * @param int $value Weight in points + * * @return self */ public function setWeight($value = null) @@ -175,7 +178,7 @@ public function setWeight($value = null) } /** - * Get color + * Get color. * * @return string */ @@ -185,9 +188,10 @@ public function getColor() } /** - * Set color + * Set color. * * @param string $value + * * @return self */ public function setColor($value = null) @@ -198,7 +202,7 @@ public function setColor($value = null) } /** - * Get beginArrow + * Get beginArrow. * * @return string */ @@ -208,24 +212,25 @@ public function getBeginArrow() } /** - * Set beginArrow + * Set beginArrow. * * @param string $value + * * @return self */ public function setBeginArrow($value = null) { - $enum = array( + $enum = [ self::ARROW_STYLE_BLOCK, self::ARROW_STYLE_CLASSIC, self::ARROW_STYLE_DIAMOND, self::ARROW_STYLE_OPEN, self::ARROW_STYLE_OVAL, - ); + ]; $this->beginArrow = $this->setEnumVal($value, $enum, $this->beginArrow); return $this; } /** - * Get endArrow + * Get endArrow. * * @return string */ @@ -235,24 +240,25 @@ public function getEndArrow() } /** - * Set endArrow + * Set endArrow. * * @param string $value + * * @return self */ public function setEndArrow($value = null) { - $enum = array( + $enum = [ self::ARROW_STYLE_BLOCK, self::ARROW_STYLE_CLASSIC, self::ARROW_STYLE_DIAMOND, self::ARROW_STYLE_OPEN, self::ARROW_STYLE_OVAL, - ); + ]; $this->endArrow = $this->setEnumVal($value, $enum, $this->endArrow); return $this; } /** - * Get Dash + * Get Dash. * * @return string */ @@ -262,18 +268,19 @@ public function getDash() } /** - * Set Dash + * Set Dash. * * @param string $value + * * @return self */ public function setDash($value = null) { - $enum = array( + $enum = [ self::DASH_STYLE_DASH, self::DASH_STYLE_DASH_DOT, self::DASH_STYLE_LONG_DASH, self::DASH_STYLE_LONG_DASH_DOT, self::DASH_STYLE_LONG_DASH_DOT_DOT, self::DASH_STYLE_ROUND_DOT, self::DASH_STYLE_SQUARE_DOT, - ); + ]; $this->dash = $this->setEnumVal($value, $enum, $this->dash); return $this; diff --git a/src/PhpWord/Style/LineNumbering.php b/src/PhpWord/Style/LineNumbering.php index 451252d87a..61a98dc8e1 100644 --- a/src/PhpWord/Style/LineNumbering.php +++ b/src/PhpWord/Style/LineNumbering.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * Line numbering style + * Line numbering style. * * @see http://www.schemacentral.com/sc/ooxml/t-w_CT_LineNumber.html * @since 0.10.0 @@ -31,46 +31,47 @@ class LineNumbering extends AbstractStyle const LINE_NUMBERING_NEW_SECTION = 'newSection'; /** - * Line numbering starting value + * Line numbering starting value. * * @var int */ private $start = 1; /** - * Line number increments + * Line number increments. * * @var int */ private $increment = 1; /** - * Distance between text and line numbering in twip + * Distance between text and line numbering in twip. * - * @var int|float + * @var float|int */ private $distance; /** - * Line numbering restart setting continuous|newPage|newSection + * Line numbering restart setting continuous|newPage|newSection. * * @var string + * * @see http://www.schemacentral.com/sc/ooxml/a-w_restart-1.html */ private $restart; /** - * Create a new instance + * Create a new instance. * * @param array $style */ - public function __construct($style = array()) + public function __construct($style = []) { $this->setStyleByArray($style); } /** - * Get start + * Get start. * * @return int */ @@ -80,9 +81,10 @@ public function getStart() } /** - * Set start + * Set start. * * @param int $value + * * @return self */ public function setStart($value = null) @@ -93,7 +95,7 @@ public function setStart($value = null) } /** - * Get increment + * Get increment. * * @return int */ @@ -103,9 +105,10 @@ public function getIncrement() } /** - * Set increment + * Set increment. * * @param int $value + * * @return self */ public function setIncrement($value = null) @@ -116,9 +119,9 @@ public function setIncrement($value = null) } /** - * Get distance + * Get distance. * - * @return int|float + * @return float|int */ public function getDistance() { @@ -126,9 +129,10 @@ public function getDistance() } /** - * Set distance + * Set distance. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setDistance($value = null) @@ -139,7 +143,7 @@ public function setDistance($value = null) } /** - * Get restart + * Get restart. * * @return string */ @@ -149,14 +153,15 @@ public function getRestart() } /** - * Set distance + * Set distance. * * @param string $value + * * @return self */ public function setRestart($value = null) { - $enum = array(self::LINE_NUMBERING_CONTINUOUS, self::LINE_NUMBERING_NEW_PAGE, self::LINE_NUMBERING_NEW_SECTION); + $enum = [self::LINE_NUMBERING_CONTINUOUS, self::LINE_NUMBERING_NEW_PAGE, self::LINE_NUMBERING_NEW_SECTION]; $this->restart = $this->setEnumVal($value, $enum, $this->restart); return $this; diff --git a/src/PhpWord/Style/ListItem.php b/src/PhpWord/Style/ListItem.php index 4293940fd2..28d3fb1b66 100644 --- a/src/PhpWord/Style/ListItem.php +++ b/src/PhpWord/Style/ListItem.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,7 +20,7 @@ use PhpOffice\PhpWord\Style; /** - * List item style + * List item style. * * Before version 0.10.0, numbering style is defined statically with $listType. * After version 0.10.0, numbering style is defined by using Numbering and @@ -36,30 +36,32 @@ class ListItem extends AbstractStyle const TYPE_ALPHANUM = 9; /** - * Legacy list type + * Legacy list type. * * @var int */ private $listType; /** - * Numbering style name + * Numbering style name. * * @var string + * * @since 0.10.0 */ private $numStyle; /** - * Numbering definition instance ID + * Numbering definition instance ID. * * @var int + * * @since 0.10.0 */ private $numId; /** - * Create new instance + * Create new instance. * * @param string $numStyle */ @@ -73,7 +75,7 @@ public function __construct($numStyle = null) } /** - * Get List Type + * Get List Type. * * @return int */ @@ -83,18 +85,19 @@ public function getListType() } /** - * Set legacy list type for version < 0.10.0 + * Set legacy list type for version < 0.10.0. * * @param int $value + * * @return self */ public function setListType($value = self::TYPE_BULLET_FILLED) { - $enum = array( + $enum = [ self::TYPE_SQUARE_FILLED, self::TYPE_BULLET_FILLED, self::TYPE_BULLET_EMPTY, self::TYPE_NUMBER, self::TYPE_NUMBER_NESTED, self::TYPE_ALPHANUM, - ); + ]; $this->listType = $this->setEnumVal($value, $enum, $this->listType); $this->getListTypeStyle(); @@ -102,7 +105,7 @@ public function setListType($value = self::TYPE_BULLET_FILLED) } /** - * Get numbering style name + * Get numbering style name. * * @return string */ @@ -112,9 +115,10 @@ public function getNumStyle() } /** - * Set numbering style name + * Set numbering style name. * * @param string $value + * * @return self */ public function setNumStyle($value) @@ -130,7 +134,7 @@ public function setNumStyle($value) } /** - * Get numbering Id + * Get numbering Id. * * @return int */ @@ -140,19 +144,21 @@ public function getNumId() } /** - * Set numbering Id. Same numId means same list + * Set numbering Id. Same numId means same list. + * * @param mixed $numInt */ - public function setNumId($numInt) + public function setNumId($numInt): void { $this->numId = $numInt; $this->getListTypeStyle(); } /** - * Get legacy numbering definition + * Get legacy numbering definition. * * @return array + * * @since 0.10.0 */ private function getListTypeStyle() @@ -171,13 +177,13 @@ private function getListTypeStyle() } // Property mapping for numbering level information - $properties = array('start', 'format', 'text', 'alignment', 'tabPos', 'left', 'hanging', 'font', 'hint'); + $properties = ['start', 'format', 'text', 'alignment', 'tabPos', 'left', 'hanging', 'font', 'hint']; // Legacy level information - $listTypeStyles = array( - self::TYPE_SQUARE_FILLED => array( - 'type' => 'hybridMultilevel', - 'levels' => array( + $listTypeStyles = [ + self::TYPE_SQUARE_FILLED => [ + 'type' => 'hybridMultilevel', + 'levels' => [ 0 => '1, bullet, , left, 720, 720, 360, Wingdings, default', 1 => '1, bullet, o, left, 1440, 1440, 360, Courier New, default', 2 => '1, bullet, , left, 2160, 2160, 360, Wingdings, default', @@ -187,11 +193,11 @@ private function getListTypeStyle() 6 => '1, bullet, , left, 5040, 5040, 360, Symbol, default', 7 => '1, bullet, o, left, 5760, 5760, 360, Courier New, default', 8 => '1, bullet, , left, 6480, 6480, 360, Wingdings, default', - ), - ), - self::TYPE_BULLET_FILLED => array( - 'type' => 'hybridMultilevel', - 'levels' => array( + ], + ], + self::TYPE_BULLET_FILLED => [ + 'type' => 'hybridMultilevel', + 'levels' => [ 0 => '1, bullet, , left, 720, 720, 360, Symbol, default', 1 => '1, bullet, o, left, 1440, 1440, 360, Courier New, default', 2 => '1, bullet, , left, 2160, 2160, 360, Wingdings, default', @@ -201,11 +207,11 @@ private function getListTypeStyle() 6 => '1, bullet, , left, 5040, 5040, 360, Symbol, default', 7 => '1, bullet, o, left, 5760, 5760, 360, Courier New, default', 8 => '1, bullet, , left, 6480, 6480, 360, Wingdings, default', - ), - ), - self::TYPE_BULLET_EMPTY => array( - 'type' => 'hybridMultilevel', - 'levels' => array( + ], + ], + self::TYPE_BULLET_EMPTY => [ + 'type' => 'hybridMultilevel', + 'levels' => [ 0 => '1, bullet, o, left, 720, 720, 360, Courier New, default', 1 => '1, bullet, o, left, 1440, 1440, 360, Courier New, default', 2 => '1, bullet, , left, 2160, 2160, 360, Wingdings, default', @@ -215,11 +221,11 @@ private function getListTypeStyle() 6 => '1, bullet, , left, 5040, 5040, 360, Symbol, default', 7 => '1, bullet, o, left, 5760, 5760, 360, Courier New, default', 8 => '1, bullet, , left, 6480, 6480, 360, Wingdings, default', - ), - ), - self::TYPE_NUMBER => array( - 'type' => 'hybridMultilevel', - 'levels' => array( + ], + ], + self::TYPE_NUMBER => [ + 'type' => 'hybridMultilevel', + 'levels' => [ 0 => '1, decimal, %1., left, 720, 720, 360, , default', 1 => '1, bullet, o, left, 1440, 1440, 360, Courier New, default', 2 => '1, bullet, , left, 2160, 2160, 360, Wingdings, default', @@ -229,11 +235,11 @@ private function getListTypeStyle() 6 => '1, bullet, , left, 5040, 5040, 360, Symbol, default', 7 => '1, bullet, o, left, 5760, 5760, 360, Courier New, default', 8 => '1, bullet, , left, 6480, 6480, 360, Wingdings, default', - ), - ), - self::TYPE_NUMBER_NESTED => array( - 'type' => 'multilevel', - 'levels' => array( + ], + ], + self::TYPE_NUMBER_NESTED => [ + 'type' => 'multilevel', + 'levels' => [ 0 => '1, decimal, %1., left, 360, 360, 360, , ', 1 => '1, decimal, %1.%2., left, 792, 792, 432, , ', 2 => '1, decimal, %1.%2.%3., left, 1224, 1224, 504, , ', @@ -243,11 +249,11 @@ private function getListTypeStyle() 6 => '1, decimal, %1.%2.%3.%4.%5.%6.%7., left, 3600, 3240, 1080, , ', 7 => '1, decimal, %1.%2.%3.%4.%5.%6.%7.%8., left, 3960, 3744, 1224, , ', 8 => '1, decimal, %1.%2.%3.%4.%5.%6.%7.%8.%9., left, 4680, 4320, 1440, , ', - ), - ), - self::TYPE_ALPHANUM => array( - 'type' => 'multilevel', - 'levels' => array( + ], + ], + self::TYPE_ALPHANUM => [ + 'type' => 'multilevel', + 'levels' => [ 0 => '1, decimal, %1., left, 720, 720, 360, , ', 1 => '1, lowerLetter, %2., left, 1440, 1440, 360, , ', 2 => '1, lowerRoman, %3., right, 2160, 2160, 180, , ', @@ -257,18 +263,18 @@ private function getListTypeStyle() 6 => '1, decimal, %7., left, 5040, 5040, 360, , ', 7 => '1, lowerLetter, %8., left, 5760, 5760, 360, , ', 8 => '1, lowerRoman, %9., right, 6480, 6480, 180, , ', - ), - ), - ); + ], + ], + ]; // Populate style and register to global Style register $style = $listTypeStyles[$this->listType]; $numProperties = count($properties); foreach ($style['levels'] as $key => $value) { - $level = array(); + $level = []; $levelProperties = explode(', ', $value); $level['level'] = $key; - for ($i = 0; $i < $numProperties; $i++) { + for ($i = 0; $i < $numProperties; ++$i) { $property = $properties[$i]; $level[$property] = $levelProperties[$i]; } diff --git a/src/PhpWord/Style/Numbering.php b/src/PhpWord/Style/Numbering.php index f7855cfa20..0efb088dd4 100644 --- a/src/PhpWord/Style/Numbering.php +++ b/src/PhpWord/Style/Numbering.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * Numbering style + * Numbering style. * * @see http://www.schemacentral.com/sc/ooxml/e-w_numbering.html * @see http://www.schemacentral.com/sc/ooxml/e-w_abstractNum-1.html @@ -28,30 +28,32 @@ class Numbering extends AbstractStyle { /** - * Numbering definition instance ID + * Numbering definition instance ID. * * @var int + * * @see http://www.schemacentral.com/sc/ooxml/e-w_num-1.html */ private $numId; /** - * Multilevel type singleLevel|multilevel|hybridMultilevel + * Multilevel type singleLevel|multilevel|hybridMultilevel. * * @var string + * * @see http://www.schemacentral.com/sc/ooxml/a-w_val-67.html */ private $type; /** - * Numbering levels + * Numbering levels. * * @var NumberingLevel[] */ - private $levels = array(); + private $levels = []; /** - * Get Id + * Get Id. * * @return int */ @@ -61,9 +63,10 @@ public function getNumId() } /** - * Set Id + * Set Id. * * @param int $value + * * @return self */ public function setNumId($value) @@ -74,7 +77,7 @@ public function setNumId($value) } /** - * Get multilevel type + * Get multilevel type. * * @return string */ @@ -84,21 +87,22 @@ public function getType() } /** - * Set multilevel type + * Set multilevel type. * * @param string $value + * * @return self */ public function setType($value) { - $enum = array('singleLevel', 'multilevel', 'hybridMultilevel'); + $enum = ['singleLevel', 'multilevel', 'hybridMultilevel']; $this->type = $this->setEnumVal($value, $enum, $this->type); return $this; } /** - * Get levels + * Get levels. * * @return NumberingLevel[] */ @@ -108,9 +112,10 @@ public function getLevels() } /** - * Set multilevel type + * Set multilevel type. * * @param array $values + * * @return self */ public function setLevels($values) diff --git a/src/PhpWord/Style/NumberingLevel.php b/src/PhpWord/Style/NumberingLevel.php index e9b32f0135..5efc830016 100644 --- a/src/PhpWord/Style/NumberingLevel.php +++ b/src/PhpWord/Style/NumberingLevel.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,7 +21,7 @@ use PhpOffice\PhpWord\SimpleType\NumberFormat; /** - * Numbering level definition + * Numbering level definition. * * @see http://www.schemacentral.com/sc/ooxml/e-w_lvl-1.html * @since 0.10.0 @@ -29,105 +29,112 @@ class NumberingLevel extends AbstractStyle { /** - * Level number, 0 to 8 (total 9 levels) + * Level number, 0 to 8 (total 9 levels). * * @var int */ private $level = 0; /** - * Starting value w:start + * Starting value w:start. * * @var int + * * @see http://www.schemacentral.com/sc/ooxml/e-w_start-1.html */ private $start = 1; /** - * Numbering format w:numFmt, one of PhpOffice\PhpWord\SimpleType\NumberFormat + * Numbering format w:numFmt, one of PhpOffice\PhpWord\SimpleType\NumberFormat. * * @var string + * * @see http://www.schemacentral.com/sc/ooxml/t-w_ST_NumberFormat.html */ private $format; /** - * Restart numbering level symbol w:lvlRestart + * Restart numbering level symbol w:lvlRestart. * * @var int + * * @see http://www.schemacentral.com/sc/ooxml/e-w_lvlRestart-1.html */ private $restart; /** - * Related paragraph style + * Related paragraph style. * * @var string + * * @see http://www.schemacentral.com/sc/ooxml/e-w_pStyle-2.html */ private $pStyle; /** - * Content between numbering symbol and paragraph text w:suff + * Content between numbering symbol and paragraph text w:suff. * * @var string tab|space|nothing + * * @see http://www.schemacentral.com/sc/ooxml/e-w_suff-1.html */ private $suffix = 'tab'; /** - * Numbering level text e.g. %1 for nonbullet or bullet character + * Numbering level text e.g. %1 for nonbullet or bullet character. * * @var string + * * @see http://www.schemacentral.com/sc/ooxml/e-w_lvlText-1.html */ private $text; /** - * Justification, w:lvlJc + * Justification, w:lvlJc. * * @var string, one of PhpOffice\PhpWord\SimpleType\Jc */ private $alignment = ''; /** - * Left + * Left. * * @var int */ private $left; /** - * Hanging + * Hanging. * * @var int */ private $hanging; /** - * Tab position + * Tab position. * * @var int */ private $tabPos; /** - * Font family + * Font family. * * @var string */ private $font; /** - * Hint default|eastAsia|cs + * Hint default|eastAsia|cs. * * @var string + * * @see http://www.schemacentral.com/sc/ooxml/a-w_hint-1.html */ private $hint; /** - * Get level + * Get level. * * @return int */ @@ -137,9 +144,10 @@ public function getLevel() } /** - * Set level + * Set level. * * @param int $value + * * @return self */ public function setLevel($value) @@ -150,7 +158,7 @@ public function setLevel($value) } /** - * Get start + * Get start. * * @return int */ @@ -160,9 +168,10 @@ public function getStart() } /** - * Set start + * Set start. * * @param int $value + * * @return self */ public function setStart($value) @@ -173,7 +182,7 @@ public function setStart($value) } /** - * Get format + * Get format. * * @return string */ @@ -183,9 +192,10 @@ public function getFormat() } /** - * Set format + * Set format. * * @param string $value + * * @return self */ public function setFormat($value) @@ -196,7 +206,7 @@ public function setFormat($value) } /** - * Get restart + * Get restart. * * @return int */ @@ -206,9 +216,10 @@ public function getRestart() } /** - * Set restart + * Set restart. * * @param int $value + * * @return self */ public function setRestart($value) @@ -219,7 +230,7 @@ public function setRestart($value) } /** - * Get related paragraph style + * Get related paragraph style. * * @return string */ @@ -229,9 +240,10 @@ public function getPStyle() } /** - * Set related paragraph style + * Set related paragraph style. * * @param string $value + * * @return self */ public function setPStyle($value) @@ -242,7 +254,7 @@ public function setPStyle($value) } /** - * Get suffix + * Get suffix. * * @return string */ @@ -252,21 +264,22 @@ public function getSuffix() } /** - * Set suffix + * Set suffix. * * @param string $value + * * @return self */ public function setSuffix($value) { - $enum = array('tab', 'space', 'nothing'); + $enum = ['tab', 'space', 'nothing']; $this->suffix = $this->setEnumVal($value, $enum, $this->suffix); return $this; } /** - * Get text + * Get text. * * @return string */ @@ -276,9 +289,10 @@ public function getText() } /** - * Set text + * Set text. * * @param string $value + * * @return self */ public function setText($value) @@ -341,7 +355,7 @@ public function setAlign($value) } /** - * Get left + * Get left. * * @return int */ @@ -351,9 +365,10 @@ public function getLeft() } /** - * Set left + * Set left. * * @param int $value + * * @return self */ public function setLeft($value) @@ -364,7 +379,7 @@ public function setLeft($value) } /** - * Get hanging + * Get hanging. * * @return int */ @@ -374,9 +389,10 @@ public function getHanging() } /** - * Set hanging + * Set hanging. * * @param int $value + * * @return self */ public function setHanging($value) @@ -387,7 +403,7 @@ public function setHanging($value) } /** - * Get tab + * Get tab. * * @return int */ @@ -397,9 +413,10 @@ public function getTabPos() } /** - * Set tab + * Set tab. * * @param int $value + * * @return self */ public function setTabPos($value) @@ -410,7 +427,7 @@ public function setTabPos($value) } /** - * Get font + * Get font. * * @return string */ @@ -420,9 +437,10 @@ public function getFont() } /** - * Set font + * Set font. * * @param string $value + * * @return self */ public function setFont($value) @@ -433,7 +451,7 @@ public function setFont($value) } /** - * Get hint + * Get hint. * * @return string */ @@ -443,14 +461,15 @@ public function getHint() } /** - * Set hint + * Set hint. * * @param string $value + * * @return self */ public function setHint($value = null) { - $enum = array('default', 'eastAsia', 'cs'); + $enum = ['default', 'eastAsia', 'cs']; $this->hint = $this->setEnumVal($value, $enum, $this->hint); return $this; diff --git a/src/PhpWord/Style/Outline.php b/src/PhpWord/Style/Outline.php index a04ad974c0..6d83f0378d 100644 --- a/src/PhpWord/Style/Outline.php +++ b/src/PhpWord/Style/Outline.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * Outline defines the line/border of the object + * Outline defines the line/border of the object. * * @see http://www.schemacentral.com/sc/ooxml/t-v_CT_Stroke.html * @see http://www.w3.org/TR/1998/NOTE-VML-19980513#_Toc416858395 @@ -27,9 +27,10 @@ class Outline extends AbstractStyle { /** - * Line style constants + * Line style constants. * * @see http://www.schemacentral.com/sc/ooxml/t-v_ST_StrokeLineStyle.html + * * @const string */ const LINE_SINGLE = 'single'; @@ -39,9 +40,10 @@ class Outline extends AbstractStyle const LINE_THICK_BETWEEN_THIN = 'thickBetweenThin'; /** - * Line style constants + * Line style constants. * * @see http://www.schemacentral.com/sc/ooxml/t-v_ST_StrokeEndCap.html + * * @const string */ const ENDCAP_FLAT = 'flat'; @@ -49,9 +51,10 @@ class Outline extends AbstractStyle const ENDCAP_ROUND = 'round'; /** - * Arrowhead type constants + * Arrowhead type constants. * * @see http://www.schemacentral.com/sc/ooxml/t-v_ST_StrokeArrowType.html + * * @const string */ const ARROW_NONE = 'none'; @@ -62,74 +65,75 @@ class Outline extends AbstractStyle const ARROW_OPEN = 'open'; /** - * Unit; No set method for now + * Unit; No set method for now. * * @var string */ private $unit = 'pt'; /** - * Outline weight + * Outline weight. * - * @var int|float + * @var float|int */ private $weight; /** - * Outline color + * Outline color. * * @var string */ private $color; /** - * Dash type + * Dash type. * * @var string */ private $dash; /** - * Line style + * Line style. * * @var string */ private $line; /** - * End cap + * End cap. * * @var string + * * @see http://www.schemacentral.com/sc/ooxml/t-v_ST_StrokeEndCap.html */ private $endCap; /** - * Start arrow type + * Start arrow type. * * @var string */ private $startArrow; /** - * End arrow type + * End arrow type. * * @var string */ private $endArrow; /** - * Create a new instance + * Create a new instance. * * @param array $style */ - public function __construct($style = array()) + public function __construct($style = []) { $this->setStyleByArray($style); } /** - * Get unit + * Get unit. * * @return string */ @@ -139,9 +143,9 @@ public function getUnit() } /** - * Get weight + * Get weight. * - * @return int|float + * @return float|int */ public function getWeight() { @@ -149,9 +153,10 @@ public function getWeight() } /** - * Set weight + * Set weight. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setWeight($value = null) @@ -162,7 +167,7 @@ public function setWeight($value = null) } /** - * Get color + * Get color. * * @return string */ @@ -172,9 +177,10 @@ public function getColor() } /** - * Set color + * Set color. * * @param string $value + * * @return self */ public function setColor($value = null) @@ -185,7 +191,7 @@ public function setColor($value = null) } /** - * Get dash type + * Get dash type. * * @return string */ @@ -195,9 +201,10 @@ public function getDash() } /** - * Set dash type + * Set dash type. * * @param string $value + * * @return self */ public function setDash($value = null) @@ -208,7 +215,7 @@ public function setDash($value = null) } /** - * Get line style + * Get line style. * * @return string */ @@ -218,22 +225,23 @@ public function getLine() } /** - * Set line style + * Set line style. * * @param string $value + * * @return self */ public function setLine($value = null) { - $enum = array(self::LINE_SINGLE, self::LINE_THIN_THIN, self::LINE_THIN_THICK, - self::LINE_THICK_THIN, self::LINE_THICK_BETWEEN_THIN, ); + $enum = [self::LINE_SINGLE, self::LINE_THIN_THIN, self::LINE_THIN_THICK, + self::LINE_THICK_THIN, self::LINE_THICK_BETWEEN_THIN, ]; $this->line = $this->setEnumVal($value, $enum, null); return $this; } /** - * Get endCap style + * Get endCap style. * * @return string */ @@ -243,21 +251,22 @@ public function getEndCap() } /** - * Set endCap style + * Set endCap style. * * @param string $value + * * @return self */ public function setEndCap($value = null) { - $enum = array(self::ENDCAP_FLAT, self::ENDCAP_SQUARE, self::ENDCAP_ROUND); + $enum = [self::ENDCAP_FLAT, self::ENDCAP_SQUARE, self::ENDCAP_ROUND]; $this->endCap = $this->setEnumVal($value, $enum, null); return $this; } /** - * Get startArrow + * Get startArrow. * * @return string */ @@ -267,22 +276,23 @@ public function getStartArrow() } /** - * Set pattern + * Set pattern. * * @param string $value + * * @return self */ public function setStartArrow($value = null) { - $enum = array(self::ARROW_NONE, self::ARROW_BLOCK, self::ARROW_CLASSIC, - self::ARROW_OVAL, self::ARROW_DIAMOND, self::ARROW_OPEN, ); + $enum = [self::ARROW_NONE, self::ARROW_BLOCK, self::ARROW_CLASSIC, + self::ARROW_OVAL, self::ARROW_DIAMOND, self::ARROW_OPEN, ]; $this->startArrow = $this->setEnumVal($value, $enum, null); return $this; } /** - * Get endArrow + * Get endArrow. * * @return string */ @@ -292,15 +302,16 @@ public function getEndArrow() } /** - * Set pattern + * Set pattern. * * @param string $value + * * @return self */ public function setEndArrow($value = null) { - $enum = array(self::ARROW_NONE, self::ARROW_BLOCK, self::ARROW_CLASSIC, - self::ARROW_OVAL, self::ARROW_DIAMOND, self::ARROW_OPEN, ); + $enum = [self::ARROW_NONE, self::ARROW_BLOCK, self::ARROW_CLASSIC, + self::ARROW_OVAL, self::ARROW_DIAMOND, self::ARROW_OPEN, ]; $this->endArrow = $this->setEnumVal($value, $enum, null); return $this; diff --git a/src/PhpWord/Style/Paper.php b/src/PhpWord/Style/Paper.php index 3c93ed8f2f..3a340bda9d 100644 --- a/src/PhpWord/Style/Paper.php +++ b/src/PhpWord/Style/Paper.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,7 +20,7 @@ use PhpOffice\PhpWord\Shared\Converter; /** - * Paper size from ISO/IEC 29500-1:2012 pg. 1656-1657 + * Paper size from ISO/IEC 29500-1:2012 pg. 1656-1657. * * 1 = Letter paper (8.5 in. by 11 in.) * 2 = Letter small paper (8.5 in. by 11 in.) @@ -94,43 +94,43 @@ class Paper extends AbstractStyle { /** - * Paper sizes + * Paper sizes. * * @var array */ - private $sizes = array( - 'A3' => array(297, 420, 'mm'), - 'A4' => array(210, 297, 'mm'), - 'A5' => array(148, 210, 'mm'), - 'B5' => array(176, 250, 'mm'), - 'Folio' => array(8.5, 13, 'in'), - 'Legal' => array(8.5, 14, 'in'), - 'Letter' => array(8.5, 11, 'in'), - ); + private $sizes = [ + 'A3' => [297, 420, 'mm'], + 'A4' => [210, 297, 'mm'], + 'A5' => [148, 210, 'mm'], + 'B5' => [176, 250, 'mm'], + 'Folio' => [8.5, 13, 'in'], + 'Legal' => [8.5, 14, 'in'], + 'Letter' => [8.5, 11, 'in'], + ]; /** - * Paper size + * Paper size. * * @var string */ private $size = 'A4'; /** - * Width + * Width. * * @var float (twip) */ private $width; /** - * Height + * Height. * * @var float (twip) */ private $height; /** - * Create a new instance + * Create a new instance. * * @param string $size */ @@ -140,7 +140,7 @@ public function __construct($size = 'A4') } /** - * Get size + * Get size. * * @return string */ @@ -150,16 +150,17 @@ public function getSize() } /** - * Set size + * Set size. * * @param string $size + * * @return self */ public function setSize($size) { $this->size = $this->setEnumVal($size, array_keys($this->sizes), $this->size); - list($width, $height, $unit) = $this->sizes[$this->size]; + [$width, $height, $unit] = $this->sizes[$this->size]; if ($unit == 'mm') { $this->width = Converter::cmToTwip($width / 10); @@ -173,7 +174,7 @@ public function setSize($size) } /** - * Get width + * Get width. * * @return float */ @@ -183,7 +184,7 @@ public function getWidth() } /** - * Get height + * Get height. * * @return float */ diff --git a/src/PhpWord/Style/Paragraph.php b/src/PhpWord/Style/Paragraph.php index 522dea9baf..cce8d3ce9c 100644 --- a/src/PhpWord/Style/Paragraph.php +++ b/src/PhpWord/Style/Paragraph.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -23,7 +23,7 @@ use PhpOffice\PhpWord\SimpleType\TextAlignment; /** - * Paragraph style + * Paragraph style. * * OOXML: * - General: alignment, outline level @@ -57,21 +57,21 @@ class Paragraph extends Border const LINE_HEIGHT = 240; /** - * Aliases + * Aliases. * * @var array */ - protected $aliases = array('line-height' => 'lineHeight', 'line-spacing' => 'spacing'); + protected $aliases = ['line-height' => 'lineHeight', 'line-spacing' => 'spacing']; /** - * Parent style + * Parent style. * * @var string */ private $basedOn = 'Normal'; /** - * Style for next paragraph + * Style for next paragraph. * * @var string */ @@ -83,115 +83,116 @@ class Paragraph extends Border private $alignment = ''; /** - * Indentation + * Indentation. * - * @var \PhpOffice\PhpWord\Style\Indentation|null + * @var null|\PhpOffice\PhpWord\Style\Indentation */ private $indentation; /** - * Spacing + * Spacing. * * @var \PhpOffice\PhpWord\Style\Spacing */ private $spacing; /** - * Text line height + * Text line height. * * @var int */ private $lineHeight; /** - * Allow first/last line to display on a separate page + * Allow first/last line to display on a separate page. * * @var bool */ private $widowControl = true; /** - * Keep paragraph with next paragraph + * Keep paragraph with next paragraph. * * @var bool */ private $keepNext = false; /** - * Keep all lines on one page + * Keep all lines on one page. * * @var bool */ private $keepLines = false; /** - * Start paragraph on next page + * Start paragraph on next page. * * @var bool */ private $pageBreakBefore = false; /** - * Numbering style name + * Numbering style name. * * @var string */ private $numStyle; /** - * Numbering level + * Numbering level. * * @var int */ private $numLevel = 0; /** - * Set of Custom Tab Stops + * Set of Custom Tab Stops. * * @var \PhpOffice\PhpWord\Style\Tab[] */ - private $tabs = array(); + private $tabs = []; /** - * Shading + * Shading. * * @var \PhpOffice\PhpWord\Style\Shading */ private $shading; /** - * Ignore Spacing Above and Below When Using Identical Styles + * Ignore Spacing Above and Below When Using Identical Styles. * * @var bool */ private $contextualSpacing = false; /** - * Right to Left Paragraph Layout + * Right to Left Paragraph Layout. * * @var bool */ private $bidi = false; /** - * Vertical Character Alignment on Line + * Vertical Character Alignment on Line. * * @var string */ private $textAlignment; /** - * Suppress hyphenation for paragraph + * Suppress hyphenation for paragraph. * * @var bool */ private $suppressAutoHyphens = false; /** - * Set Style value + * Set Style value. * * @param string $key * @param mixed $value + * * @return self */ public function setStyleValue($key, $value) @@ -205,41 +206,42 @@ public function setStyleValue($key, $value) } /** - * Get style values + * Get style values. * * An experiment to retrieve all style values in one function. This will * reduce function call and increase cohesion between functions. Should be * implemented in all styles. * * @ignoreScrutinizerPatch + * * @return array */ public function getStyleValues() { - $styles = array( - 'name' => $this->getStyleName(), - 'basedOn' => $this->getBasedOn(), - 'next' => $this->getNext(), - 'alignment' => $this->getAlignment(), - 'indentation' => $this->getIndentation(), - 'spacing' => $this->getSpace(), - 'pagination' => array( - 'widowControl' => $this->hasWidowControl(), - 'keepNext' => $this->isKeepNext(), - 'keepLines' => $this->isKeepLines(), - 'pageBreak' => $this->hasPageBreakBefore(), - ), - 'numbering' => array( - 'style' => $this->getNumStyle(), - 'level' => $this->getNumLevel(), - ), - 'tabs' => $this->getTabs(), - 'shading' => $this->getShading(), - 'contextualSpacing' => $this->hasContextualSpacing(), - 'bidi' => $this->isBidi(), - 'textAlignment' => $this->getTextAlignment(), + $styles = [ + 'name' => $this->getStyleName(), + 'basedOn' => $this->getBasedOn(), + 'next' => $this->getNext(), + 'alignment' => $this->getAlignment(), + 'indentation' => $this->getIndentation(), + 'spacing' => $this->getSpace(), + 'pagination' => [ + 'widowControl' => $this->hasWidowControl(), + 'keepNext' => $this->isKeepNext(), + 'keepLines' => $this->isKeepLines(), + 'pageBreak' => $this->hasPageBreakBefore(), + ], + 'numbering' => [ + 'style' => $this->getNumStyle(), + 'level' => $this->getNumLevel(), + ], + 'tabs' => $this->getTabs(), + 'shading' => $this->getShading(), + 'contextualSpacing' => $this->hasContextualSpacing(), + 'bidi' => $this->isBidi(), + 'textAlignment' => $this->getTextAlignment(), 'suppressAutoHyphens' => $this->hasSuppressAutoHyphens(), - ); + ]; return $styles; } @@ -297,7 +299,7 @@ public function setAlign($value = null) } /** - * Get parent style ID + * Get parent style ID. * * @return string */ @@ -307,9 +309,10 @@ public function getBasedOn() } /** - * Set parent style ID + * Set parent style ID. * * @param string $value + * * @return self */ public function setBasedOn($value = 'Normal') @@ -320,7 +323,7 @@ public function setBasedOn($value = 'Normal') } /** - * Get style for next paragraph + * Get style for next paragraph. * * @return string */ @@ -330,9 +333,10 @@ public function getNext() } /** - * Set style for next paragraph + * Set style for next paragraph. * * @param string $value + * * @return self */ public function setNext($value = null) @@ -343,7 +347,7 @@ public function setNext($value = null) } /** - * Get shading + * Get shading. * * @return \PhpOffice\PhpWord\Style\Indentation */ @@ -353,9 +357,10 @@ public function getIndentation() } /** - * Set shading + * Set shading. * * @param mixed $value + * * @return self */ public function setIndentation($value = null) @@ -366,7 +371,7 @@ public function setIndentation($value = null) } /** - * Get indentation + * Get indentation. * * @return int */ @@ -376,18 +381,19 @@ public function getIndent() } /** - * Set indentation + * Set indentation. * * @param int $value + * * @return self */ public function setIndent($value = null) { - return $this->setIndentation(array('left' => $value)); + return $this->setIndentation(['left' => $value]); } /** - * Get hanging + * Get hanging. * * @return int */ @@ -397,20 +403,22 @@ public function getHanging() } /** - * Set hanging + * Set hanging. * * @param int $value + * * @return self */ public function setHanging($value = null) { - return $this->setIndentation(array('hanging' => $value)); + return $this->setIndentation(['hanging' => $value]); } /** - * Get spacing + * Get spacing. * * @return \PhpOffice\PhpWord\Style\Spacing + * * @todo Rename to getSpacing in 1.0 */ public function getSpace() @@ -419,10 +427,12 @@ public function getSpace() } /** - * Set spacing + * Set spacing. * * @param mixed $value + * * @return self + * * @todo Rename to setSpacing in 1.0 */ public function setSpace($value = null) @@ -433,7 +443,7 @@ public function setSpace($value = null) } /** - * Get space before paragraph + * Get space before paragraph. * * @return int */ @@ -443,18 +453,19 @@ public function getSpaceBefore() } /** - * Set space before paragraph + * Set space before paragraph. * * @param int $value + * * @return self */ public function setSpaceBefore($value = null) { - return $this->setSpace(array('before' => $value)); + return $this->setSpace(['before' => $value]); } /** - * Get space after paragraph + * Get space after paragraph. * * @return int */ @@ -464,20 +475,21 @@ public function getSpaceAfter() } /** - * Set space after paragraph + * Set space after paragraph. * * @param int $value + * * @return self */ public function setSpaceAfter($value = null) { - return $this->setSpace(array('after' => $value)); + return $this->setSpace(['after' => $value]); } /** - * Get spacing between lines + * Get spacing between lines. * - * @return int|float + * @return float|int */ public function getSpacing() { @@ -485,18 +497,19 @@ public function getSpacing() } /** - * Set spacing between lines + * Set spacing between lines. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setSpacing($value = null) { - return $this->setSpace(array('line' => $value)); + return $this->setSpace(['line' => $value]); } /** - * Get spacing line rule + * Get spacing line rule. * * @return string */ @@ -506,20 +519,21 @@ public function getSpacingLineRule() } /** - * Set the spacing line rule + * Set the spacing line rule. * * @param string $value Possible values are defined in LineSpacingRule + * * @return \PhpOffice\PhpWord\Style\Paragraph */ public function setSpacingLineRule($value) { - return $this->setSpace(array('lineRule' => $value)); + return $this->setSpace(['lineRule' => $value]); } /** - * Get line height + * Get line height. * - * @return int|float + * @return float|int */ public function getLineHeight() { @@ -527,11 +541,10 @@ public function getLineHeight() } /** - * Set the line height + * Set the line height. * - * @param int|float|string $lineHeight + * @param float|int|string $lineHeight * - * @throws \PhpOffice\PhpWord\Exception\InvalidStyleException * @return self */ public function setLineHeight($lineHeight) @@ -552,7 +565,7 @@ public function setLineHeight($lineHeight) } /** - * Get allow first/last line to display on a separate page setting + * Get allow first/last line to display on a separate page setting. * * @return bool */ @@ -562,9 +575,10 @@ public function hasWidowControl() } /** - * Set keep paragraph with next paragraph setting + * Set keep paragraph with next paragraph setting. * * @param bool $value + * * @return self */ public function setWidowControl($value = true) @@ -575,7 +589,7 @@ public function setWidowControl($value = true) } /** - * Get keep paragraph with next paragraph setting + * Get keep paragraph with next paragraph setting. * * @return bool */ @@ -585,9 +599,10 @@ public function isKeepNext() } /** - * Set keep paragraph with next paragraph setting + * Set keep paragraph with next paragraph setting. * * @param bool $value + * * @return self */ public function setKeepNext($value = true) @@ -598,7 +613,7 @@ public function setKeepNext($value = true) } /** - * Get keep all lines on one page setting + * Get keep all lines on one page setting. * * @return bool */ @@ -608,9 +623,10 @@ public function isKeepLines() } /** - * Set keep all lines on one page setting + * Set keep all lines on one page setting. * * @param bool $value + * * @return self */ public function setKeepLines($value = true) @@ -621,7 +637,7 @@ public function setKeepLines($value = true) } /** - * Get start paragraph on next page setting + * Get start paragraph on next page setting. * * @return bool */ @@ -631,9 +647,10 @@ public function hasPageBreakBefore() } /** - * Set start paragraph on next page setting + * Set start paragraph on next page setting. * * @param bool $value + * * @return self */ public function setPageBreakBefore($value = true) @@ -644,7 +661,7 @@ public function setPageBreakBefore($value = true) } /** - * Get numbering style name + * Get numbering style name. * * @return string */ @@ -654,9 +671,10 @@ public function getNumStyle() } /** - * Set numbering style name + * Set numbering style name. * * @param string $value + * * @return self */ public function setNumStyle($value) @@ -667,7 +685,7 @@ public function setNumStyle($value) } /** - * Get numbering level + * Get numbering level. * * @return int */ @@ -677,9 +695,10 @@ public function getNumLevel() } /** - * Set numbering level + * Set numbering level. * * @param int $value + * * @return self */ public function setNumLevel($value = 0) @@ -690,7 +709,7 @@ public function setNumLevel($value = 0) } /** - * Get tabs + * Get tabs. * * @return \PhpOffice\PhpWord\Style\Tab[] */ @@ -700,9 +719,10 @@ public function getTabs() } /** - * Set tabs + * Set tabs. * * @param array $value + * * @return self */ public function setTabs($value = null) @@ -715,7 +735,7 @@ public function setTabs($value = null) } /** - * Get allow first/last line to display on a separate page setting + * Get allow first/last line to display on a separate page setting. * * @deprecated 0.10.0 * @@ -727,7 +747,7 @@ public function getWidowControl() } /** - * Get keep paragraph with next paragraph setting + * Get keep paragraph with next paragraph setting. * * @deprecated 0.10.0 * @@ -739,7 +759,7 @@ public function getKeepNext() } /** - * Get keep all lines on one page setting + * Get keep all lines on one page setting. * * @deprecated 0.10.0 * @@ -751,7 +771,7 @@ public function getKeepLines() } /** - * Get start paragraph on next page setting + * Get start paragraph on next page setting. * * @deprecated 0.10.0 * @@ -763,7 +783,7 @@ public function getPageBreakBefore() } /** - * Get shading + * Get shading. * * @return \PhpOffice\PhpWord\Style\Shading */ @@ -773,9 +793,10 @@ public function getShading() } /** - * Set shading + * Set shading. * * @param mixed $value + * * @return self */ public function setShading($value = null) @@ -786,7 +807,7 @@ public function setShading($value = null) } /** - * Get contextualSpacing + * Get contextualSpacing. * * @return bool */ @@ -796,9 +817,10 @@ public function hasContextualSpacing() } /** - * Set contextualSpacing + * Set contextualSpacing. * * @param bool $contextualSpacing + * * @return self */ public function setContextualSpacing($contextualSpacing) @@ -809,7 +831,7 @@ public function setContextualSpacing($contextualSpacing) } /** - * Get bidirectional + * Get bidirectional. * * @return bool */ @@ -819,10 +841,11 @@ public function isBidi() } /** - * Set bidi + * Set bidi. * * @param bool $bidi * Set to true to write from right to left + * * @return self */ public function setBidi($bidi) @@ -833,7 +856,7 @@ public function setBidi($bidi) } /** - * Get textAlignment + * Get textAlignment. * * @return string */ @@ -843,9 +866,10 @@ public function getTextAlignment() } /** - * Set textAlignment + * Set textAlignment. * * @param string $textAlignment + * * @return self */ public function setTextAlignment($textAlignment) @@ -867,7 +891,7 @@ public function hasSuppressAutoHyphens() /** * @param bool $suppressAutoHyphens */ - public function setSuppressAutoHyphens($suppressAutoHyphens) + public function setSuppressAutoHyphens($suppressAutoHyphens): void { $this->suppressAutoHyphens = (bool) $suppressAutoHyphens; } diff --git a/src/PhpWord/Style/Row.php b/src/PhpWord/Style/Row.php index ad801af6e2..e7be3992e1 100644 --- a/src/PhpWord/Style/Row.php +++ b/src/PhpWord/Style/Row.php @@ -11,49 +11,49 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * Table row style + * Table row style. * * @since 0.8.0 */ class Row extends AbstractStyle { /** - * Repeat table row on every new page + * Repeat table row on every new page. * * @var bool */ private $tblHeader = false; /** - * Table row cannot break across pages + * Table row cannot break across pages. * * @var bool */ private $cantSplit = false; /** - * Table row exact height + * Table row exact height. * * @var bool */ private $exactHeight = false; /** - * Create a new row style + * Create a new row style. */ public function __construct() { } /** - * Is tblHeader + * Is tblHeader. * * @return bool */ @@ -63,9 +63,10 @@ public function isTblHeader() } /** - * Is tblHeader + * Is tblHeader. * * @param bool $value + * * @return self */ public function setTblHeader($value = true) @@ -76,7 +77,7 @@ public function setTblHeader($value = true) } /** - * Is cantSplit + * Is cantSplit. * * @return bool */ @@ -86,9 +87,10 @@ public function isCantSplit() } /** - * Is cantSplit + * Is cantSplit. * * @param bool $value + * * @return self */ public function setCantSplit($value = true) @@ -99,7 +101,7 @@ public function setCantSplit($value = true) } /** - * Is exactHeight + * Is exactHeight. * * @return bool */ @@ -109,9 +111,10 @@ public function isExactHeight() } /** - * Set exactHeight + * Set exactHeight. * * @param bool $value + * * @return self */ public function setExactHeight($value = true) @@ -122,7 +125,7 @@ public function setExactHeight($value = true) } /** - * Get tblHeader + * Get tblHeader. * * @deprecated 0.10.0 * @@ -134,7 +137,7 @@ public function getTblHeader() } /** - * Get cantSplit + * Get cantSplit. * * @deprecated 0.10.0 * @@ -146,7 +149,7 @@ public function getCantSplit() } /** - * Get exactHeight + * Get exactHeight. * * @deprecated 0.10.0 * diff --git a/src/PhpWord/Style/Section.php b/src/PhpWord/Style/Section.php index 697add7456..29e06bf3cf 100644 --- a/src/PhpWord/Style/Section.php +++ b/src/PhpWord/Style/Section.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,12 +21,12 @@ use PhpOffice\PhpWord\SimpleType\VerticalJc; /** - * Section settings + * Section settings. */ class Section extends Border { /** - * Page orientation + * Page orientation. * * @const string */ @@ -34,7 +34,7 @@ class Section extends Border const ORIENTATION_LANDSCAPE = 'landscape'; /** - * Page default constants + * Page default constants. * * @const int|float */ @@ -48,107 +48,109 @@ class Section extends Border const DEFAULT_COLUMN_SPACING = 720; // In twips. /** - * Page Orientation + * Page Orientation. * * @var string + * * @see http://www.schemacentral.com/sc/ooxml/a-w_orient-1.html */ private $orientation = self::ORIENTATION_PORTRAIT; /** - * Paper size + * Paper size. * * @var \PhpOffice\PhpWord\Style\Paper */ private $paper; /** - * Page Size Width + * Page Size Width. * - * @var int|float + * @var float|int */ private $pageSizeW = self::DEFAULT_WIDTH; /** - * Page Size Height + * Page Size Height. * - * @var int|float + * @var float|int */ private $pageSizeH = self::DEFAULT_HEIGHT; /** - * Top margin spacing + * Top margin spacing. * - * @var int|float + * @var float|int */ private $marginTop = self::DEFAULT_MARGIN; /** - * Left margin spacing + * Left margin spacing. * - * @var int|float + * @var float|int */ private $marginLeft = self::DEFAULT_MARGIN; /** - * Right margin spacing + * Right margin spacing. * - * @var int|float + * @var float|int */ private $marginRight = self::DEFAULT_MARGIN; /** - * Bottom margin spacing + * Bottom margin spacing. * - * @var int|float + * @var float|int */ private $marginBottom = self::DEFAULT_MARGIN; /** - * Page gutter spacing + * Page gutter spacing. + * + * @var float|int * - * @var int|float * @see http://www.schemacentral.com/sc/ooxml/e-w_pgMar-1.html */ private $gutter = self::DEFAULT_GUTTER; /** - * Header height + * Header height. * - * @var int|float + * @var float|int */ private $headerHeight = self::DEFAULT_HEADER_HEIGHT; /** - * Footer height + * Footer height. * - * @var int|float + * @var float|int */ private $footerHeight = self::DEFAULT_FOOTER_HEIGHT; /** - * Page Numbering Start + * Page Numbering Start. * * @var int */ private $pageNumberingStart; /** - * Section columns count + * Section columns count. * * @var int */ private $colsNum = self::DEFAULT_COLUMN_COUNT; /** - * Section spacing between columns + * Section spacing between columns. * - * @var int|float + * @var float|int */ private $colsSpace = self::DEFAULT_COLUMN_SPACING; /** - * Section break type + * Section break type. * * Options: * - nextPage: Next page section break @@ -162,23 +164,24 @@ class Section extends Border private $breakType; /** - * Line numbering + * Line numbering. * * @var \PhpOffice\PhpWord\Style\LineNumbering + * * @see http://www.schemacentral.com/sc/ooxml/e-w_lnNumType-1.html */ private $lineNumbering; /** * Vertical Text Alignment on Page - * One of \PhpOffice\PhpWord\SimpleType\VerticalJc + * One of \PhpOffice\PhpWord\SimpleType\VerticalJc. * * @var string */ private $vAlign; /** - * Create new instance + * Create new instance. */ public function __construct() { @@ -186,7 +189,7 @@ public function __construct() } /** - * Get paper size + * Get paper size. * * @return string */ @@ -196,9 +199,10 @@ public function getPaperSize() } /** - * Set paper size + * Set paper size. * * @param string $value + * * @return self */ public function setPaperSize($value = '') @@ -217,10 +221,11 @@ public function setPaperSize($value = '') } /** - * Set Setting Value + * Set Setting Value. * * @param string $key * @param string $value + * * @return self */ public function setSettingValue($key, $value) @@ -229,20 +234,21 @@ public function setSettingValue($key, $value) } /** - * Set orientation + * Set orientation. * * @param string $value + * * @return self */ public function setOrientation($value = null) { - $enum = array(self::ORIENTATION_PORTRAIT, self::ORIENTATION_LANDSCAPE); + $enum = [self::ORIENTATION_PORTRAIT, self::ORIENTATION_LANDSCAPE]; $this->orientation = $this->setEnumVal($value, $enum, $this->orientation); - /** @var int|float $longSide Type hint */ + /** @var float|int $longSide Type hint */ $longSide = $this->pageSizeW >= $this->pageSizeH ? $this->pageSizeW : $this->pageSizeH; - /** @var int|float $shortSide Type hint */ + /** @var float|int $shortSide Type hint */ $shortSide = $this->pageSizeW < $this->pageSizeH ? $this->pageSizeW : $this->pageSizeH; if ($this->orientation == self::ORIENTATION_PORTRAIT) { @@ -257,7 +263,7 @@ public function setOrientation($value = null) } /** - * Get Page Orientation + * Get Page Orientation. * * @return string */ @@ -267,7 +273,7 @@ public function getOrientation() } /** - * Set Portrait Orientation + * Set Portrait Orientation. * * @return self */ @@ -277,7 +283,7 @@ public function setPortrait() } /** - * Set Landscape Orientation + * Set Landscape Orientation. * * @return self */ @@ -287,9 +293,9 @@ public function setLandscape() } /** - * Get Page Size Width + * Get Page Size Width. * - * @return int|float|null + * @return null|float|int * * @since 0.12.0 */ @@ -299,7 +305,7 @@ public function getPageSizeW() } /** - * @param int|float|null $value + * @param null|float|int $value * * @return \PhpOffice\PhpWord\Style\Section * @@ -313,9 +319,9 @@ public function setPageSizeW($value = null) } /** - * Get Page Size Height + * Get Page Size Height. * - * @return int|float|null + * @return null|float|int * * @since 0.12.0 */ @@ -325,7 +331,7 @@ public function getPageSizeH() } /** - * @param int|float|null $value + * @param null|float|int $value * * @return \PhpOffice\PhpWord\Style\Section * @@ -339,9 +345,9 @@ public function setPageSizeH($value = null) } /** - * Get Margin Top + * Get Margin Top. * - * @return int|float + * @return float|int */ public function getMarginTop() { @@ -349,9 +355,10 @@ public function getMarginTop() } /** - * Set Margin Top + * Set Margin Top. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setMarginTop($value = null) @@ -362,9 +369,9 @@ public function setMarginTop($value = null) } /** - * Get Margin Left + * Get Margin Left. * - * @return int|float + * @return float|int */ public function getMarginLeft() { @@ -372,9 +379,10 @@ public function getMarginLeft() } /** - * Set Margin Left + * Set Margin Left. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setMarginLeft($value = null) @@ -385,9 +393,9 @@ public function setMarginLeft($value = null) } /** - * Get Margin Right + * Get Margin Right. * - * @return int|float + * @return float|int */ public function getMarginRight() { @@ -395,9 +403,10 @@ public function getMarginRight() } /** - * Set Margin Right + * Set Margin Right. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setMarginRight($value = null) @@ -408,9 +417,9 @@ public function setMarginRight($value = null) } /** - * Get Margin Bottom + * Get Margin Bottom. * - * @return int|float + * @return float|int */ public function getMarginBottom() { @@ -418,9 +427,10 @@ public function getMarginBottom() } /** - * Set Margin Bottom + * Set Margin Bottom. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setMarginBottom($value = null) @@ -431,9 +441,9 @@ public function setMarginBottom($value = null) } /** - * Get gutter + * Get gutter. * - * @return int|float + * @return float|int */ public function getGutter() { @@ -441,9 +451,10 @@ public function getGutter() } /** - * Set gutter + * Set gutter. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setGutter($value = null) @@ -454,9 +465,9 @@ public function setGutter($value = null) } /** - * Get Header Height + * Get Header Height. * - * @return int|float + * @return float|int */ public function getHeaderHeight() { @@ -464,9 +475,10 @@ public function getHeaderHeight() } /** - * Set Header Height + * Set Header Height. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setHeaderHeight($value = null) @@ -477,9 +489,9 @@ public function setHeaderHeight($value = null) } /** - * Get Footer Height + * Get Footer Height. * - * @return int|float + * @return float|int */ public function getFooterHeight() { @@ -487,9 +499,10 @@ public function getFooterHeight() } /** - * Set Footer Height + * Set Footer Height. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setFooterHeight($value = null) @@ -500,7 +513,7 @@ public function setFooterHeight($value = null) } /** - * Get page numbering start + * Get page numbering start. * * @return null|int */ @@ -510,9 +523,10 @@ public function getPageNumberingStart() } /** - * Set page numbering start + * Set page numbering start. * * @param null|int $pageNumberingStart + * * @return self */ public function setPageNumberingStart($pageNumberingStart = null) @@ -523,7 +537,7 @@ public function setPageNumberingStart($pageNumberingStart = null) } /** - * Get Section Columns Count + * Get Section Columns Count. * * @return int */ @@ -533,9 +547,10 @@ public function getColsNum() } /** - * Set Section Columns Count + * Set Section Columns Count. * * @param int $value + * * @return self */ public function setColsNum($value = null) @@ -546,9 +561,9 @@ public function setColsNum($value = null) } /** - * Get Section Space Between Columns + * Get Section Space Between Columns. * - * @return int|float + * @return float|int */ public function getColsSpace() { @@ -556,9 +571,10 @@ public function getColsSpace() } /** - * Set Section Space Between Columns + * Set Section Space Between Columns. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setColsSpace($value = null) @@ -569,7 +585,7 @@ public function setColsSpace($value = null) } /** - * Get Break Type + * Get Break Type. * * @return string */ @@ -579,9 +595,10 @@ public function getBreakType() } /** - * Set Break Type + * Set Break Type. * * @param string $value + * * @return self */ public function setBreakType($value = null) @@ -592,7 +609,7 @@ public function setBreakType($value = null) } /** - * Get line numbering + * Get line numbering. * * @return \PhpOffice\PhpWord\Style\LineNumbering */ @@ -602,9 +619,10 @@ public function getLineNumbering() } /** - * Set line numbering + * Set line numbering. * * @param mixed $value + * * @return self */ public function setLineNumbering($value = null) @@ -615,7 +633,7 @@ public function setLineNumbering($value = null) } /** - * Get vertical alignment + * Get vertical alignment. * * @return string */ @@ -625,9 +643,10 @@ public function getVAlign() } /** - * Set vertical alignment + * Set vertical alignment. * * @param string $value + * * @return self */ public function setVAlign($value = null) diff --git a/src/PhpWord/Style/Shading.php b/src/PhpWord/Style/Shading.php index 154df26c7a..81d69e313d 100644 --- a/src/PhpWord/Style/Shading.php +++ b/src/PhpWord/Style/Shading.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * Shading style + * Shading style. * * @see http://www.schemacentral.com/sc/ooxml/t-w_CT_Shd.html * @since 0.10.0 @@ -26,9 +26,10 @@ class Shading extends AbstractStyle { /** - * Pattern constants (partly) + * Pattern constants (partly). * * @const string + * * @see http://www.schemacentral.com/sc/ooxml/t-w_ST_Shd.html */ const PATTERN_CLEAR = 'clear'; // No pattern @@ -40,39 +41,40 @@ class Shading extends AbstractStyle const PATTERN_DCROSS = 'diagCross'; // Diagonal cross pattern /** - * Shading pattern + * Shading pattern. * * @var string + * * @see http://www.schemacentral.com/sc/ooxml/t-w_ST_Shd.html */ private $pattern = self::PATTERN_CLEAR; /** - * Shading pattern color + * Shading pattern color. * * @var string */ private $color; /** - * Shading background color + * Shading background color. * * @var string */ private $fill; /** - * Create a new instance + * Create a new instance. * * @param array $style */ - public function __construct($style = array()) + public function __construct($style = []) { $this->setStyleByArray($style); } /** - * Get pattern + * Get pattern. * * @return string */ @@ -82,24 +84,25 @@ public function getPattern() } /** - * Set pattern + * Set pattern. * * @param string $value + * * @return self */ public function setPattern($value = null) { - $enum = array( + $enum = [ self::PATTERN_CLEAR, self::PATTERN_SOLID, self::PATTERN_HSTRIPE, self::PATTERN_VSTRIPE, self::PATTERN_DSTRIPE, self::PATTERN_HCROSS, self::PATTERN_DCROSS, - ); + ]; $this->pattern = $this->setEnumVal($value, $enum, $this->pattern); return $this; } /** - * Get color + * Get color. * * @return string */ @@ -109,9 +112,10 @@ public function getColor() } /** - * Set pattern + * Set pattern. * * @param string $value + * * @return self */ public function setColor($value = null) @@ -122,7 +126,7 @@ public function setColor($value = null) } /** - * Get fill + * Get fill. * * @return string */ @@ -132,9 +136,10 @@ public function getFill() } /** - * Set fill + * Set fill. * * @param string $value + * * @return self */ public function setFill($value = null) diff --git a/src/PhpWord/Style/Shadow.php b/src/PhpWord/Style/Shadow.php index 1379a32096..3f6252d439 100644 --- a/src/PhpWord/Style/Shadow.php +++ b/src/PhpWord/Style/Shadow.php @@ -11,14 +11,14 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * Shadow style + * Shadow style. * * @see http://www.schemacentral.com/sc/ooxml/t-v_CT_Shadow.html * @since 0.12.0 @@ -26,31 +26,31 @@ class Shadow extends AbstractStyle { /** - * Color + * Color. * * @var string */ private $color; /** - * Offset; Format: 3pt,3pt + * Offset; Format: 3pt,3pt. * * @var string */ private $offset; /** - * Create a new instance + * Create a new instance. * * @param array $style */ - public function __construct($style = array()) + public function __construct($style = []) { $this->setStyleByArray($style); } /** - * Get color + * Get color. * * @return string */ @@ -60,9 +60,10 @@ public function getColor() } /** - * Set color + * Set color. * * @param string $value + * * @return self */ public function setColor($value = null) @@ -73,7 +74,7 @@ public function setColor($value = null) } /** - * Get offset + * Get offset. * * @return string */ @@ -83,9 +84,10 @@ public function getOffset() } /** - * Set offset + * Set offset. * * @param string $value + * * @return self */ public function setOffset($value = null) diff --git a/src/PhpWord/Style/Shape.php b/src/PhpWord/Style/Shape.php index 0c3f817982..7dd62a1f71 100644 --- a/src/PhpWord/Style/Shape.php +++ b/src/PhpWord/Style/Shape.php @@ -11,22 +11,23 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * Shape style + * Shape style. * * @since 0.12.0 + * * @todo Skew http://www.schemacentral.com/sc/ooxml/t-o_CT_Skew.html */ class Shape extends AbstractStyle { /** - * Points + * Points. * * - Arc: startAngle endAngle; 0 = top center, moving clockwise * - Curve: from-x1,from-y1 to-x2,to-y2 control1-x,control1-y control2-x,control2-y @@ -39,61 +40,61 @@ class Shape extends AbstractStyle private $points; /** - * Roundness measure of corners; 0 = straightest (rectangular); 1 = roundest (circle/oval) + * Roundness measure of corners; 0 = straightest (rectangular); 1 = roundest (circle/oval). * * Only for rect * - * @var int|float + * @var float|int */ private $roundness; /** - * Frame + * Frame. * * @var \PhpOffice\PhpWord\Style\Frame */ private $frame; /** - * Fill + * Fill. * * @var \PhpOffice\PhpWord\Style\Fill */ private $fill; /** - * Outline + * Outline. * * @var \PhpOffice\PhpWord\Style\Outline */ private $outline; /** - * Shadow + * Shadow. * * @var \PhpOffice\PhpWord\Style\Shadow */ private $shadow; /** - * 3D extrusion + * 3D extrusion. * * @var \PhpOffice\PhpWord\Style\Extrusion */ private $extrusion; /** - * Create a new instance + * Create a new instance. * * @param array $style */ - public function __construct($style = array()) + public function __construct($style = []) { $this->setStyleByArray($style); } /** - * Get points + * Get points. * * @return string */ @@ -103,9 +104,10 @@ public function getPoints() } /** - * Set points + * Set points. * * @param string $value + * * @return self */ public function setPoints($value = null) @@ -116,9 +118,9 @@ public function setPoints($value = null) } /** - * Get roundness + * Get roundness. * - * @return int|float + * @return float|int */ public function getRoundness() { @@ -126,9 +128,10 @@ public function getRoundness() } /** - * Set roundness + * Set roundness. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setRoundness($value = null) @@ -139,7 +142,7 @@ public function setRoundness($value = null) } /** - * Get frame + * Get frame. * * @return \PhpOffice\PhpWord\Style\Frame */ @@ -149,9 +152,10 @@ public function getFrame() } /** - * Set frame + * Set frame. * * @param mixed $value + * * @return self */ public function setFrame($value = null) @@ -162,7 +166,7 @@ public function setFrame($value = null) } /** - * Get fill + * Get fill. * * @return \PhpOffice\PhpWord\Style\Fill */ @@ -172,9 +176,10 @@ public function getFill() } /** - * Set fill + * Set fill. * * @param mixed $value + * * @return self */ public function setFill($value = null) @@ -185,7 +190,7 @@ public function setFill($value = null) } /** - * Get outline + * Get outline. * * @return \PhpOffice\PhpWord\Style\Outline */ @@ -195,9 +200,10 @@ public function getOutline() } /** - * Set outline + * Set outline. * * @param mixed $value + * * @return self */ public function setOutline($value = null) @@ -208,7 +214,7 @@ public function setOutline($value = null) } /** - * Get shadow + * Get shadow. * * @return \PhpOffice\PhpWord\Style\Shadow */ @@ -218,9 +224,10 @@ public function getShadow() } /** - * Set shadow + * Set shadow. * * @param mixed $value + * * @return self */ public function setShadow($value = null) @@ -231,7 +238,7 @@ public function setShadow($value = null) } /** - * Get 3D extrusion + * Get 3D extrusion. * * @return \PhpOffice\PhpWord\Style\Extrusion */ @@ -241,9 +248,10 @@ public function getExtrusion() } /** - * Set 3D extrusion + * Set 3D extrusion. * * @param mixed $value + * * @return self */ public function setExtrusion($value = null) diff --git a/src/PhpWord/Style/Spacing.php b/src/PhpWord/Style/Spacing.php index 9bfb22822b..165cfd0262 100644 --- a/src/PhpWord/Style/Spacing.php +++ b/src/PhpWord/Style/Spacing.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,7 +20,7 @@ use PhpOffice\PhpWord\SimpleType\LineSpacingRule; /** - * Spacing between lines and above/below paragraph style + * Spacing between lines and above/below paragraph style. * * @see http://www.datypic.com/sc/ooxml/t-w_CT_Spacing.html * @since 0.10.0 @@ -28,47 +28,47 @@ class Spacing extends AbstractStyle { /** - * Spacing above paragraph (twip) + * Spacing above paragraph (twip). * - * @var int|float + * @var float|int */ private $before; /** - * Spacing below paragraph (twip) + * Spacing below paragraph (twip). * - * @var int|float + * @var float|int */ private $after; /** - * Spacing between lines in paragraph (twip) + * Spacing between lines in paragraph (twip). * - * @var int|float + * @var float|int */ private $line; /** - * Type of spacing between lines + * Type of spacing between lines. * * @var string */ private $lineRule = LineSpacingRule::AUTO; /** - * Create a new instance + * Create a new instance. * * @param array $style */ - public function __construct($style = array()) + public function __construct($style = []) { $this->setStyleByArray($style); } /** - * Get before + * Get before. * - * @return int|float + * @return float|int */ public function getBefore() { @@ -76,9 +76,10 @@ public function getBefore() } /** - * Set before + * Set before. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setBefore($value = null) @@ -89,9 +90,9 @@ public function setBefore($value = null) } /** - * Get after + * Get after. * - * @return int|float + * @return float|int */ public function getAfter() { @@ -99,9 +100,10 @@ public function getAfter() } /** - * Set after + * Set after. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setAfter($value = null) @@ -112,9 +114,9 @@ public function setAfter($value = null) } /** - * Get line + * Get line. * - * @return int|float + * @return float|int */ public function getLine() { @@ -122,9 +124,10 @@ public function getLine() } /** - * Set distance + * Set distance. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setLine($value = null) @@ -135,7 +138,7 @@ public function setLine($value = null) } /** - * Get line rule + * Get line rule. * * @return string */ @@ -145,9 +148,10 @@ public function getLineRule() } /** - * Set line rule + * Set line rule. * * @param string $value + * * @return self */ public function setLineRule($value = null) @@ -159,10 +163,12 @@ public function setLineRule($value = null) } /** - * Get line rule + * Get line rule. * * @return string + * * @deprecated Use getLineRule() instead + * * @codeCoverageIgnore */ public function getRule() @@ -171,11 +177,14 @@ public function getRule() } /** - * Set line rule + * Set line rule. * * @param string $value + * * @return self + * * @deprecated Use setLineRule() instead + * * @codeCoverageIgnore */ public function setRule($value = null) diff --git a/src/PhpWord/Style/TOC.php b/src/PhpWord/Style/TOC.php index 2efd54a4a4..d1d851bdc4 100644 --- a/src/PhpWord/Style/TOC.php +++ b/src/PhpWord/Style/TOC.php @@ -11,19 +11,19 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * TOC style + * TOC style. */ class TOC extends Tab { /** - * Tab leader types for backward compatibility + * Tab leader types for backward compatibility. * * @deprecated 0.11.0 * @@ -35,14 +35,14 @@ class TOC extends Tab const TABLEADER_NONE = self::TAB_LEADER_NONE; /** - * Indent + * Indent. * - * @var int|float (twip) + * @var float|int (twip) */ private $indent = 200; /** - * Create a new TOC Style + * Create a new TOC Style. */ public function __construct() { @@ -50,9 +50,9 @@ public function __construct() } /** - * Get Tab Position + * Get Tab Position. * - * @return int|float + * @return float|int */ public function getTabPos() { @@ -60,9 +60,10 @@ public function getTabPos() } /** - * Set Tab Position + * Set Tab Position. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setTabPos($value) @@ -71,7 +72,7 @@ public function setTabPos($value) } /** - * Get Tab Leader + * Get Tab Leader. * * @return string */ @@ -81,9 +82,10 @@ public function getTabLeader() } /** - * Set Tab Leader + * Set Tab Leader. * * @param string $value + * * @return self */ public function setTabLeader($value = self::TAB_LEADER_DOT) @@ -92,9 +94,9 @@ public function setTabLeader($value = self::TAB_LEADER_DOT) } /** - * Get Indent + * Get Indent. * - * @return int|float + * @return float|int */ public function getIndent() { @@ -102,9 +104,10 @@ public function getIndent() } /** - * Set Indent + * Set Indent. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setIndent($value) diff --git a/src/PhpWord/Style/Tab.php b/src/PhpWord/Style/Tab.php index d3cf5bd7f4..02158fd498 100644 --- a/src/PhpWord/Style/Tab.php +++ b/src/PhpWord/Style/Tab.php @@ -11,19 +11,19 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * Tab style + * Tab style. */ class Tab extends AbstractStyle { /** - * Tab stop types + * Tab stop types. * * @const string */ @@ -36,7 +36,7 @@ class Tab extends AbstractStyle const TAB_STOP_NUM = 'num'; /** - * Tab leader types + * Tab leader types. * * @const string */ @@ -48,23 +48,23 @@ class Tab extends AbstractStyle const TAB_LEADER_MIDDLEDOT = 'middleDot'; /** - * Tab stop type + * Tab stop type. * * @var string */ private $type = self::TAB_STOP_CLEAR; /** - * Tab leader character + * Tab leader character. * * @var string */ private $leader = self::TAB_LEADER_NONE; /** - * Tab stop position (twip) + * Tab stop position (twip). * - * @var int|float + * @var float|int */ private $position = 0; @@ -79,14 +79,14 @@ class Tab extends AbstractStyle */ public function __construct($type = null, $position = 0, $leader = null) { - $stopTypes = array( + $stopTypes = [ self::TAB_STOP_CLEAR, self::TAB_STOP_LEFT, self::TAB_STOP_CENTER, self::TAB_STOP_RIGHT, self::TAB_STOP_DECIMAL, self::TAB_STOP_BAR, self::TAB_STOP_NUM, - ); - $leaderTypes = array( + ]; + $leaderTypes = [ self::TAB_LEADER_NONE, self::TAB_LEADER_DOT, self::TAB_LEADER_HYPHEN, self::TAB_LEADER_UNDERSCORE, self::TAB_LEADER_HEAVY, self::TAB_LEADER_MIDDLEDOT, - ); + ]; $this->type = $this->setEnumVal($type, $stopTypes, $this->type); $this->position = $this->setNumericVal($position, $this->position); @@ -94,7 +94,7 @@ public function __construct($type = null, $position = 0, $leader = null) } /** - * Get stop type + * Get stop type. * * @return string */ @@ -104,25 +104,26 @@ public function getType() } /** - * Set stop type + * Set stop type. * * @param string $value + * * @return self */ public function setType($value) { - $enum = array( + $enum = [ self::TAB_STOP_CLEAR, self::TAB_STOP_LEFT, self::TAB_STOP_CENTER, self::TAB_STOP_RIGHT, self::TAB_STOP_DECIMAL, self::TAB_STOP_BAR, self::TAB_STOP_NUM, - ); + ]; $this->type = $this->setEnumVal($value, $enum, $this->type); return $this; } /** - * Get leader + * Get leader. * * @return string */ @@ -132,26 +133,27 @@ public function getLeader() } /** - * Set leader + * Set leader. * * @param string $value + * * @return self */ public function setLeader($value) { - $enum = array( + $enum = [ self::TAB_LEADER_NONE, self::TAB_LEADER_DOT, self::TAB_LEADER_HYPHEN, self::TAB_LEADER_UNDERSCORE, self::TAB_LEADER_HEAVY, self::TAB_LEADER_MIDDLEDOT, - ); + ]; $this->leader = $this->setEnumVal($value, $enum, $this->leader); return $this; } /** - * Get position + * Get position. * - * @return int|float + * @return float|int */ public function getPosition() { @@ -159,9 +161,10 @@ public function getPosition() } /** - * Set position + * Set position. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setPosition($value) diff --git a/src/PhpWord/Style/Table.php b/src/PhpWord/Style/Table.php index f777ac671f..c2d6406d37 100644 --- a/src/PhpWord/Style/Table.php +++ b/src/PhpWord/Style/Table.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -39,13 +39,13 @@ class Table extends Border //values for http://www.datypic.com/sc/ooxml/t-w_ST_TblLayoutType.html /** - * AutoFit Table Layout + * AutoFit Table Layout. * * @var string */ const LAYOUT_AUTO = 'autofit'; /** - * Fixed Width Table Layout + * Fixed Width Table Layout. * * @var string */ @@ -59,70 +59,70 @@ class Table extends Border private $isFirstRow = false; /** - * Style for first row + * Style for first row. * * @var \PhpOffice\PhpWord\Style\Table */ private $firstRowStyle; /** - * Cell margin top + * Cell margin top. * * @var int */ private $cellMarginTop; /** - * Cell margin left + * Cell margin left. * * @var int */ private $cellMarginLeft; /** - * Cell margin right + * Cell margin right. * * @var int */ private $cellMarginRight; /** - * Cell margin bottom + * Cell margin bottom. * * @var int */ private $cellMarginBottom; /** - * Border size inside horizontal + * Border size inside horizontal. * * @var int */ private $borderInsideHSize; /** - * Border color inside horizontal + * Border color inside horizontal. * * @var string */ private $borderInsideHColor; /** - * Border size inside vertical + * Border size inside vertical. * * @var int */ private $borderInsideVSize; /** - * Border color inside vertical + * Border color inside vertical. * * @var string */ private $borderInsideVColor; /** - * Shading + * Shading. * * @var \PhpOffice\PhpWord\Style\Shading */ @@ -134,7 +134,7 @@ class Table extends Border private $alignment = ''; /** - * @var int|float Width value + * @var float|int Width value */ private $width = 0; @@ -144,9 +144,9 @@ class Table extends Border private $unit = TblWidth::AUTO; /** - * @var int|float cell spacing value + * @var float|int cell spacing value */ - protected $cellSpacing = null; + protected $cellSpacing; /** * @var string Table Layout @@ -154,32 +154,33 @@ class Table extends Border private $layout = self::LAYOUT_AUTO; /** - * Position + * Position. * * @var \PhpOffice\PhpWord\Style\TablePosition */ private $position; - /** @var TblWidthComplexType|null */ + /** @var null|TblWidthComplexType */ private $indent; /** - * The width of each column, computed based on the max cell width of each column + * The width of each column, computed based on the max cell width of each column. * * @var int[] */ private $columnWidths; /** - * Visually Right to Left Table + * Visually Right to Left Table. * * @see http://www.datypic.com/sc/ooxml/e-w_bidiVisual-1.html + * * @var bool */ private $bidiVisual = false; /** - * Create new table style + * Create new table style. * * @param mixed $tableStyle * @param mixed $firstRowStyle @@ -202,7 +203,7 @@ public function __construct($tableStyle = null, $firstRowStyle = null) /** * @param float|int $cellSpacing */ - public function setCellSpacing($cellSpacing = null) + public function setCellSpacing($cellSpacing = null): void { $this->cellSpacing = $cellSpacing; } @@ -216,7 +217,7 @@ public function getCellSpacing() } /** - * Set first row + * Set first row. * * @return \PhpOffice\PhpWord\Style\Table */ @@ -226,7 +227,7 @@ public function getFirstRow() } /** - * Get background + * Get background. * * @return string */ @@ -240,39 +241,41 @@ public function getBgColor() } /** - * Set background + * Set background. * * @param string $value + * * @return self */ public function setBgColor($value = null) { - $this->setShading(array('fill' => $value)); + $this->setShading(['fill' => $value]); return $this; } /** - * Get TLRBHV Border Size + * Get TLRBHV Border Size. * * @return int[] */ public function getBorderSize() { - return array( + return [ $this->getBorderTopSize(), $this->getBorderLeftSize(), $this->getBorderRightSize(), $this->getBorderBottomSize(), $this->getBorderInsideHSize(), $this->getBorderInsideVSize(), - ); + ]; } /** - * Set TLRBHV Border Size + * Set TLRBHV Border Size. * * @param int $value Border size in eighths of a point (1/8 point) + * * @return self */ public function setBorderSize($value = null) @@ -288,26 +291,27 @@ public function setBorderSize($value = null) } /** - * Get TLRBHV Border Color + * Get TLRBHV Border Color. * * @return string[] */ public function getBorderColor() { - return array( + return [ $this->getBorderTopColor(), $this->getBorderLeftColor(), $this->getBorderRightColor(), $this->getBorderBottomColor(), $this->getBorderInsideHColor(), $this->getBorderInsideVColor(), - ); + ]; } /** - * Set TLRBHV Border Color + * Set TLRBHV Border Color. * * @param string $value + * * @return self */ public function setBorderColor($value = null) @@ -323,7 +327,7 @@ public function setBorderColor($value = null) } /** - * Get border size inside horizontal + * Get border size inside horizontal. * * @return int */ @@ -333,9 +337,10 @@ public function getBorderInsideHSize() } /** - * Set border size inside horizontal + * Set border size inside horizontal. * * @param int $value + * * @return self */ public function setBorderInsideHSize($value = null) @@ -344,7 +349,7 @@ public function setBorderInsideHSize($value = null) } /** - * Get border color inside horizontal + * Get border color inside horizontal. * * @return string */ @@ -354,9 +359,10 @@ public function getBorderInsideHColor() } /** - * Set border color inside horizontal + * Set border color inside horizontal. * * @param string $value + * * @return self */ public function setBorderInsideHColor($value = null) @@ -365,7 +371,7 @@ public function setBorderInsideHColor($value = null) } /** - * Get border size inside vertical + * Get border size inside vertical. * * @return int */ @@ -375,9 +381,10 @@ public function getBorderInsideVSize() } /** - * Set border size inside vertical + * Set border size inside vertical. * * @param int $value + * * @return self */ public function setBorderInsideVSize($value = null) @@ -386,7 +393,7 @@ public function setBorderInsideVSize($value = null) } /** - * Get border color inside vertical + * Get border color inside vertical. * * @return string */ @@ -396,9 +403,10 @@ public function getBorderInsideVColor() } /** - * Set border color inside vertical + * Set border color inside vertical. * * @param string $value + * * @return self */ public function setBorderInsideVColor($value = null) @@ -407,7 +415,7 @@ public function setBorderInsideVColor($value = null) } /** - * Get cell margin top + * Get cell margin top. * * @return int */ @@ -417,9 +425,10 @@ public function getCellMarginTop() } /** - * Set cell margin top + * Set cell margin top. * * @param int $value + * * @return self */ public function setCellMarginTop($value = null) @@ -428,7 +437,7 @@ public function setCellMarginTop($value = null) } /** - * Get cell margin left + * Get cell margin left. * * @return int */ @@ -438,9 +447,10 @@ public function getCellMarginLeft() } /** - * Set cell margin left + * Set cell margin left. * * @param int $value + * * @return self */ public function setCellMarginLeft($value = null) @@ -449,7 +459,7 @@ public function setCellMarginLeft($value = null) } /** - * Get cell margin right + * Get cell margin right. * * @return int */ @@ -459,9 +469,10 @@ public function getCellMarginRight() } /** - * Set cell margin right + * Set cell margin right. * * @param int $value + * * @return self */ public function setCellMarginRight($value = null) @@ -470,7 +481,7 @@ public function setCellMarginRight($value = null) } /** - * Get cell margin bottom + * Get cell margin bottom. * * @return int */ @@ -480,9 +491,10 @@ public function getCellMarginBottom() } /** - * Set cell margin bottom + * Set cell margin bottom. * * @param int $value + * * @return self */ public function setCellMarginBottom($value = null) @@ -491,24 +503,25 @@ public function setCellMarginBottom($value = null) } /** - * Get cell margin + * Get cell margin. * * @return int[] */ public function getCellMargin() { - return array( + return [ $this->cellMarginTop, $this->cellMarginLeft, $this->cellMarginRight, $this->cellMarginBottom, - ); + ]; } /** - * Set TLRB cell margin + * Set TLRB cell margin. * * @param int $value Margin in twips + * * @return self */ public function setCellMargin($value = null) @@ -522,7 +535,7 @@ public function setCellMargin($value = null) } /** - * Check if any of the margin is not null + * Check if any of the margin is not null. * * @return bool */ @@ -534,7 +547,7 @@ public function hasMargin() } /** - * Get shading + * Get shading. * * @return \PhpOffice\PhpWord\Style\Shading */ @@ -544,9 +557,10 @@ public function getShading() } /** - * Set shading + * Set shading. * * @param mixed $value + * * @return self */ public function setShading($value = null) @@ -609,9 +623,9 @@ public function setAlign($value = null) } /** - * Get width + * Get width. * - * @return int|float + * @return float|int */ public function getWidth() { @@ -619,9 +633,10 @@ public function getWidth() } /** - * Set width + * Set width. + * + * @param float|int $value * - * @param int|float $value * @return self */ public function setWidth($value = null) @@ -632,7 +647,7 @@ public function setWidth($value = null) } /** - * Get width unit + * Get width unit. * * @return string */ @@ -642,9 +657,10 @@ public function getUnit() } /** - * Set width unit + * Set width unit. * * @param string $value + * * @return self */ public function setUnit($value = null) @@ -656,7 +672,7 @@ public function setUnit($value = null) } /** - * Get layout + * Get layout. * * @return string */ @@ -666,27 +682,29 @@ public function getLayout() } /** - * Set layout + * Set layout. * * @param string $value + * * @return self */ public function setLayout($value = null) { - $enum = array(self::LAYOUT_AUTO, self::LAYOUT_FIXED); + $enum = [self::LAYOUT_AUTO, self::LAYOUT_FIXED]; $this->layout = $this->setEnumVal($value, $enum, $this->layout); return $this; } /** - * Get table style only property by checking if it's a firstRow + * Get table style only property by checking if it's a firstRow. * * This is necessary since firstRow style is cloned from table style but * without certain properties activated, e.g. margins * * @param string $property - * @return int|string|null + * + * @return null|int|string */ private function getTableOnlyProperty($property) { @@ -698,7 +716,7 @@ private function getTableOnlyProperty($property) } /** - * Set table style only property by checking if it's a firstRow + * Set table style only property by checking if it's a firstRow. * * This is necessary since firstRow style is cloned from table style but * without certain properties activated, e.g. margins @@ -706,6 +724,7 @@ private function getTableOnlyProperty($property) * @param string $property * @param int|string $value * @param bool $isNumeric + * * @return self */ private function setTableOnlyProperty($property, $value, $isNumeric = true) @@ -722,7 +741,7 @@ private function setTableOnlyProperty($property, $value, $isNumeric = true) } /** - * Get position + * Get position. * * @return \PhpOffice\PhpWord\Style\TablePosition */ @@ -732,9 +751,10 @@ public function getPosition() } /** - * Set position + * Set position. * * @param mixed $value + * * @return self */ public function setPosition($value = null) @@ -753,8 +773,8 @@ public function getIndent() } /** - * @param TblWidthComplexType $indent * @return self + * * @see http://www.datypic.com/sc/ooxml/e-w_tblInd-1.html */ public function setIndent(TblWidthComplexType $indent) @@ -765,7 +785,7 @@ public function setIndent(TblWidthComplexType $indent) } /** - * Get the columnWidths + * Get the columnWidths. * * @return null|int[] */ @@ -775,17 +795,17 @@ public function getColumnWidths() } /** - * The column widths + * The column widths. * * @param int[] $value */ - public function setColumnWidths(array $value = null) + public function setColumnWidths(?array $value = null): void { $this->columnWidths = $value; } /** - * Get bidiVisual + * Get bidiVisual. * * @return bool */ @@ -795,10 +815,11 @@ public function isBidiVisual() } /** - * Set bidiVisual + * Set bidiVisual. * * @param bool $bidi * Set to true to visually present table as Right to Left + * * @return self */ public function setBidiVisual($bidi) diff --git a/src/PhpWord/Style/TablePosition.php b/src/PhpWord/Style/TablePosition.php index d4b7083102..a61926b83c 100644 --- a/src/PhpWord/Style/TablePosition.php +++ b/src/PhpWord/Style/TablePosition.php @@ -11,23 +11,24 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * TablePosition style + * TablePosition style. * * @see http://www.datypic.com/sc/ooxml/e-w_tblpPr-1.html */ class TablePosition extends AbstractStyle { /** - * Vertical anchor constants + * Vertical anchor constants. * * @const string + * * @see http://www.datypic.com/sc/ooxml/t-w_ST_VAnchor.html */ const VANCHOR_TEXT = 'text'; // Relative to vertical text extents @@ -35,9 +36,10 @@ class TablePosition extends AbstractStyle const VANCHOR_PAGE = 'page'; // Relative to page /** - * Horizontal anchor constants + * Horizontal anchor constants. * * @const string + * * @see http://www.datypic.com/sc/ooxml/t-w_ST_HAnchor.html */ const HANCHOR_TEXT = 'text'; // Relative to text extents @@ -45,9 +47,10 @@ class TablePosition extends AbstractStyle const HANCHOR_PAGE = 'page'; // Relative to page /** - * Horizontal alignment constants + * Horizontal alignment constants. * * @const string + * * @see http://www.datypic.com/sc/ooxml/t-w_ST_XAlign.html */ const XALIGN_LEFT = 'left'; // Left aligned horizontally @@ -57,9 +60,10 @@ class TablePosition extends AbstractStyle const XALIGN_OUTSIDE = 'outside'; // Outside /** - * Vertical alignment constants + * Vertical alignment constants. * * @const string + * * @see http://www.datypic.com/sc/ooxml/t-w_ST_YAlign.html */ const YALIGN_INLINE = 'inline'; // In line with text @@ -70,91 +74,95 @@ class TablePosition extends AbstractStyle const YALIGN_OUTSIDE = 'outside'; // Centered vertically /** - * Distance from left of table to text + * Distance from left of table to text. * * @var int */ private $leftFromText; /** - * Distance from right of table to text + * Distance from right of table to text. * * @var int */ private $rightFromText; /** - * Distance from top of table to text + * Distance from top of table to text. * * @var int */ private $topFromText; /** - * Distance from bottom of table to text + * Distance from bottom of table to text. * * @var int */ private $bottomFromText; /** - * Table vertical anchor + * Table vertical anchor. * * @var string + * * @see http://www.datypic.com/sc/ooxml/t-w_ST_VAnchor.html */ private $vertAnchor; /** - * Table horizontal anchor + * Table horizontal anchor. * * @var string + * * @see http://www.datypic.com/sc/ooxml/t-w_ST_HAnchor.html */ private $horzAnchor; /** - * Relative horizontal alignment from anchor + * Relative horizontal alignment from anchor. * * @var string + * * @see http://www.datypic.com/sc/ooxml/t-w_ST_XAlign.html */ private $tblpXSpec; /** - * Absolute horizontal distance from anchor + * Absolute horizontal distance from anchor. * * @var int */ private $tblpX; /** - * Relative vertical alignment from anchor + * Relative vertical alignment from anchor. * * @var string + * * @see http://www.datypic.com/sc/ooxml/t-w_ST_YAlign.html */ private $tblpYSpec; /** - * Absolute vertical distance from anchor + * Absolute vertical distance from anchor. * * @var int */ private $tblpY; /** - * Create a new instance + * Create a new instance. * * @param array $style */ - public function __construct($style = array()) + public function __construct($style = []) { $this->setStyleByArray($style); } /** - * Get distance from left of table to text + * Get distance from left of table to text. * * @return int */ @@ -164,9 +172,10 @@ public function getLeftFromText() } /** - * Set distance from left of table to text + * Set distance from left of table to text. * * @param int $value + * * @return self */ public function setLeftFromText($value = null) @@ -177,7 +186,7 @@ public function setLeftFromText($value = null) } /** - * Get distance from right of table to text + * Get distance from right of table to text. * * @return int */ @@ -187,9 +196,10 @@ public function getRightFromText() } /** - * Set distance from right of table to text + * Set distance from right of table to text. * * @param int $value + * * @return self */ public function setRightFromText($value = null) @@ -200,7 +210,7 @@ public function setRightFromText($value = null) } /** - * Get distance from top of table to text + * Get distance from top of table to text. * * @return int */ @@ -210,9 +220,10 @@ public function getTopFromText() } /** - * Set distance from top of table to text + * Set distance from top of table to text. * * @param int $value + * * @return self */ public function setTopFromText($value = null) @@ -223,7 +234,7 @@ public function setTopFromText($value = null) } /** - * Get distance from bottom of table to text + * Get distance from bottom of table to text. * * @return int */ @@ -233,9 +244,10 @@ public function getBottomFromText() } /** - * Set distance from bottom of table to text + * Set distance from bottom of table to text. * * @param int $value + * * @return self */ public function setBottomFromText($value = null) @@ -246,7 +258,7 @@ public function setBottomFromText($value = null) } /** - * Get table vertical anchor + * Get table vertical anchor. * * @return string */ @@ -256,25 +268,26 @@ public function getVertAnchor() } /** - * Set table vertical anchor + * Set table vertical anchor. * * @param string $value + * * @return self */ public function setVertAnchor($value = null) { - $enum = array( - self::VANCHOR_TEXT, - self::VANCHOR_MARGIN, - self::VANCHOR_PAGE, - ); + $enum = [ + self::VANCHOR_TEXT, + self::VANCHOR_MARGIN, + self::VANCHOR_PAGE, + ]; $this->vertAnchor = $this->setEnumVal($value, $enum, $this->vertAnchor); return $this; } /** - * Get table horizontal anchor + * Get table horizontal anchor. * * @return string */ @@ -284,25 +297,26 @@ public function getHorzAnchor() } /** - * Set table horizontal anchor + * Set table horizontal anchor. * * @param string $value + * * @return self */ public function setHorzAnchor($value = null) { - $enum = array( - self::HANCHOR_TEXT, - self::HANCHOR_MARGIN, - self::HANCHOR_PAGE, - ); + $enum = [ + self::HANCHOR_TEXT, + self::HANCHOR_MARGIN, + self::HANCHOR_PAGE, + ]; $this->horzAnchor = $this->setEnumVal($value, $enum, $this->horzAnchor); return $this; } /** - * Get relative horizontal alignment from anchor + * Get relative horizontal alignment from anchor. * * @return string */ @@ -312,27 +326,28 @@ public function getTblpXSpec() } /** - * Set relative horizontal alignment from anchor + * Set relative horizontal alignment from anchor. * * @param string $value + * * @return self */ public function setTblpXSpec($value = null) { - $enum = array( + $enum = [ self::XALIGN_LEFT, self::XALIGN_CENTER, self::XALIGN_RIGHT, self::XALIGN_INSIDE, self::XALIGN_OUTSIDE, - ); + ]; $this->tblpXSpec = $this->setEnumVal($value, $enum, $this->tblpXSpec); return $this; } /** - * Get absolute horizontal distance from anchor + * Get absolute horizontal distance from anchor. * * @return int */ @@ -342,9 +357,10 @@ public function getTblpX() } /** - * Set absolute horizontal distance from anchor + * Set absolute horizontal distance from anchor. * * @param int $value + * * @return self */ public function setTblpX($value = null) @@ -355,7 +371,7 @@ public function setTblpX($value = null) } /** - * Get relative vertical alignment from anchor + * Get relative vertical alignment from anchor. * * @return string */ @@ -365,28 +381,29 @@ public function getTblpYSpec() } /** - * Set relative vertical alignment from anchor + * Set relative vertical alignment from anchor. * * @param string $value + * * @return self */ public function setTblpYSpec($value = null) { - $enum = array( + $enum = [ self::YALIGN_INLINE, self::YALIGN_TOP, self::YALIGN_CENTER, self::YALIGN_BOTTOM, self::YALIGN_INSIDE, self::YALIGN_OUTSIDE, - ); + ]; $this->tblpYSpec = $this->setEnumVal($value, $enum, $this->tblpYSpec); return $this; } /** - * Get absolute vertical distance from anchor + * Get absolute vertical distance from anchor. * * @return int */ @@ -396,9 +413,10 @@ public function getTblpY() } /** - * Set absolute vertical distance from anchor + * Set absolute vertical distance from anchor. * * @param int $value + * * @return self */ public function setTblpY($value = null) diff --git a/src/PhpWord/Style/TextBox.php b/src/PhpWord/Style/TextBox.php index e9c0f0c064..e43e6fa231 100644 --- a/src/PhpWord/Style/TextBox.php +++ b/src/PhpWord/Style/TextBox.php @@ -11,56 +11,56 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Style; /** - * TextBox style + * TextBox style. * * @since 0.11.0 */ class TextBox extends Image { /** - * margin top + * margin top. * * @var int */ - private $innerMarginTop = null; + private $innerMarginTop; /** - * margin left + * margin left. * * @var int */ - private $innerMarginLeft = null; + private $innerMarginLeft; /** - * margin right + * margin right. * * @var int */ - private $innerMarginRight = null; + private $innerMarginRight; /** - * Cell margin bottom + * Cell margin bottom. * * @var int */ - private $innerMarginBottom = null; + private $innerMarginBottom; /** - * border size + * border size. * * @var int */ - private $borderSize = null; + private $borderSize; /** - * border color + * border color. * * @var string */ @@ -71,13 +71,13 @@ class TextBox extends Image * * @param int $value */ - public function setInnerMarginTop($value = null) + public function setInnerMarginTop($value = null): void { $this->innerMarginTop = $value; } /** - * Get margin top + * Get margin top. * * @return int */ @@ -91,13 +91,13 @@ public function getInnerMarginTop() * * @param int $value */ - public function setInnerMarginLeft($value = null) + public function setInnerMarginLeft($value = null): void { $this->innerMarginLeft = $value; } /** - * Get margin left + * Get margin left. * * @return int */ @@ -111,13 +111,13 @@ public function getInnerMarginLeft() * * @param int $value */ - public function setInnerMarginRight($value = null) + public function setInnerMarginRight($value = null): void { $this->innerMarginRight = $value; } /** - * Get margin right + * Get margin right. * * @return int */ @@ -131,13 +131,13 @@ public function getInnerMarginRight() * * @param int $value */ - public function setInnerMarginBottom($value = null) + public function setInnerMarginBottom($value = null): void { $this->innerMarginBottom = $value; } /** - * Get margin bottom + * Get margin bottom. * * @return int */ @@ -151,7 +151,7 @@ public function getInnerMarginBottom() * * @param int $value Margin in twips */ - public function setInnerMargin($value = null) + public function setInnerMargin($value = null): void { $this->setInnerMarginTop($value); $this->setInnerMarginLeft($value); @@ -160,13 +160,13 @@ public function setInnerMargin($value = null) } /** - * Get cell margin + * Get cell margin. * * @return int[] */ public function getInnerMargin() { - return array($this->innerMarginLeft, $this->innerMarginTop, $this->innerMarginRight, $this->innerMarginBottom); + return [$this->innerMarginLeft, $this->innerMarginTop, $this->innerMarginRight, $this->innerMarginBottom]; } /** @@ -179,7 +179,7 @@ public function hasInnerMargins() $hasInnerMargins = false; $margins = $this->getInnerMargin(); $numMargins = count($margins); - for ($i = 0; $i < $numMargins; $i++) { + for ($i = 0; $i < $numMargins; ++$i) { if ($margins[$i] !== null) { $hasInnerMargins = true; } @@ -193,13 +193,13 @@ public function hasInnerMargins() * * @param int $value Size in points */ - public function setBorderSize($value = null) + public function setBorderSize($value = null): void { $this->borderSize = $value; } /** - * Get border size + * Get border size. * * @return int */ @@ -213,13 +213,13 @@ public function getBorderSize() * * @param string $value */ - public function setBorderColor($value = null) + public function setBorderColor($value = null): void { $this->borderColor = $value; } /** - * Get border color + * Get border color. * * @return string */ diff --git a/src/PhpWord/Template.php b/src/PhpWord/Template.php index c42696f08c..e0e09450a8 100644 --- a/src/PhpWord/Template.php +++ b/src/PhpWord/Template.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 09f5461995..1cf3242984 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -12,12 +12,13 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord; +use DOMDocument; use PhpOffice\PhpWord\Escaper\RegExp; use PhpOffice\PhpWord\Escaper\Xml; use PhpOffice\PhpWord\Exception\CopyFileException; @@ -26,6 +27,7 @@ use PhpOffice\PhpWord\Shared\Text; use PhpOffice\PhpWord\Shared\XMLWriter; use PhpOffice\PhpWord\Shared\ZipArchive; +use XSLTProcessor; class TemplateProcessor { @@ -44,39 +46,39 @@ class TemplateProcessor protected $tempDocumentFilename; /** - * Content of main document part (in XML format) of the temporary document + * Content of main document part (in XML format) of the temporary document. * * @var string */ protected $tempDocumentMainPart; /** - * Content of settings part (in XML format) of the temporary document + * Content of settings part (in XML format) of the temporary document. * * @var string */ protected $tempDocumentSettingsPart; /** - * Content of headers (in XML format) of the temporary document + * Content of headers (in XML format) of the temporary document. * * @var string[] */ - protected $tempDocumentHeaders = array(); + protected $tempDocumentHeaders = []; /** - * Content of footers (in XML format) of the temporary document + * Content of footers (in XML format) of the temporary document. * * @var string[] */ - protected $tempDocumentFooters = array(); + protected $tempDocumentFooters = []; /** * Document relations (in XML format) of the temporary document. * * @var string[] */ - protected $tempDocumentRelations = array(); + protected $tempDocumentRelations = []; /** * Document content types (in XML format) of the temporary document. @@ -86,19 +88,16 @@ class TemplateProcessor protected $tempDocumentContentTypes = ''; /** - * new inserted images list + * new inserted images list. * * @var string[] */ - protected $tempDocumentNewImages = array(); + protected $tempDocumentNewImages = []; /** * @since 0.12.0 Throws CreateTemporaryFileException and CopyFileException instead of Exception * * @param string $documentTemplate The fully qualified template filename - * - * @throws \PhpOffice\PhpWord\Exception\CreateTemporaryFileException - * @throws \PhpOffice\PhpWord\Exception\CopyFileException */ public function __construct($documentTemplate) { @@ -119,12 +118,12 @@ public function __construct($documentTemplate) $index = 1; while (false !== $this->zipClass->locateName($this->getHeaderName($index))) { $this->tempDocumentHeaders[$index] = $this->readPartWithRels($this->getHeaderName($index)); - $index++; + ++$index; } $index = 1; while (false !== $this->zipClass->locateName($this->getFooterName($index))) { $this->tempDocumentFooters[$index] = $this->readPartWithRels($this->getFooterName($index)); - $index++; + ++$index; } $this->tempDocumentMainPart = $this->readPartWithRels($this->getMainPartName()); @@ -133,7 +132,7 @@ public function __construct($documentTemplate) } /** - * Expose zip class + * Expose zip class. * * To replace an image: $templateProcessor->zip()->AddFromString("word/media/image1.jpg", file_get_contents($file));
    * To read a file: $templateProcessor->zip()->getFromName("word/media/image1.jpg"); @@ -163,9 +162,7 @@ protected function readPartWithRels($fileName) /** * @param string $xml - * @param \XSLTProcessor $xsltProcessor - * - * @throws \PhpOffice\PhpWord\Exception\Exception + * @param XSLTProcessor $xsltProcessor * * @return string */ @@ -174,7 +171,7 @@ protected function transformSingleXml($xml, $xsltProcessor) if (\PHP_VERSION_ID < 80000) { $orignalLibEntityLoader = libxml_disable_entity_loader(true); } - $domDocument = new \DOMDocument(); + $domDocument = new DOMDocument(); if (false === $domDocument->loadXML($xml)) { throw new Exception('Could not load the given XML document.'); } @@ -192,7 +189,7 @@ protected function transformSingleXml($xml, $xsltProcessor) /** * @param mixed $xml - * @param \XSLTProcessor $xsltProcessor + * @param XSLTProcessor $xsltProcessor * * @return mixed */ @@ -216,15 +213,13 @@ protected function transformXml($xml, $xsltProcessor) * Note: since the method doesn't make any guess on logic of the provided XSL style sheet, * make sure that output is correctly escaped. Otherwise you may get broken document. * - * @param \DOMDocument $xslDomDocument + * @param DOMDocument $xslDomDocument * @param array $xslOptions * @param string $xslOptionsUri - * - * @throws \PhpOffice\PhpWord\Exception\Exception */ - public function applyXslStyleSheet($xslDomDocument, $xslOptions = array(), $xslOptionsUri = '') + public function applyXslStyleSheet($xslDomDocument, $xslOptions = [], $xslOptionsUri = ''): void { - $xsltProcessor = new \XSLTProcessor(); + $xsltProcessor = new XSLTProcessor(); $xsltProcessor->importStylesheet($xslDomDocument); if (false === $xsltProcessor->setParameter($xslOptionsUri, $xslOptions)) { @@ -257,18 +252,18 @@ protected static function ensureMacroCompleted($macro) */ protected static function ensureUtf8Encoded($subject) { - if (!Text::isUTF8($subject) && !is_null($subject)) { + if (!Text::isUTF8($subject) && null !== $subject) { $subject = utf8_encode($subject); } - return (!is_null($subject)) ? $subject : ''; + return (null !== $subject) ? $subject : ''; } /** * @param string $search * @param \PhpOffice\PhpWord\Element\AbstractElement $complexType */ - public function setComplexValue($search, \PhpOffice\PhpWord\Element\AbstractElement $complexType) + public function setComplexValue($search, Element\AbstractElement $complexType): void { $elementName = substr(get_class($complexType), strrpos(get_class($complexType), '\\') + 1); $objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $elementName; @@ -296,7 +291,7 @@ public function setComplexValue($search, \PhpOffice\PhpWord\Element\AbstractElem * @param string $search * @param \PhpOffice\PhpWord\Element\AbstractElement $complexType */ - public function setComplexBlock($search, \PhpOffice\PhpWord\Element\AbstractElement $complexType) + public function setComplexBlock($search, Element\AbstractElement $complexType): void { $elementName = substr(get_class($complexType), strrpos(get_class($complexType), '\\') + 1); $objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $elementName; @@ -314,7 +309,7 @@ public function setComplexBlock($search, \PhpOffice\PhpWord\Element\AbstractElem * @param mixed $replace * @param int $limit */ - public function setValue($search, $replace, $limit = self::MAXIMUM_REPLACEMENTS_DEFAULT) + public function setValue($search, $replace, $limit = self::MAXIMUM_REPLACEMENTS_DEFAULT): void { if (is_array($search)) { foreach ($search as &$item) { @@ -346,10 +341,8 @@ public function setValue($search, $replace, $limit = self::MAXIMUM_REPLACEMENTS_ /** * Set values from a one-dimensional array of "variable => value"-pairs. - * - * @param array $values */ - public function setValues(array $values) + public function setValues(array $values): void { foreach ($values as $macro => $replace) { $this->setValue($macro, $replace); @@ -358,9 +351,8 @@ public function setValues(array $values) /** * @param string $search - * @param \PhpOffice\PhpWord\Element\AbstractElement $complexType */ - public function setChart($search, \PhpOffice\PhpWord\Element\AbstractElement $chart) + public function setChart($search, Element\AbstractElement $chart): void { $elementName = substr(get_class($chart), strrpos(get_class($chart), '\\') + 1); $objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $elementName; @@ -401,29 +393,32 @@ private function getImageArgs($varNameWithArgs) $varElements = explode(':', $varNameWithArgs); array_shift($varElements); // first element is name of variable => remove it - $varInlineArgs = array(); + $varInlineArgs = []; // size format documentation: https://msdn.microsoft.com/en-us/library/documentformat.openxml.vml.shape%28v=office.14%29.aspx?f=255&MSPPError=-2147217396 foreach ($varElements as $argIdx => $varArg) { if (strpos($varArg, '=')) { // arg=value - list($argName, $argValue) = explode('=', $varArg, 2); + [$argName, $argValue] = explode('=', $varArg, 2); $argName = strtolower($argName); if ($argName == 'size') { - list($varInlineArgs['width'], $varInlineArgs['height']) = explode('x', $argValue, 2); + [$varInlineArgs['width'], $varInlineArgs['height']] = explode('x', $argValue, 2); } else { $varInlineArgs[strtolower($argName)] = $argValue; } } elseif (preg_match('/^([0-9]*[a-z%]{0,2}|auto)x([0-9]*[a-z%]{0,2}|auto)$/i', $varArg)) { // 60x40 - list($varInlineArgs['width'], $varInlineArgs['height']) = explode('x', $varArg, 2); + [$varInlineArgs['width'], $varInlineArgs['height']] = explode('x', $varArg, 2); } else { // :60:40:f switch ($argIdx) { case 0: $varInlineArgs['width'] = $varArg; + break; case 1: $varInlineArgs['height'] = $varArg; + break; case 2: $varInlineArgs['ratio'] = $varArg; + break; } } @@ -435,13 +430,13 @@ private function getImageArgs($varNameWithArgs) private function chooseImageDimension($baseValue, $inlineValue, $defaultValue) { $value = $baseValue; - if (is_null($value) && isset($inlineValue)) { + if (null === $value && isset($inlineValue)) { $value = $inlineValue; } - if (!preg_match('/^([0-9]*(cm|mm|in|pt|pc|px|%|em|ex|)|auto)$/i', isset($value) ? $value : '')) { + if (!preg_match('/^([0-9]*(cm|mm|in|pt|pc|px|%|em|ex|)|auto)$/i', $value ?? '')) { $value = null; } - if (is_null($value)) { + if (null === $value) { $value = $defaultValue; } if (is_numeric($value)) { @@ -451,7 +446,7 @@ private function chooseImageDimension($baseValue, $inlineValue, $defaultValue) return $value; } - private function fixImageWidthHeightRatio(&$width, &$height, $actualWidth, $actualHeight) + private function fixImageWidthHeightRatio(&$width, &$height, $actualWidth, $actualHeight): void { $imageRatio = $actualWidth / $actualHeight; @@ -461,20 +456,20 @@ private function fixImageWidthHeightRatio(&$width, &$height, $actualWidth, $actu } elseif ($width === '') { // defined width is empty $heightFloat = (float) $height; $widthFloat = $heightFloat * $imageRatio; - $matches = array(); - preg_match("/\d([a-z%]+)$/", $height, $matches); + $matches = []; + preg_match('/\\d([a-z%]+)$/', $height, $matches); $width = $widthFloat . $matches[1]; } elseif ($height === '') { // defined height is empty $widthFloat = (float) $width; $heightFloat = $widthFloat / $imageRatio; - $matches = array(); - preg_match("/\d([a-z%]+)$/", $width, $matches); + $matches = []; + preg_match('/\\d([a-z%]+)$/', $width, $matches); $height = $heightFloat . $matches[1]; } else { // we have defined size, but we need also check it aspect ratio - $widthMatches = array(); - preg_match("/\d([a-z%]+)$/", $width, $widthMatches); - $heightMatches = array(); - preg_match("/\d([a-z%]+)$/", $height, $heightMatches); + $widthMatches = []; + preg_match('/\\d([a-z%]+)$/', $width, $widthMatches); + $heightMatches = []; + preg_match('/\\d([a-z%]+)$/', $height, $heightMatches); // try to fix only if dimensions are same if ($widthMatches[1] == $heightMatches[1]) { $dimention = $widthMatches[1]; @@ -519,46 +514,46 @@ private function prepareImageAttrs($replaceImage, $varInlineArgs) $imgPath = $replaceImage; } - $width = $this->chooseImageDimension($width, isset($varInlineArgs['width']) ? $varInlineArgs['width'] : null, 115); - $height = $this->chooseImageDimension($height, isset($varInlineArgs['height']) ? $varInlineArgs['height'] : null, 70); + $width = $this->chooseImageDimension($width, $varInlineArgs['width'] ?? null, 115); + $height = $this->chooseImageDimension($height, $varInlineArgs['height'] ?? null, 70); $imageData = @getimagesize($imgPath); if (!is_array($imageData)) { throw new Exception(sprintf('Invalid image: %s', $imgPath)); } - list($actualWidth, $actualHeight, $imageType) = $imageData; + [$actualWidth, $actualHeight, $imageType] = $imageData; // fix aspect ratio (by default) - if (is_null($ratio) && isset($varInlineArgs['ratio'])) { + if (null === $ratio && isset($varInlineArgs['ratio'])) { $ratio = $varInlineArgs['ratio']; } - if (is_null($ratio) || !in_array(strtolower($ratio), array('', '-', 'f', 'false'))) { + if (null === $ratio || !in_array(strtolower($ratio), ['', '-', 'f', 'false'])) { $this->fixImageWidthHeightRatio($width, $height, $actualWidth, $actualHeight); } - $imageAttrs = array( - 'src' => $imgPath, - 'mime' => image_type_to_mime_type($imageType), - 'width' => $width, + $imageAttrs = [ + 'src' => $imgPath, + 'mime' => image_type_to_mime_type($imageType), + 'width' => $width, 'height' => $height, - ); + ]; return $imageAttrs; } - private function addImageToRelations($partFileName, $rid, $imgPath, $imageMimeType) + private function addImageToRelations($partFileName, $rid, $imgPath, $imageMimeType): void { // define templates $typeTpl = ''; $relationTpl = ''; $newRelationsTpl = '' . "\n" . ''; $newRelationsTypeTpl = ''; - $extTransform = array( + $extTransform = [ 'image/jpeg' => 'jpeg', - 'image/png' => 'png', - 'image/bmp' => 'bmp', - 'image/gif' => 'gif', - ); + 'image/png' => 'png', + 'image/bmp' => 'bmp', + 'image/gif' => 'gif', + ]; // get image embed name if (isset($this->tempDocumentNewImages[$imgPath])) { @@ -577,11 +572,11 @@ private function addImageToRelations($partFileName, $rid, $imgPath, $imageMimeTy $this->tempDocumentNewImages[$imgPath] = $imgName; // setup type for image - $xmlImageType = str_replace(array('{IMG}', '{EXT}'), array($imgName, $imgExt), $typeTpl); + $xmlImageType = str_replace(['{IMG}', '{EXT}'], [$imgName, $imgExt], $typeTpl); $this->tempDocumentContentTypes = str_replace('', $xmlImageType, $this->tempDocumentContentTypes) . ''; } - $xmlImageRelation = str_replace(array('{RID}', '{IMG}'), array($rid, $imgName), $relationTpl); + $xmlImageRelation = str_replace(['{RID}', '{IMG}'], [$rid, $imgName], $relationTpl); if (!isset($this->tempDocumentRelations[$partFileName])) { // create new relations file @@ -600,29 +595,29 @@ private function addImageToRelations($partFileName, $rid, $imgPath, $imageMimeTy * @param mixed $replace Path to image, or array("path" => xx, "width" => yy, "height" => zz) * @param int $limit */ - public function setImageValue($search, $replace, $limit = self::MAXIMUM_REPLACEMENTS_DEFAULT) + public function setImageValue($search, $replace, $limit = self::MAXIMUM_REPLACEMENTS_DEFAULT): void { // prepare $search_replace if (!is_array($search)) { - $search = array($search); + $search = [$search]; } - $replacesList = array(); + $replacesList = []; if (!is_array($replace) || isset($replace['path'])) { $replacesList[] = $replace; } else { $replacesList = array_values($replace); } - $searchReplace = array(); + $searchReplace = []; foreach ($search as $searchIdx => $searchString) { - $searchReplace[$searchString] = isset($replacesList[$searchIdx]) ? $replacesList[$searchIdx] : $replacesList[0]; + $searchReplace[$searchString] = $replacesList[$searchIdx] ?? $replacesList[0]; } // collect document parts - $searchParts = array( + $searchParts = [ $this->getMainPartName() => &$this->tempDocumentMainPart, - ); + ]; foreach (array_keys($this->tempDocumentHeaders) as $headerIndex) { $searchParts[$this->getHeaderName($headerIndex)] = &$this->tempDocumentHeaders[$headerIndex]; } @@ -654,15 +649,15 @@ public function setImageValue($search, $replace, $limit = self::MAXIMUM_REPLACEM // replace preparations $this->addImageToRelations($partFileName, $rid, $imgPath, $preparedImageAttrs['mime']); - $xmlImage = str_replace(array('{RID}', '{WIDTH}', '{HEIGHT}'), array($rid, $preparedImageAttrs['width'], $preparedImageAttrs['height']), $imgTpl); + $xmlImage = str_replace(['{RID}', '{WIDTH}', '{HEIGHT}'], [$rid, $preparedImageAttrs['width'], $preparedImageAttrs['height']], $imgTpl); // replace variable $varNameWithArgsFixed = static::ensureMacroCompleted($varNameWithArgs); - $matches = array(); + $matches = []; if (preg_match('/(<[^<]+>)([^<]*)(' . preg_quote($varNameWithArgsFixed) . ')([^>]*)(<[^>]+>)/Uu', $partContent, $matches)) { $wholeTag = $matches[0]; array_shift($matches); - list($openTag, $prefix, , $postfix, $closeTag) = $matches; + [$openTag, $prefix, , $postfix, $closeTag] = $matches; $replaceXml = $openTag . $prefix . $closeTag . $xmlImage . $openTag . $postfix . $closeTag; // replace on each iteration, because in one tag we can have 2+ inline variables => before proceed next variable we need to change $partContent $partContent = $this->setValueForPart($wholeTag, $replaceXml, $partContent, $limit); @@ -717,10 +712,8 @@ public function getVariables() * * @param string $search * @param int $numberOfClones - * - * @throws \PhpOffice\PhpWord\Exception\Exception */ - public function cloneRow($search, $numberOfClones) + public function cloneRow($search, $numberOfClones): void { $search = static::ensureMacroCompleted($search); @@ -760,7 +753,7 @@ public function cloneRow($search, $numberOfClones) } $result = $this->getSlice(0, $rowStart); - $result .= implode($this->indexClonedVariables($numberOfClones, $xmlRow)); + $result .= implode('', $this->indexClonedVariables($numberOfClones, $xmlRow)); $result .= $this->getSlice($rowEnd); $this->tempDocumentMainPart = $result; @@ -772,7 +765,7 @@ public function cloneRow($search, $numberOfClones) * @param string $search * @param array $values */ - public function cloneRowAndSetValues($search, $values) + public function cloneRowAndSetValues($search, $values): void { $this->cloneRow($search, count($values)); @@ -793,12 +786,12 @@ public function cloneRowAndSetValues($search, $values) * @param bool $indexVariables If true, any variables inside the block will be indexed (postfixed with #1, #2, ...) * @param array $variableReplacements Array containing replacements for macros found inside the block to clone * - * @return string|null + * @return null|string */ public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVariables = false, $variableReplacements = null) { $xmlBlock = null; - $matches = array(); + $matches = []; preg_match( '/(.*((?s)))(.*)((?s))/is', $this->tempDocumentMainPart, @@ -812,8 +805,8 @@ public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVaria } elseif ($variableReplacements !== null && is_array($variableReplacements)) { $cloned = $this->replaceClonedVariables($variableReplacements, $xmlBlock); } else { - $cloned = array(); - for ($i = 1; $i <= $clones; $i++) { + $cloned = []; + for ($i = 1; $i <= $clones; ++$i) { $cloned[] = $xmlBlock; } } @@ -836,9 +829,9 @@ public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVaria * @param string $blockname * @param string $replacement */ - public function replaceBlock($blockname, $replacement) + public function replaceBlock($blockname, $replacement): void { - $matches = array(); + $matches = []; preg_match( '/(<\?xml.*)(\${' . $blockname . '}<\/w:.*?p>)(.*)()/is', $this->tempDocumentMainPart, @@ -859,20 +852,20 @@ public function replaceBlock($blockname, $replacement) * * @param string $blockname */ - public function deleteBlock($blockname) + public function deleteBlock($blockname): void { $this->replaceBlock($blockname, ''); } /** - * Automatically Recalculate Fields on Open + * Automatically Recalculate Fields on Open. * * @param bool $update */ - public function setUpdateFields($update = true) + public function setUpdateFields($update = true): void { $string = $update ? 'true' : 'false'; - $matches = array(); + $matches = []; if (preg_match('//', $this->tempDocumentSettingsPart, $matches)) { $this->tempDocumentSettingsPart = str_replace($matches[0], '', $this->tempDocumentSettingsPart); } else { @@ -883,8 +876,6 @@ public function setUpdateFields($update = true) /** * Saves the result document. * - * @throws \PhpOffice\PhpWord\Exception\Exception - * * @return string */ public function save() @@ -914,7 +905,7 @@ public function save() * @param string $fileName * @param string $xml */ - protected function savePartWithRels($fileName, $xml) + protected function savePartWithRels($fileName, $xml): void { $this->zipClass->addFromString($fileName, $xml); if (isset($this->tempDocumentRelations[$fileName])) { @@ -930,7 +921,7 @@ protected function savePartWithRels($fileName, $xml) * * @param string $fileName */ - public function saveAs($fileName) + public function saveAs($fileName): void { $tempFileName = $this->save(); @@ -997,7 +988,7 @@ protected function setValueForPart($search, $replace, $documentPartXML, $limit) */ protected function getVariablesForPart($documentPartXML) { - $matches = array(); + $matches = []; preg_match_all('/\$\{(.*?)}/i', $documentPartXML, $matches); return $matches[1]; @@ -1026,14 +1017,14 @@ protected function getMainPartName() $pattern = '~PartName="\/(word\/document.*?\.xml)" ContentType="application\/vnd\.openxmlformats-officedocument\.wordprocessingml\.document\.main\+xml"~'; - $matches = array(); + $matches = []; preg_match($pattern, $contentTypes, $matches); return array_key_exists(1, $matches) ? $matches[1] : 'word/document.xml'; } /** - * The name of the file containing the Settings part + * The name of the file containing the Settings part. * * @return string */ @@ -1071,7 +1062,7 @@ protected function getNextRelationsIndex($documentPartName) if (isset($this->tempDocumentRelations[$documentPartName])) { $candidate = substr_count($this->tempDocumentRelations[$documentPartName], 'tempDocumentRelations[$documentPartName], 'Id="rId' . $candidate . '"') !== false) { - $candidate++; + ++$candidate; } return $candidate; @@ -1093,8 +1084,6 @@ protected function getDocumentContentTypesName() * * @param int $offset * - * @throws \PhpOffice\PhpWord\Exception\Exception - * * @return int */ protected function findRowStart($offset) @@ -1142,7 +1131,7 @@ protected function getSlice($startPosition, $endPosition = 0) /** * Replaces variable names in cloned - * rows/blocks with indexed names + * rows/blocks with indexed names. * * @param int $count * @param string $xmlBlock @@ -1151,8 +1140,8 @@ protected function getSlice($startPosition, $endPosition = 0) */ protected function indexClonedVariables($count, $xmlBlock) { - $results = array(); - for ($i = 1; $i <= $count; $i++) { + $results = []; + for ($i = 1; $i <= $count; ++$i) { $results[] = preg_replace('/\$\{([^:]*?)(:.*?)?\}/', '\${\1#' . $i . '\2}', $xmlBlock); } @@ -1160,7 +1149,7 @@ protected function indexClonedVariables($count, $xmlBlock) } /** - * Raplaces variables with values from array, array keys are the variable names + * Raplaces variables with values from array, array keys are the variable names. * * @param array $variableReplacements * @param string $xmlBlock @@ -1169,7 +1158,7 @@ protected function indexClonedVariables($count, $xmlBlock) */ protected function replaceClonedVariables($variableReplacements, $xmlBlock) { - $results = array(); + $results = []; foreach ($variableReplacements as $replacementArray) { $localXmlBlock = $xmlBlock; foreach ($replacementArray as $search => $replacement) { @@ -1182,11 +1171,12 @@ protected function replaceClonedVariables($variableReplacements, $xmlBlock) } /** - * Replace an XML block surrounding a macro with a new block + * Replace an XML block surrounding a macro with a new block. * * @param string $macro Name of macro * @param string $block New block content * @param string $blockType XML tag type of block + * * @return \PhpOffice\PhpWord\TemplateProcessor Fluent interface */ public function replaceXmlBlock($macro, $block, $blockType = 'w:p') @@ -1201,12 +1191,13 @@ public function replaceXmlBlock($macro, $block, $blockType = 'w:p') /** * Find start and end of XML block containing the given macro - * e.g. ...${macro}... + * e.g. ...${macro}.... * * Note that only the first instance of the macro will be found * * @param string $macro Name of macro * @param string $blockType XML tag for block + * * @return bool|int[] FALSE if not found, otherwise array with start and end */ protected function findContainingXmlBlockForMacro($macro, $blockType = 'w:p') @@ -1225,11 +1216,11 @@ protected function findContainingXmlBlockForMacro($macro, $blockType = 'w:p') return false; } - return array('start' => $start, 'end' => $end); + return ['start' => $start, 'end' => $end]; } /** - * Find the position of (the start of) a macro + * Find the position of (the start of) a macro. * * Returns -1 if not found, otherwise position of opening $ * @@ -1237,6 +1228,7 @@ protected function findContainingXmlBlockForMacro($macro, $blockType = 'w:p') * * @param string $search Macro name * @param int $offset Offset from which to start searching + * * @return int -1 if macro not found */ protected function findMacro($search, $offset = 0) @@ -1248,10 +1240,11 @@ protected function findMacro($search, $offset = 0) } /** - * Find the start position of the nearest XML block start before $offset + * Find the start position of the nearest XML block start before $offset. * * @param int $offset Search position * @param string $blockType XML Block tag + * * @return int -1 if block start not found */ protected function findXmlBlockStart($offset, $blockType) @@ -1269,10 +1262,11 @@ protected function findXmlBlockStart($offset, $blockType) } /** - * Find the nearest block end position after $offset + * Find the nearest block end position after $offset. * * @param int $offset Search position * @param string $blockType XML Block tag + * * @return int -1 if block end not found */ protected function findXmlBlockEnd($offset, $blockType) @@ -1284,9 +1278,10 @@ protected function findXmlBlockEnd($offset, $blockType) } /** - * Splits a w:r/w:t into a list of w:r where each ${macro} is in a separate w:r + * Splits a w:r/w:t into a list of w:r where each ${macro} is in a separate w:r. * * @param string $text + * * @return string */ protected function splitTextIntoTexts($text) @@ -1294,7 +1289,7 @@ protected function splitTextIntoTexts($text) if (!$this->textNeedsSplitting($text)) { return $text; } - $matches = array(); + $matches = []; if (preg_match('/()/i', $text, $matches)) { $extractedStyle = $matches[0]; } else { @@ -1302,15 +1297,16 @@ protected function splitTextIntoTexts($text) } $unformattedText = preg_replace('/>\s+<', $text); - $result = str_replace(array('${', '}'), array('' . $extractedStyle . '${', '}' . $extractedStyle . ''), $unformattedText); + $result = str_replace(['${', '}'], ['' . $extractedStyle . '${', '}' . $extractedStyle . ''], $unformattedText); - return str_replace(array('' . $extractedStyle . '', '', ''), array('', '', ''), $result); + return str_replace(['' . $extractedStyle . '', '', ''], ['', '', ''], $result); } /** - * Returns true if string contains a macro that is not in it's own w:r + * Returns true if string contains a macro that is not in it's own w:r. * * @param string $text + * * @return bool */ protected function textNeedsSplitting($text) diff --git a/src/PhpWord/Writer/AbstractWriter.php b/src/PhpWord/Writer/AbstractWriter.php index 2c1ad29460..5bceac8021 100644 --- a/src/PhpWord/Writer/AbstractWriter.php +++ b/src/PhpWord/Writer/AbstractWriter.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -24,96 +24,97 @@ use PhpOffice\PhpWord\Shared\ZipArchive; /** - * Abstract writer class + * Abstract writer class. * * @since 0.10.0 */ abstract class AbstractWriter implements WriterInterface { /** - * PHPWord object + * PHPWord object. * * @var \PhpOffice\PhpWord\PhpWord */ - protected $phpWord = null; + protected $phpWord; /** - * Part name and file name pairs + * Part name and file name pairs. * * @var array */ - protected $parts = array(); + protected $parts = []; /** - * Individual writers + * Individual writers. * * @var array */ - protected $writerParts = array(); + protected $writerParts = []; /** - * Paths to store media files + * Paths to store media files. * * @var array */ - protected $mediaPaths = array('image' => '', 'object' => ''); + protected $mediaPaths = ['image' => '', 'object' => '']; /** - * Use disk caching + * Use disk caching. * * @var bool */ private $useDiskCaching = false; /** - * Disk caching directory + * Disk caching directory. * * @var string */ private $diskCachingDirectory = './'; /** - * Temporary directory + * Temporary directory. * * @var string */ private $tempDir = ''; /** - * Original file name + * Original file name. * * @var string */ private $originalFilename; /** - * Temporary file name + * Temporary file name. * * @var string */ private $tempFilename; /** - * Get PhpWord object + * Get PhpWord object. * - * @throws \PhpOffice\PhpWord\Exception\Exception * @return \PhpOffice\PhpWord\PhpWord */ public function getPhpWord() { - if (!is_null($this->phpWord)) { + if (null !== $this->phpWord) { return $this->phpWord; } + throw new Exception('No PhpWord assigned.'); } /** - * Set PhpWord object + * Set PhpWord object. * * @param \PhpOffice\PhpWord\PhpWord + * * @return self */ - public function setPhpWord(PhpWord $phpWord = null) + public function setPhpWord(?PhpWord $phpWord = null) { $this->phpWord = $phpWord; @@ -121,9 +122,10 @@ public function setPhpWord(PhpWord $phpWord = null) } /** - * Get writer part + * Get writer part. * * @param string $partName Writer part name + * * @return mixed */ public function getWriterPart($partName = '') @@ -136,7 +138,7 @@ public function getWriterPart($partName = '') } /** - * Get use disk caching status + * Get use disk caching status. * * @return bool */ @@ -146,19 +148,18 @@ public function isUseDiskCaching() } /** - * Set use disk caching status + * Set use disk caching status. * * @param bool $value * @param string $directory * - * @throws \PhpOffice\PhpWord\Exception\Exception * @return self */ public function setUseDiskCaching($value = false, $directory = null) { $this->useDiskCaching = $value; - if (!is_null($directory)) { + if (null !== $directory) { if (is_dir($directory)) { $this->diskCachingDirectory = $directory; } else { @@ -170,7 +171,7 @@ public function setUseDiskCaching($value = false, $directory = null) } /** - * Get disk caching directory + * Get disk caching directory. * * @return string */ @@ -180,7 +181,7 @@ public function getDiskCachingDirectory() } /** - * Get temporary directory + * Get temporary directory. * * @return string */ @@ -190,9 +191,10 @@ public function getTempDir() } /** - * Set temporary directory + * Set temporary directory. * * @param string $value + * * @return self */ public function setTempDir($value) @@ -206,11 +208,12 @@ public function setTempDir($value) } /** - * Get temporary file name + * Get temporary file name. * * If $filename is php://output or php://stdout, make it a temporary file * * @param string $filename + * * @return string */ protected function getTempFile($filename) @@ -233,10 +236,8 @@ protected function getTempFile($filename) /** * Cleanup temporary file. - * - * @throws \PhpOffice\PhpWord\Exception\CopyFileException */ - protected function cleanupTempFile() + protected function cleanupTempFile(): void { if ($this->originalFilename != $this->tempFilename) { // @codeCoverageIgnoreStart @@ -254,7 +255,7 @@ protected function cleanupTempFile() /** * Clear temporary directory. */ - protected function clearTempDir() + protected function clearTempDir(): void { if (is_dir($this->tempDir)) { $this->deleteDir($this->tempDir); @@ -262,12 +263,10 @@ protected function clearTempDir() } /** - * Get ZipArchive object + * Get ZipArchive object. * * @param string $filename * - * @throws \Exception - * * @return \PhpOffice\PhpWord\Shared\ZipArchive */ protected function getZipArchive($filename) @@ -293,20 +292,18 @@ protected function getZipArchive($filename) } /** - * Open file for writing + * Open file for writing. * * @since 0.11.0 * * @param string $filename * - * @throws \Exception - * * @return resource */ protected function openFile($filename) { $filename = $this->getTempFile($filename); - $fileHandle = fopen($filename, 'w'); + $fileHandle = fopen($filename, 'wb'); // @codeCoverageIgnoreStart // Can't find any test case. Uncomment when found. if ($fileHandle === false) { @@ -325,7 +322,7 @@ protected function openFile($filename) * @param resource $fileHandle * @param string $content */ - protected function writeFile($fileHandle, $content) + protected function writeFile($fileHandle, $content): void { fwrite($fileHandle, $content); fclose($fileHandle); @@ -335,10 +332,9 @@ protected function writeFile($fileHandle, $content) /** * Add files to package. * - * @param \PhpOffice\PhpWord\Shared\ZipArchive $zip * @param mixed $elements */ - protected function addFilesToPackage(ZipArchive $zip, $elements) + protected function addFilesToPackage(ZipArchive $zip, $elements): void { foreach ($elements as $element) { $type = $element['type']; // image|object|link @@ -377,13 +373,13 @@ protected function addFilesToPackage(ZipArchive $zip, $elements) * @param string $source * @param string $target */ - protected function addFileToPackage($zipPackage, $source, $target) + protected function addFileToPackage($zipPackage, $source, $target): void { $isArchive = strpos($source, 'zip://') !== false; $actualSource = null; if ($isArchive) { $source = substr($source, 6); - list($zipFilename, $imageFilename) = explode('#', $source); + [$zipFilename, $imageFilename] = explode('#', $source); $zip = new ZipArchive(); if ($zip->open($zipFilename) !== false) { @@ -397,7 +393,7 @@ protected function addFileToPackage($zipPackage, $source, $target) $actualSource = $source; } - if (!is_null($actualSource)) { + if (null !== $actualSource) { $zipPackage->addFile($actualSource, $target); } } @@ -407,7 +403,7 @@ protected function addFileToPackage($zipPackage, $source, $target) * * @param string $dir */ - private function deleteDir($dir) + private function deleteDir($dir): void { foreach (scandir($dir) as $file) { if ($file === '.' || $file === '..') { @@ -423,7 +419,7 @@ private function deleteDir($dir) } /** - * Get use disk caching status + * Get use disk caching status. * * @deprecated 0.10.0 * diff --git a/src/PhpWord/Writer/HTML.php b/src/PhpWord/Writer/HTML.php index 7f55b9d3e6..34d3fb32a6 100644 --- a/src/PhpWord/Writer/HTML.php +++ b/src/PhpWord/Writer/HTML.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,9 +20,10 @@ use PhpOffice\PhpWord\PhpWord; /** - * HTML writer + * HTML writer. * * Not supported: PreserveText, PageBreak, Object + * * @since 0.10.0 */ class HTML extends AbstractWriter implements WriterInterface @@ -35,20 +36,20 @@ class HTML extends AbstractWriter implements WriterInterface protected $isPdf = false; /** - * Footnotes and endnotes collection + * Footnotes and endnotes collection. * * @var array */ - protected $notes = array(); + protected $notes = []; /** - * Create new instance + * Create new instance. */ - public function __construct(PhpWord $phpWord = null) + public function __construct(?PhpWord $phpWord = null) { $this->setPhpWord($phpWord); - $this->parts = array('Head', 'Body'); + $this->parts = ['Head', 'Body']; foreach ($this->parts as $partName) { $partClass = 'PhpOffice\\PhpWord\\Writer\\HTML\\Part\\' . $partName; if (class_exists($partClass)) { @@ -64,18 +65,17 @@ public function __construct(PhpWord $phpWord = null) * Save PhpWord to file. * * @param string $filename - * - * @throws \PhpOffice\PhpWord\Exception\Exception */ - public function save($filename = null) + public function save($filename = null): void { $this->writeFile($this->openFile($filename), $this->getContent()); } /** - * Get content + * Get content. * * @return string + * * @since 0.11.0 */ public function getContent() @@ -93,7 +93,7 @@ public function getContent() } /** - * Get is PDF + * Get is PDF. * * @return bool */ @@ -103,7 +103,7 @@ public function isPdf() } /** - * Get notes + * Get notes. * * @return array */ @@ -118,13 +118,13 @@ public function getNotes() * @param int $noteId * @param string $noteMark */ - public function addNote($noteId, $noteMark) + public function addNote($noteId, $noteMark): void { $this->notes[$noteId] = $noteMark; } /** - * Write document + * Write document. * * @deprecated 0.11.0 * diff --git a/src/PhpWord/Writer/HTML/Element/AbstractElement.php b/src/PhpWord/Writer/HTML/Element/AbstractElement.php index 30d1ccaa4c..f5b0e91719 100644 --- a/src/PhpWord/Writer/HTML/Element/AbstractElement.php +++ b/src/PhpWord/Writer/HTML/Element/AbstractElement.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -22,28 +22,28 @@ use PhpOffice\PhpWord\Writer\AbstractWriter; /** - * Abstract HTML element writer + * Abstract HTML element writer. * * @since 0.11.0 */ abstract class AbstractElement { /** - * Parent writer + * Parent writer. * * @var \PhpOffice\PhpWord\Writer\AbstractWriter */ protected $parentWriter; /** - * Element + * Element. * * @var \PhpOffice\PhpWord\Element\AbstractElement */ protected $element; /** - * Without paragraph + * Without paragraph. * * @var bool */ @@ -55,15 +55,13 @@ abstract class AbstractElement protected $escaper; /** - * Write element + * Write element. */ abstract public function write(); /** - * Create new instance + * Create new instance. * - * @param \PhpOffice\PhpWord\Writer\AbstractWriter $parentWriter - * @param \PhpOffice\PhpWord\Element\AbstractElement $element * @param bool $withoutP */ public function __construct(AbstractWriter $parentWriter, Element $element, $withoutP = false) @@ -79,7 +77,7 @@ public function __construct(AbstractWriter $parentWriter, Element $element, $wit * * @param bool $value */ - public function setWithoutP($value) + public function setWithoutP($value): void { $this->withoutP = $value; } diff --git a/src/PhpWord/Writer/HTML/Element/Bookmark.php b/src/PhpWord/Writer/HTML/Element/Bookmark.php index 082bd76073..521a73db09 100644 --- a/src/PhpWord/Writer/HTML/Element/Bookmark.php +++ b/src/PhpWord/Writer/HTML/Element/Bookmark.php @@ -11,21 +11,21 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Writer\HTML\Element; /** - * Bookmark element HTML writer + * Bookmark element HTML writer. * * @since 0.15.0 */ class Bookmark extends Text { /** - * Write bookmark + * Write bookmark. * * @return string */ diff --git a/src/PhpWord/Writer/HTML/Element/Container.php b/src/PhpWord/Writer/HTML/Element/Container.php index 006b588918..7909e73f21 100644 --- a/src/PhpWord/Writer/HTML/Element/Container.php +++ b/src/PhpWord/Writer/HTML/Element/Container.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,21 +20,21 @@ use PhpOffice\PhpWord\Element\AbstractContainer as ContainerElement; /** - * Container element HTML writer + * Container element HTML writer. * * @since 0.11.0 */ class Container extends AbstractElement { /** - * Namespace; Can't use __NAMESPACE__ in inherited class (RTF) + * Namespace; Can't use __NAMESPACE__ in inherited class (RTF). * * @var string */ protected $namespace = 'PhpOffice\\PhpWord\\Writer\\HTML\\Element'; /** - * Write container + * Write container. * * @return string */ @@ -45,7 +45,7 @@ public function write() return ''; } $containerClass = substr(get_class($container), strrpos(get_class($container), '\\') + 1); - $withoutP = in_array($containerClass, array('TextRun', 'Footnote', 'Endnote')) ? true : false; + $withoutP = in_array($containerClass, ['TextRun', 'Footnote', 'Endnote']) ? true : false; $content = ''; $elements = $container->getElements(); diff --git a/src/PhpWord/Writer/HTML/Element/Endnote.php b/src/PhpWord/Writer/HTML/Element/Endnote.php index 2252dc3af8..1c35e8faa8 100644 --- a/src/PhpWord/Writer/HTML/Element/Endnote.php +++ b/src/PhpWord/Writer/HTML/Element/Endnote.php @@ -11,21 +11,21 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Writer\HTML\Element; /** - * Endnote element HTML writer + * Endnote element HTML writer. * * @since 0.10.0 */ class Endnote extends Footnote { /** - * Note type + * Note type. * * @var string */ diff --git a/src/PhpWord/Writer/HTML/Element/Footnote.php b/src/PhpWord/Writer/HTML/Element/Footnote.php index ed14db1e04..0cb2ca5fcd 100644 --- a/src/PhpWord/Writer/HTML/Element/Footnote.php +++ b/src/PhpWord/Writer/HTML/Element/Footnote.php @@ -11,28 +11,28 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Writer\HTML\Element; /** - * Footnote element HTML writer + * Footnote element HTML writer. * * @since 0.10.0 */ class Footnote extends AbstractElement { /** - * Note type footnote|endnote + * Note type footnote|endnote. * * @var string */ protected $noteType = 'footnote'; /** - * Write footnote/endnote marks; The actual content is written in parent writer (HTML) + * Write footnote/endnote marks; The actual content is written in parent writer (HTML). * * @return string */ diff --git a/src/PhpWord/Writer/HTML/Element/Image.php b/src/PhpWord/Writer/HTML/Element/Image.php index 7c22a1663d..40e864e6a4 100644 --- a/src/PhpWord/Writer/HTML/Element/Image.php +++ b/src/PhpWord/Writer/HTML/Element/Image.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,14 +21,14 @@ use PhpOffice\PhpWord\Writer\HTML\Style\Image as ImageStyleWriter; /** - * Image element HTML writer + * Image element HTML writer. * * @since 0.10.0 */ class Image extends Text { /** - * Write image + * Write image. * * @return string */ diff --git a/src/PhpWord/Writer/HTML/Element/Link.php b/src/PhpWord/Writer/HTML/Element/Link.php index f6dae5cdd3..7d302c1f85 100644 --- a/src/PhpWord/Writer/HTML/Element/Link.php +++ b/src/PhpWord/Writer/HTML/Element/Link.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,14 +20,14 @@ use PhpOffice\PhpWord\Settings; /** - * Link element HTML writer + * Link element HTML writer. * * @since 0.10.0 */ class Link extends Text { /** - * Write link + * Write link. * * @return string */ diff --git a/src/PhpWord/Writer/HTML/Element/ListItem.php b/src/PhpWord/Writer/HTML/Element/ListItem.php index 384b3ef165..d04798684f 100644 --- a/src/PhpWord/Writer/HTML/Element/ListItem.php +++ b/src/PhpWord/Writer/HTML/Element/ListItem.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,14 +20,14 @@ use PhpOffice\PhpWord\Settings; /** - * ListItem element HTML writer + * ListItem element HTML writer. * * @since 0.10.0 */ class ListItem extends AbstractElement { /** - * Write list item + * Write list item. * * @return string */ diff --git a/src/PhpWord/Writer/HTML/Element/ListItemRun.php b/src/PhpWord/Writer/HTML/Element/ListItemRun.php index a4d7e46073..5bbe23f0f3 100644 --- a/src/PhpWord/Writer/HTML/Element/ListItemRun.php +++ b/src/PhpWord/Writer/HTML/Element/ListItemRun.php @@ -11,21 +11,21 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Writer\HTML\Element; /** - * ListItem element HTML writer + * ListItem element HTML writer. * * @since 0.10.0 */ class ListItemRun extends TextRun { /** - * Write list item + * Write list item. * * @return string */ diff --git a/src/PhpWord/Writer/HTML/Element/PageBreak.php b/src/PhpWord/Writer/HTML/Element/PageBreak.php index f9998e3793..762426bf26 100644 --- a/src/PhpWord/Writer/HTML/Element/PageBreak.php +++ b/src/PhpWord/Writer/HTML/Element/PageBreak.php @@ -11,21 +11,21 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Writer\HTML\Element; /** - * PageBreak element HTML writer + * PageBreak element HTML writer. * * @since 0.10.0 */ class PageBreak extends TextBreak { /** - * Write page break + * Write page break. * * @since 0.12.0 * diff --git a/src/PhpWord/Writer/HTML/Element/Table.php b/src/PhpWord/Writer/HTML/Element/Table.php index 059574a272..b1a2ee9667 100644 --- a/src/PhpWord/Writer/HTML/Element/Table.php +++ b/src/PhpWord/Writer/HTML/Element/Table.php @@ -11,21 +11,21 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Writer\HTML\Element; /** - * Table element HTML writer + * Table element HTML writer. * * @since 0.10.0 */ class Table extends AbstractElement { /** - * Write table + * Write table. * * @return string */ @@ -41,15 +41,15 @@ public function write() if ($rowCount > 0) { $content .= 'element->getStyle()) . '>' . PHP_EOL; - for ($i = 0; $i < $rowCount; $i++) { - /** @var $row \PhpOffice\PhpWord\Element\Row Type hint */ + for ($i = 0; $i < $rowCount; ++$i) { + /** @var \PhpOffice\PhpWord\Element\Row $row Type hint */ $rowStyle = $rows[$i]->getStyle(); // $height = $row->getHeight(); $tblHeader = $rowStyle->isTblHeader(); $content .= '
    '; + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + Html::addHtml($section, $html); + + self::assertInstanceOf(Table::class, $section->getElement(0)); + self::assertEquals('pStyle', $section->getElement(0)->getStyle()->getStyleName()); + } + /** * Test underline. */ From d721b5eda7e93997a4b5f4de31b24ca3751306da Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 23 Nov 2022 13:32:03 +0100 Subject: [PATCH 069/246] HTML Reader : Set style name from the CSS class (and if not CSS is loaded) --- src/PhpWord/Shared/Html.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index c937d29918..3253b83c99 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -160,8 +160,10 @@ protected static function parseInlineStyle($node, $styles = []) } $attributeClass = $attributes->getNamedItem('class'); - if ($attributeClass && self::$css) { - $styles = self::parseStyleDeclarations(self::$css->getStyle('.' . $attributeClass->value), $styles); + if ($attributeClass) { + if (self::$css) { + $styles = self::parseStyleDeclarations(self::$css->getStyle('.' . $attributeClass->value), $styles); + } $styles['className'] = $attributeClass->value; } From 25de4b819c037db33496508caed579f0370ce8c0 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 23 Nov 2022 20:36:39 +0000 Subject: [PATCH 070/246] Fixed PHPCSFixer error --- src/PhpWord/Style/Language.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index 63d6198c0f..e47cceb3e9 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -69,7 +69,7 @@ final class Language extends AbstractStyle const NL_NL = 'nl-NL'; const NL_NL_ID = 1043; - + const SV_SE = 'sv-SE'; const SV_SE_ID = 1053; From 803cdee4f3efe774bc658856d21d49f54624dd6e Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Tue, 29 Nov 2022 10:47:35 +0100 Subject: [PATCH 071/246] Use local install of friendsofphp/php-cs-fixer Otherwise, `composer check` and `composer fix` are broken and contributing becomes much harder than it should be. Also using the same version everywhere is a benefit to get consistent result locally and on CI. --- .github/workflows/ci.yml | 9 +++------ composer.json | 3 ++- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e50faea084..a822bd9328 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,14 +79,11 @@ jobs: key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- - - name: Composer Install - run: composer global require friendsofphp/php-cs-fixer - - - name: Add environment path - run: export PATH="$PATH:$HOME/.composer/vendor/bin" + - name: Install dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader - name: Code style with PHP-CS-Fixer - run: php-cs-fixer fix --dry-run --diff + run: ./vendor/bin/php-cs-fixer fix --dry-run --diff coverage: runs-on: ubuntu-latest diff --git a/composer.json b/composer.json index ccb42ccaf2..32d2711a31 100644 --- a/composer.json +++ b/composer.json @@ -73,7 +73,8 @@ "phpmd/phpmd": "^2.13", "phpunit/phpunit": ">=7.0", "tecnickcom/tcpdf": "^6.5", - "symfony/process": "^4.4" + "symfony/process": "^4.4", + "friendsofphp/php-cs-fixer": "^3.3" }, "suggest": { "ext-zip": "Allows writing OOXML and ODF", From 20f3a3e3704b08df641c3800778b65355471b546 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Tue, 29 Nov 2022 11:09:02 +0100 Subject: [PATCH 072/246] Use pcov instead of xdebug because it is much faster --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a822bd9328..b8e8cd16dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -96,7 +96,7 @@ jobs: with: php-version: 7.4 extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: xdebug + coverage: pcov - name: Get composer cache directory id: composer-cache From 3f2b90c40ed39eca2423594df516e7c635b9d65f Mon Sep 17 00:00:00 2001 From: Artem Vasilev Date: Tue, 20 Dec 2022 20:46:28 +0300 Subject: [PATCH 073/246] Add nowrap parameter for table cell --- src/PhpWord/Reader/Word2007/AbstractPart.php | 1 + src/PhpWord/Style/Cell.php | 29 ++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index df3cfed709..96ef9b28d7 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -560,6 +560,7 @@ private function readCellStyle(XMLReader $xmlReader, DOMElement $domNode) 'gridSpan' => [self::READ_VALUE, 'w:gridSpan'], 'vMerge' => [self::READ_VALUE, 'w:vMerge', null, null, 'continue'], 'bgColor' => [self::READ_VALUE, 'w:shd', 'w:fill'], + 'noWrap' => [self::READ_VALUE, 'w:noWrap', null, null, true] ]; return $this->readStyleDefs($xmlReader, $domNode, $styleDefs); diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index b2bd9aeb21..56b26c42e7 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -118,6 +118,13 @@ class Cell extends Border */ private $unit = TblWidth::TWIP; + /** + * Prevent text from wrapping in the cell + * + * @var bool + */ + private $noWrap; + /** * Get vertical align. * @@ -312,4 +319,26 @@ public function setUnit($value) return $this; } + + /** + * Set noWrap + * + * @param $value + */ + public function setNoWrap($value) + { + $this->noWrap = $this->setBoolVal($value, true); + + return $this; + } + + /** + * Get noWrap + * + * @return bool + */ + public function getNoWrap() + { + return $this->noWrap; + } } From 9ba0fa762b95c1f5e35abb1da62d87592dee3fc3 Mon Sep 17 00:00:00 2001 From: Artem Vasilev Date: Tue, 20 Dec 2022 20:51:04 +0300 Subject: [PATCH 074/246] ADD: noWrap to Word2007 writer --- src/PhpWord/Writer/Word2007/Style/Cell.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/PhpWord/Writer/Word2007/Style/Cell.php b/src/PhpWord/Writer/Word2007/Style/Cell.php index 9a489b6622..870419cadd 100644 --- a/src/PhpWord/Writer/Word2007/Style/Cell.php +++ b/src/PhpWord/Writer/Word2007/Style/Cell.php @@ -89,6 +89,10 @@ public function write(): void $xmlWriter->writeElementIf(null !== $gridSpan, 'w:gridSpan', 'w:val', $gridSpan); $xmlWriter->writeElementIf(null !== $vMerge, 'w:vMerge', 'w:val', $vMerge); + // noWrap + $noWrap = $style->getNoWrap(); + $xmlWriter->writeElementIf(true === $noWrap, 'w:noWrap'); + $xmlWriter->endElement(); // w:tcPr } From 831c1bc6ac3db2a9b046338cc22c69ae110da9bc Mon Sep 17 00:00:00 2001 From: Artem Vasilev Date: Tue, 20 Dec 2022 21:09:02 +0300 Subject: [PATCH 075/246] FIX: code style --- src/PhpWord/Reader/Word2007/AbstractPart.php | 2 +- src/PhpWord/Style/Cell.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 96ef9b28d7..6c7fd245a7 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -560,7 +560,7 @@ private function readCellStyle(XMLReader $xmlReader, DOMElement $domNode) 'gridSpan' => [self::READ_VALUE, 'w:gridSpan'], 'vMerge' => [self::READ_VALUE, 'w:vMerge', null, null, 'continue'], 'bgColor' => [self::READ_VALUE, 'w:shd', 'w:fill'], - 'noWrap' => [self::READ_VALUE, 'w:noWrap', null, null, true] + 'noWrap' => [self::READ_VALUE, 'w:noWrap', null, null, true], ]; return $this->readStyleDefs($xmlReader, $domNode, $styleDefs); diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index 56b26c42e7..e96fb65422 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -119,7 +119,7 @@ class Cell extends Border private $unit = TblWidth::TWIP; /** - * Prevent text from wrapping in the cell + * Prevent text from wrapping in the cell. * * @var bool */ @@ -321,7 +321,7 @@ public function setUnit($value) } /** - * Set noWrap + * Set noWrap. * * @param $value */ @@ -333,7 +333,7 @@ public function setNoWrap($value) } /** - * Get noWrap + * Get noWrap. * * @return bool */ From 1dc3dc6ce5ee3dca89fc0d9c99a6052b94a77b03 Mon Sep 17 00:00:00 2001 From: Erik Hazington <83652897+hazington@users.noreply.github.com> Date: Fri, 30 Dec 2022 21:32:48 +0100 Subject: [PATCH 076/246] Add background color support for textboxes --- src/PhpWord/Style/TextBox.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/PhpWord/Style/TextBox.php b/src/PhpWord/Style/TextBox.php index e43e6fa231..447c6c91dd 100644 --- a/src/PhpWord/Style/TextBox.php +++ b/src/PhpWord/Style/TextBox.php @@ -65,6 +65,33 @@ class TextBox extends Image * @var string */ private $borderColor; + + /** + * background color + * + * @var string + */ + private $bgColor; + + /** + * Set background color + * + * @param string $value + */ + public function setBgColor($value = null) + { + $this->bgColor = $value; + } + + /** + * Get background color + * + * @return string + */ + public function getBgColor() + { + return $this->bgColor; + } /** * Set margin top. From 25575c80ca1ec1a496eba09882a9cada56626190 Mon Sep 17 00:00:00 2001 From: Erik Hazington <83652897+hazington@users.noreply.github.com> Date: Fri, 30 Dec 2022 21:34:47 +0100 Subject: [PATCH 077/246] Add background color support for text boxes for Word writer --- src/PhpWord/Writer/Word2007/Element/TextBox.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/PhpWord/Writer/Word2007/Element/TextBox.php b/src/PhpWord/Writer/Word2007/Element/TextBox.php index d264f084dd..54db928587 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Element/TextBox.php @@ -50,6 +50,9 @@ public function write(): void $xmlWriter->startElement('v:shape'); $xmlWriter->writeAttribute('type', '#_x0000_t0202'); + if ($style->getBgColor()) { + $xmlWriter->writeAttribute('fillcolor', $style->getBgColor()); + } $styleWriter->write(); $styleWriter->writeBorder(); From 143e01b29b3595eae2ce032deca313e49480c848 Mon Sep 17 00:00:00 2001 From: Erik Hazington <83652897+hazington@users.noreply.github.com> Date: Fri, 30 Dec 2022 21:46:44 +0100 Subject: [PATCH 078/246] Added period to the comments to match the cs-fixer configuration --- src/PhpWord/Style/TextBox.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PhpWord/Style/TextBox.php b/src/PhpWord/Style/TextBox.php index 447c6c91dd..a43b76fedd 100644 --- a/src/PhpWord/Style/TextBox.php +++ b/src/PhpWord/Style/TextBox.php @@ -67,14 +67,14 @@ class TextBox extends Image private $borderColor; /** - * background color + * background color. * * @var string */ private $bgColor; /** - * Set background color + * Set background color. * * @param string $value */ @@ -84,7 +84,7 @@ public function setBgColor($value = null) } /** - * Get background color + * Get background color. * * @return string */ From 40d57706515da9821006163f3d3463484b2ee067 Mon Sep 17 00:00:00 2001 From: Erik Hazington <83652897+hazington@users.noreply.github.com> Date: Fri, 30 Dec 2022 21:50:28 +0100 Subject: [PATCH 079/246] Fixed cs-fixer issues. --- src/PhpWord/Style/TextBox.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/Style/TextBox.php b/src/PhpWord/Style/TextBox.php index a43b76fedd..846c89b567 100644 --- a/src/PhpWord/Style/TextBox.php +++ b/src/PhpWord/Style/TextBox.php @@ -65,7 +65,7 @@ class TextBox extends Image * @var string */ private $borderColor; - + /** * background color. * @@ -78,7 +78,7 @@ class TextBox extends Image * * @param string $value */ - public function setBgColor($value = null) + public function setBgColor($value = null): void { $this->bgColor = $value; } From 1a80aacb4fb361e00b9ab89cea45245bffd0212a Mon Sep 17 00:00:00 2001 From: hazington Date: Tue, 3 Jan 2023 23:26:02 +0100 Subject: [PATCH 080/246] Added type hints and matching PHPDoc. Also added @return void. --- src/PhpWord/Style/TextBox.php | 87 ++++++++++--------- .../Writer/Word2007/Element/TextBox.php | 10 +-- src/PhpWord/Writer/Word2007/Style/TextBox.php | 2 + 3 files changed, 53 insertions(+), 46 deletions(-) diff --git a/src/PhpWord/Style/TextBox.php b/src/PhpWord/Style/TextBox.php index 846c89b567..68b516b1aa 100644 --- a/src/PhpWord/Style/TextBox.php +++ b/src/PhpWord/Style/TextBox.php @@ -2,16 +2,13 @@ /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. - * * PHPWord is free software distributed under the terms of the GNU Lesser * General Public License version 3 as published by the Free Software Foundation. - * * For the full copyright and license information, please read the LICENSE * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -27,58 +24,59 @@ class TextBox extends Image /** * margin top. * - * @var int + * @var null|int */ private $innerMarginTop; /** * margin left. * - * @var int + * @var null|int */ private $innerMarginLeft; /** * margin right. * - * @var int + * @var null|int */ private $innerMarginRight; /** * Cell margin bottom. * - * @var int + * @var null|int */ private $innerMarginBottom; /** * border size. * - * @var int + * @var null|int */ private $borderSize; /** * border color. * - * @var string + * @var null|string */ private $borderColor; /** * background color. * - * @var string + * @var null|string */ private $bgColor; /** * Set background color. * - * @param string $value + * @param null|string $value + * @return void */ - public function setBgColor($value = null): void + public function setBgColor(string $value = null): void { $this->bgColor = $value; } @@ -86,9 +84,9 @@ public function setBgColor($value = null): void /** * Get background color. * - * @return string + * @return null|string */ - public function getBgColor() + public function getBgColor(): ?string { return $this->bgColor; } @@ -96,9 +94,10 @@ public function getBgColor() /** * Set margin top. * - * @param int $value + * @param null|int $value + * @return void */ - public function setInnerMarginTop($value = null): void + public function setInnerMarginTop(int $value = null): void { $this->innerMarginTop = $value; } @@ -106,9 +105,9 @@ public function setInnerMarginTop($value = null): void /** * Get margin top. * - * @return int + * @return null|int */ - public function getInnerMarginTop() + public function getInnerMarginTop(): ?int { return $this->innerMarginTop; } @@ -116,9 +115,10 @@ public function getInnerMarginTop() /** * Set margin left. * - * @param int $value + * @param null|int $value + * @return void */ - public function setInnerMarginLeft($value = null): void + public function setInnerMarginLeft(int $value = null): void { $this->innerMarginLeft = $value; } @@ -126,9 +126,9 @@ public function setInnerMarginLeft($value = null): void /** * Get margin left. * - * @return int + * @return null|int */ - public function getInnerMarginLeft() + public function getInnerMarginLeft(): ?int { return $this->innerMarginLeft; } @@ -136,9 +136,10 @@ public function getInnerMarginLeft() /** * Set margin right. * - * @param int $value + * @param null|int $value + * @return void */ - public function setInnerMarginRight($value = null): void + public function setInnerMarginRight(int $value = null): void { $this->innerMarginRight = $value; } @@ -146,9 +147,9 @@ public function setInnerMarginRight($value = null): void /** * Get margin right. * - * @return int + * @return null|int */ - public function getInnerMarginRight() + public function getInnerMarginRight(): ?int { return $this->innerMarginRight; } @@ -156,9 +157,10 @@ public function getInnerMarginRight() /** * Set margin bottom. * - * @param int $value + * @param null|int $value + * @return void */ - public function setInnerMarginBottom($value = null): void + public function setInnerMarginBottom(int $value = null): void { $this->innerMarginBottom = $value; } @@ -166,9 +168,9 @@ public function setInnerMarginBottom($value = null): void /** * Get margin bottom. * - * @return int + * @return null|int */ - public function getInnerMarginBottom() + public function getInnerMarginBottom(): ?int { return $this->innerMarginBottom; } @@ -176,9 +178,10 @@ public function getInnerMarginBottom() /** * Set TLRB cell margin. * - * @param int $value Margin in twips + * @param null|int $value Margin in twips + * @return void */ - public function setInnerMargin($value = null): void + public function setInnerMargin(int $value = null): void { $this->setInnerMarginTop($value); $this->setInnerMarginLeft($value); @@ -191,7 +194,7 @@ public function setInnerMargin($value = null): void * * @return int[] */ - public function getInnerMargin() + public function getInnerMargin(): array { return [$this->innerMarginLeft, $this->innerMarginTop, $this->innerMarginRight, $this->innerMarginBottom]; } @@ -201,7 +204,7 @@ public function getInnerMargin() * * @return bool */ - public function hasInnerMargins() + public function hasInnerMargins(): bool { $hasInnerMargins = false; $margins = $this->getInnerMargin(); @@ -218,9 +221,10 @@ public function hasInnerMargins() /** * Set border size. * - * @param int $value Size in points + * @param null|int $value Size in points + * @return void */ - public function setBorderSize($value = null): void + public function setBorderSize(int $value = null): void { $this->borderSize = $value; } @@ -230,7 +234,7 @@ public function setBorderSize($value = null): void * * @return int */ - public function getBorderSize() + public function getBorderSize(): int { return $this->borderSize; } @@ -238,9 +242,10 @@ public function getBorderSize() /** * Set border color. * - * @param string $value + * @param null|string $value + * @return void */ - public function setBorderColor($value = null): void + public function setBorderColor(string $value = null): void { $this->borderColor = $value; } @@ -248,9 +253,9 @@ public function setBorderColor($value = null): void /** * Get border color. * - * @return string + * @return null|string */ - public function getBorderColor() + public function getBorderColor(): ?string { return $this->borderColor; } diff --git a/src/PhpWord/Writer/Word2007/Element/TextBox.php b/src/PhpWord/Writer/Word2007/Element/TextBox.php index 54db928587..18fef7a653 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Element/TextBox.php @@ -2,16 +2,13 @@ /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. - * * PHPWord is free software distributed under the terms of the GNU Lesser * General Public License version 3 as published by the Free Software Foundation. - * * For the full copyright and license information, please read the LICENSE * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -28,18 +25,20 @@ class TextBox extends Image { /** * Write element. + * + * @return void */ public function write(): void { $xmlWriter = $this->getXmlWriter(); $element = $this->getElement(); - if (!$element instanceof \PhpOffice\PhpWord\Element\TextBox) { + if (! $element instanceof \PhpOffice\PhpWord\Element\TextBox) { return; } $style = $element->getStyle(); $styleWriter = new TextBoxStyleWriter($xmlWriter, $style); - if (!$this->withoutP) { + if (! $this->withoutP) { $xmlWriter->startElement('w:p'); $styleWriter->writeAlignment(); } @@ -53,6 +52,7 @@ public function write(): void if ($style->getBgColor()) { $xmlWriter->writeAttribute('fillcolor', $style->getBgColor()); } + $styleWriter->write(); $styleWriter->writeBorder(); diff --git a/src/PhpWord/Writer/Word2007/Style/TextBox.php b/src/PhpWord/Writer/Word2007/Style/TextBox.php index 6aa6b0199e..89dc4a395b 100644 --- a/src/PhpWord/Writer/Word2007/Style/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Style/TextBox.php @@ -28,6 +28,7 @@ class TextBox extends Frame { /** * Writer inner margin. + * @return void */ public function writeInnerMargin(): void { @@ -44,6 +45,7 @@ public function writeInnerMargin(): void /** * Writer border. + * @return void */ public function writeBorder(): void { From a215501cc992e638edf390f087198a696d694684 Mon Sep 17 00:00:00 2001 From: hazington Date: Tue, 3 Jan 2023 23:35:37 +0100 Subject: [PATCH 081/246] Added bgcolor unit test coverage --- tests/PhpWordTests/Style/TextBoxTest.php | 84 +++++++++++++----------- 1 file changed, 47 insertions(+), 37 deletions(-) diff --git a/tests/PhpWordTests/Style/TextBoxTest.php b/tests/PhpWordTests/Style/TextBoxTest.php index 3c1c243676..76688377e2 100644 --- a/tests/PhpWordTests/Style/TextBoxTest.php +++ b/tests/PhpWordTests/Style/TextBoxTest.php @@ -2,16 +2,13 @@ /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. - * * PHPWord is free software distributed under the terms of the GNU Lesser * General Public License version 3 as published by the Free Software Foundation. - * * For the full copyright and license information, please read the LICENSE * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,15 +17,15 @@ use InvalidArgumentException; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\Style\TextBox; +use PHPUnit\Framework\TestCase; /** * Test class for PhpOffice\PhpWord\Style\Image. * * @coversDefaultClass \PhpOffice\PhpWord\Style\Image - * * @runTestsInSeparateProcesses */ -class TextBoxTest extends \PHPUnit\Framework\TestCase +class TextBoxTest extends TestCase { /** * Test setting style with normal value. @@ -38,23 +35,24 @@ public function testSetGetNormal(): void $object = new TextBox(); $properties = [ - 'width' => 200, - 'height' => 200, - 'alignment' => Jc::START, - 'marginTop' => 240, - 'marginLeft' => 240, - 'wrappingStyle' => 'inline', - 'positioning' => 'absolute', - 'posHorizontal' => 'center', - 'posVertical' => 'top', - 'posHorizontalRel' => 'margin', - 'posVerticalRel' => 'page', - 'innerMarginTop' => '5', - 'innerMarginRight' => '5', + 'width' => 200, + 'height' => 200, + 'alignment' => Jc::START, + 'marginTop' => 240, + 'marginLeft' => 240, + 'wrappingStyle' => 'inline', + 'positioning' => 'absolute', + 'posHorizontal' => 'center', + 'posVertical' => 'top', + 'posHorizontalRel' => 'margin', + 'posVerticalRel' => 'page', + 'innerMarginTop' => '5', + 'innerMarginRight' => '5', 'innerMarginBottom' => '5', - 'innerMarginLeft' => '5', - 'borderSize' => '2', - 'borderColor' => 'red', + 'innerMarginLeft' => '5', + 'borderSize' => '2', + 'borderColor' => 'red', + 'bgColor' => 'blue', ]; foreach ($properties as $key => $value) { $set = "set{$key}"; @@ -72,23 +70,24 @@ public function testSetStyleValue(): void $object = new TextBox(); $properties = [ - 'width' => 200, - 'height' => 200, - 'alignment' => Jc::START, - 'marginTop' => 240, - 'marginLeft' => 240, - 'wrappingStyle' => 'inline', - 'positioning' => 'absolute', - 'posHorizontal' => 'center', - 'posVertical' => 'top', - 'posHorizontalRel' => 'margin', - 'posVerticalRel' => 'page', - 'innerMarginTop' => '5', - 'innerMarginRight' => '5', + 'width' => 200, + 'height' => 200, + 'alignment' => Jc::START, + 'marginTop' => 240, + 'marginLeft' => 240, + 'wrappingStyle' => 'inline', + 'positioning' => 'absolute', + 'posHorizontal' => 'center', + 'posVertical' => 'top', + 'posHorizontalRel' => 'margin', + 'posVerticalRel' => 'page', + 'innerMarginTop' => '5', + 'innerMarginRight' => '5', 'innerMarginBottom' => '5', - 'innerMarginLeft' => '5', - 'borderSize' => '2', - 'borderColor' => 'red', + 'innerMarginLeft' => '5', + 'borderSize' => '2', + 'borderColor' => 'red', + 'bgColor' => 'blue', ]; foreach ($properties as $key => $value) { $get = "get{$key}"; @@ -305,4 +304,15 @@ public function testSetGetBorderColor(): void $object->setBorderColor($expected); self::assertEquals($expected, $object->getBorderColor()); } + + /** + * Test set/get bgColor. + */ + public function testSetGetBgColor(): void + { + $expected = 'blue'; + $object = new TextBox(); + $object->setBgColor($expected); + self::assertEquals($expected, $object->getBgColor()); + } } From 050802bdb5a60980d65a50614c0fed0afb73a401 Mon Sep 17 00:00:00 2001 From: hazington Date: Tue, 3 Jan 2023 23:38:08 +0100 Subject: [PATCH 082/246] Removed @return void as not compatible with projects coding standard. --- src/PhpWord/Writer/Word2007/Element/TextBox.php | 2 -- src/PhpWord/Writer/Word2007/Style/TextBox.php | 9 ++------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/PhpWord/Writer/Word2007/Element/TextBox.php b/src/PhpWord/Writer/Word2007/Element/TextBox.php index 18fef7a653..0efc50f917 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Element/TextBox.php @@ -25,8 +25,6 @@ class TextBox extends Image { /** * Write element. - * - * @return void */ public function write(): void { diff --git a/src/PhpWord/Writer/Word2007/Style/TextBox.php b/src/PhpWord/Writer/Word2007/Style/TextBox.php index 89dc4a395b..91361c9fbe 100644 --- a/src/PhpWord/Writer/Word2007/Style/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Style/TextBox.php @@ -2,16 +2,13 @@ /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. - * * PHPWord is free software distributed under the terms of the GNU Lesser * General Public License version 3 as published by the Free Software Foundation. - * * For the full copyright and license information, please read the LICENSE * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -28,12 +25,11 @@ class TextBox extends Frame { /** * Writer inner margin. - * @return void */ public function writeInnerMargin(): void { $style = $this->getStyle(); - if (!$style instanceof TextBoxStyle || !$style->hasInnerMargins()) { + if (! $style instanceof TextBoxStyle || ! $style->hasInnerMargins()) { return; } @@ -45,12 +41,11 @@ public function writeInnerMargin(): void /** * Writer border. - * @return void */ public function writeBorder(): void { $style = $this->getStyle(); - if (!$style instanceof TextBoxStyle) { + if (! $style instanceof TextBoxStyle) { return; } $xmlWriter = $this->getXmlWriter(); From 0f6fbf2b11c13988d9feaefe51050e9d4136b862 Mon Sep 17 00:00:00 2001 From: hazington Date: Tue, 3 Jan 2023 23:44:51 +0100 Subject: [PATCH 083/246] Fixed several CS-Fixer issues --- src/PhpWord/Style/TextBox.php | 55 +++------------ .../Writer/Word2007/Element/TextBox.php | 5 +- src/PhpWord/Writer/Word2007/Style/TextBox.php | 5 +- tests/PhpWordTests/Style/TextBoxTest.php | 69 ++++++++++--------- 4 files changed, 51 insertions(+), 83 deletions(-) diff --git a/src/PhpWord/Style/TextBox.php b/src/PhpWord/Style/TextBox.php index 68b516b1aa..341d93068f 100644 --- a/src/PhpWord/Style/TextBox.php +++ b/src/PhpWord/Style/TextBox.php @@ -9,6 +9,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -72,19 +73,14 @@ class TextBox extends Image /** * Set background color. - * - * @param null|string $value - * @return void */ - public function setBgColor(string $value = null): void + public function setBgColor(?string $value = null): void { $this->bgColor = $value; } /** * Get background color. - * - * @return null|string */ public function getBgColor(): ?string { @@ -93,19 +89,14 @@ public function getBgColor(): ?string /** * Set margin top. - * - * @param null|int $value - * @return void */ - public function setInnerMarginTop(int $value = null): void + public function setInnerMarginTop(?int $value = null): void { $this->innerMarginTop = $value; } /** * Get margin top. - * - * @return null|int */ public function getInnerMarginTop(): ?int { @@ -114,19 +105,14 @@ public function getInnerMarginTop(): ?int /** * Set margin left. - * - * @param null|int $value - * @return void */ - public function setInnerMarginLeft(int $value = null): void + public function setInnerMarginLeft(?int $value = null): void { $this->innerMarginLeft = $value; } /** * Get margin left. - * - * @return null|int */ public function getInnerMarginLeft(): ?int { @@ -135,19 +121,14 @@ public function getInnerMarginLeft(): ?int /** * Set margin right. - * - * @param null|int $value - * @return void */ - public function setInnerMarginRight(int $value = null): void + public function setInnerMarginRight(?int $value = null): void { $this->innerMarginRight = $value; } /** * Get margin right. - * - * @return null|int */ public function getInnerMarginRight(): ?int { @@ -156,19 +137,14 @@ public function getInnerMarginRight(): ?int /** * Set margin bottom. - * - * @param null|int $value - * @return void */ - public function setInnerMarginBottom(int $value = null): void + public function setInnerMarginBottom(?int $value = null): void { $this->innerMarginBottom = $value; } /** * Get margin bottom. - * - * @return null|int */ public function getInnerMarginBottom(): ?int { @@ -179,9 +155,8 @@ public function getInnerMarginBottom(): ?int * Set TLRB cell margin. * * @param null|int $value Margin in twips - * @return void */ - public function setInnerMargin(int $value = null): void + public function setInnerMargin(?int $value = null): void { $this->setInnerMarginTop($value); $this->setInnerMarginLeft($value); @@ -201,8 +176,6 @@ public function getInnerMargin(): array /** * Has inner margin? - * - * @return bool */ public function hasInnerMargins(): bool { @@ -222,38 +195,30 @@ public function hasInnerMargins(): bool * Set border size. * * @param null|int $value Size in points - * @return void */ - public function setBorderSize(int $value = null): void + public function setBorderSize(?int $value = null): void { $this->borderSize = $value; } /** * Get border size. - * - * @return int */ - public function getBorderSize(): int + public function getBorderSize(): ?int { return $this->borderSize; } /** * Set border color. - * - * @param null|string $value - * @return void */ - public function setBorderColor(string $value = null): void + public function setBorderColor(?string $value = null): void { $this->borderColor = $value; } /** * Get border color. - * - * @return null|string */ public function getBorderColor(): ?string { diff --git a/src/PhpWord/Writer/Word2007/Element/TextBox.php b/src/PhpWord/Writer/Word2007/Element/TextBox.php index 0efc50f917..ff94094de7 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Element/TextBox.php @@ -9,6 +9,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -30,13 +31,13 @@ public function write(): void { $xmlWriter = $this->getXmlWriter(); $element = $this->getElement(); - if (! $element instanceof \PhpOffice\PhpWord\Element\TextBox) { + if (!$element instanceof \PhpOffice\PhpWord\Element\TextBox) { return; } $style = $element->getStyle(); $styleWriter = new TextBoxStyleWriter($xmlWriter, $style); - if (! $this->withoutP) { + if (!$this->withoutP) { $xmlWriter->startElement('w:p'); $styleWriter->writeAlignment(); } diff --git a/src/PhpWord/Writer/Word2007/Style/TextBox.php b/src/PhpWord/Writer/Word2007/Style/TextBox.php index 91361c9fbe..d5ccf7a83b 100644 --- a/src/PhpWord/Writer/Word2007/Style/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Style/TextBox.php @@ -9,6 +9,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -29,7 +30,7 @@ class TextBox extends Frame public function writeInnerMargin(): void { $style = $this->getStyle(); - if (! $style instanceof TextBoxStyle || ! $style->hasInnerMargins()) { + if (!$style instanceof TextBoxStyle || !$style->hasInnerMargins()) { return; } @@ -45,7 +46,7 @@ public function writeInnerMargin(): void public function writeBorder(): void { $style = $this->getStyle(); - if (! $style instanceof TextBoxStyle) { + if (!$style instanceof TextBoxStyle) { return; } $xmlWriter = $this->getXmlWriter(); diff --git a/tests/PhpWordTests/Style/TextBoxTest.php b/tests/PhpWordTests/Style/TextBoxTest.php index 76688377e2..284829aaba 100644 --- a/tests/PhpWordTests/Style/TextBoxTest.php +++ b/tests/PhpWordTests/Style/TextBoxTest.php @@ -9,6 +9,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord + * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -35,24 +36,24 @@ public function testSetGetNormal(): void $object = new TextBox(); $properties = [ - 'width' => 200, - 'height' => 200, - 'alignment' => Jc::START, - 'marginTop' => 240, - 'marginLeft' => 240, - 'wrappingStyle' => 'inline', - 'positioning' => 'absolute', - 'posHorizontal' => 'center', - 'posVertical' => 'top', - 'posHorizontalRel' => 'margin', - 'posVerticalRel' => 'page', - 'innerMarginTop' => '5', - 'innerMarginRight' => '5', + 'width' => 200, + 'height' => 200, + 'alignment' => Jc::START, + 'marginTop' => 240, + 'marginLeft' => 240, + 'wrappingStyle' => 'inline', + 'positioning' => 'absolute', + 'posHorizontal' => 'center', + 'posVertical' => 'top', + 'posHorizontalRel' => 'margin', + 'posVerticalRel' => 'page', + 'innerMarginTop' => '5', + 'innerMarginRight' => '5', 'innerMarginBottom' => '5', - 'innerMarginLeft' => '5', - 'borderSize' => '2', - 'borderColor' => 'red', - 'bgColor' => 'blue', + 'innerMarginLeft' => '5', + 'borderSize' => '2', + 'borderColor' => 'red', + 'bgColor' => 'blue', ]; foreach ($properties as $key => $value) { $set = "set{$key}"; @@ -70,24 +71,24 @@ public function testSetStyleValue(): void $object = new TextBox(); $properties = [ - 'width' => 200, - 'height' => 200, - 'alignment' => Jc::START, - 'marginTop' => 240, - 'marginLeft' => 240, - 'wrappingStyle' => 'inline', - 'positioning' => 'absolute', - 'posHorizontal' => 'center', - 'posVertical' => 'top', - 'posHorizontalRel' => 'margin', - 'posVerticalRel' => 'page', - 'innerMarginTop' => '5', - 'innerMarginRight' => '5', + 'width' => 200, + 'height' => 200, + 'alignment' => Jc::START, + 'marginTop' => 240, + 'marginLeft' => 240, + 'wrappingStyle' => 'inline', + 'positioning' => 'absolute', + 'posHorizontal' => 'center', + 'posVertical' => 'top', + 'posHorizontalRel' => 'margin', + 'posVerticalRel' => 'page', + 'innerMarginTop' => '5', + 'innerMarginRight' => '5', 'innerMarginBottom' => '5', - 'innerMarginLeft' => '5', - 'borderSize' => '2', - 'borderColor' => 'red', - 'bgColor' => 'blue', + 'innerMarginLeft' => '5', + 'borderSize' => '2', + 'borderColor' => 'red', + 'bgColor' => 'blue', ]; foreach ($properties as $key => $value) { $get = "get{$key}"; From 679a738c426ff498bd1b4319c23ad1ef438d5e10 Mon Sep 17 00:00:00 2001 From: hazington Date: Tue, 3 Jan 2023 23:56:04 +0100 Subject: [PATCH 084/246] Replaced deprecated "assertRegExp" test method by assertMatchesRegularExpression. --- tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php index 98449f3b6d..00582e12ab 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php @@ -408,7 +408,7 @@ public function testWriteImage(): void // behind $element = $doc->getElement('/w:document/w:body/w:p[2]/w:r/w:pict/v:shape'); $style = $element->getAttribute('style'); - self::assertRegExp('/z\-index:\-[0-9]*/', $style); + self::assertMatchesRegularExpression('/z\-index:\-[0-9]*/', $style); // square $element = $doc->getElement('/w:document/w:body/w:p[4]/w:r/w:pict/v:shape/w10:wrap'); From 53d34fd049026752a13183891250bd3d91c482c0 Mon Sep 17 00:00:00 2001 From: hazington Date: Wed, 4 Jan 2023 00:07:39 +0100 Subject: [PATCH 085/246] Address the CI coverage issue for the regex match assertion. --- .../Writer/Word2007/Part/DocumentTest.php | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php index 00582e12ab..be8f8cc4bf 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php @@ -2,10 +2,8 @@ /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. - * * PHPWord is free software distributed under the terms of the GNU Lesser * General Public License version 3 as published by the Free Software Foundation. - * * For the full copyright and license information, please read the LICENSE * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. @@ -61,11 +59,11 @@ public function testWriteCustomProps(): void $doc = TestHelperDOCX::getDocument($phpWord); self::assertNotNull($doc); -// $this->assertTrue($doc->elementExists('/Properties/property[name="key1"]/vt:lpwstr')); -// $this->assertTrue($doc->elementExists('/Properties/property[name="key2"]/vt:bool')); -// $this->assertTrue($doc->elementExists('/Properties/property[name="key3"]/vt:i4')); -// $this->assertTrue($doc->elementExists('/Properties/property[name="key4"]/vt:r8')); -// $this->assertTrue($doc->elementExists('/Properties/property[name="key5"]/vt:lpwstr')); + // $this->assertTrue($doc->elementExists('/Properties/property[name="key1"]/vt:lpwstr')); + // $this->assertTrue($doc->elementExists('/Properties/property[name="key2"]/vt:bool')); + // $this->assertTrue($doc->elementExists('/Properties/property[name="key3"]/vt:i4')); + // $this->assertTrue($doc->elementExists('/Properties/property[name="key4"]/vt:r8')); + // $this->assertTrue($doc->elementExists('/Properties/property[name="key5"]/vt:lpwstr')); } /** @@ -408,7 +406,13 @@ public function testWriteImage(): void // behind $element = $doc->getElement('/w:document/w:body/w:p[2]/w:r/w:pict/v:shape'); $style = $element->getAttribute('style'); - self::assertMatchesRegularExpression('/z\-index:\-[0-9]*/', $style); + + // Try to address CI coverage issue for PHP 7.1 and 7.2 when using regex match assertions + if (method_exists(static::class, 'assertRegExp')) { + self::assertRegExp('/z\-index:\-[0-9]*/', $style); + } else { + self::assertMatchesRegularExpression('/z\-index:\-[0-9]*/', $style); + } // square $element = $doc->getElement('/w:document/w:body/w:p[4]/w:r/w:pict/v:shape/w10:wrap'); @@ -551,7 +555,13 @@ public function testWriteDefaultColor(): void $cell->addText('Test'); $doc = TestHelperDOCX::getDocument($phpWord); - self::assertEquals(Cell::DEFAULT_BORDER_COLOR, $doc->getElementAttribute('/w:document/w:body/w:tbl/w:tr/w:tc/w:tcPr/w:tcBorders/w:top', 'w:color')); + self::assertEquals( + Cell::DEFAULT_BORDER_COLOR, + $doc->getElementAttribute( + '/w:document/w:body/w:tbl/w:tr/w:tc/w:tcPr/w:tcBorders/w:top', + 'w:color' + ) + ); } /** From ed8d9ff420d4ef52c70994ad6448d961298111ac Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Thu, 5 Jan 2023 21:53:50 +0100 Subject: [PATCH 086/246] Fixed some stylelint --- src/PhpWord/Reader/Word2007/AbstractPart.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 0d8a7e1731..6e41c3b704 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -327,8 +327,8 @@ protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, Abstrac $element->setChangeInfo($type, $author, $date); } } - } elseif ($node->nodeName=='w:softHyphen') { - $element=$parent->addText("\u{200c}", $fontStyle, $paragraphStyle); + } elseif ($node->nodeName == 'w:softHyphen') { + $element = $parent->addText("\u{200c}", $fontStyle, $paragraphStyle); } } From ef99fac8e1a69989c7a3db19b3be0ba3eef8e094 Mon Sep 17 00:00:00 2001 From: Yohann Tilotti Date: Fri, 6 Jan 2023 16:26:34 +0100 Subject: [PATCH 087/246] Add support table row height when importing HTML (#2350) * Add support table row height when importing HTML * fix space * fix phpcsfixer * Add test table row height * Fix xpath test table row height * Fix attribute first test table row height * Fix $cValue Co-authored-by: Progi1984 * Fix css * Fix test on pt Co-authored-by: Progi1984 --- src/PhpWord/Shared/Html.php | 11 +++++- tests/PhpWordTests/Shared/HtmlTest.php | 52 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index b0fcfb9e59..0b35158507 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -444,7 +444,11 @@ protected static function parseRow($node, $element, &$styles) $rowStyles['tblHeader'] = true; } - return $element->addRow(null, $rowStyles); + // set cell height to control row heights + $height = $rowStyles['height'] ?? null; + unset($rowStyles['height']); // would not apply + + return $element->addRow($height, $rowStyles); } /** @@ -808,6 +812,11 @@ protected static function parseStyleDeclarations(array $selectors, array $styles $styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::AUTO; } + break; + case 'height': + $styles['height'] = Converter::cssToTwip($value); + $styles['exactHeight'] = true; + break; case 'border': case 'border-top': diff --git a/tests/PhpWordTests/Shared/HtmlTest.php b/tests/PhpWordTests/Shared/HtmlTest.php index 8da6ccc61e..7340b219ab 100644 --- a/tests/PhpWordTests/Shared/HtmlTest.php +++ b/tests/PhpWordTests/Shared/HtmlTest.php @@ -464,6 +464,58 @@ public function testParseTableAndCellWidth(): void self::assertEquals('dxa', $doc->getElement($xpath)->getAttribute('w:type')); } + /** + * Parse heights in rows, which also allows for controlling column height. + */ + public function testParseTableRowHeight(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection([ + 'orientation' => \PhpOffice\PhpWord\Style\Section::ORIENTATION_LANDSCAPE, + ]); + + $html = << + + 100px + + + 200pt + + + + + + + +
    300px
    + + + +HTML; + + Html::addHtml($section, $html); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + // elementExists($xpath)); + self::assertEquals(4000, $doc->getElement($xpath)->getAttribute('w:val')); + self::assertEquals('exact', $doc->getElement($xpath)->getAttribute('w:hRule')); + + // Co-authored-by: Progi1984 --- src/PhpWord/Settings.php | 172 ++++++++++------------------ tests/PhpWordTests/SettingsTest.php | 13 ++- 2 files changed, 68 insertions(+), 117 deletions(-) diff --git a/src/PhpWord/Settings.php b/src/PhpWord/Settings.php index 7b1f456eca..22d067b0b8 100644 --- a/src/PhpWord/Settings.php +++ b/src/PhpWord/Settings.php @@ -2,10 +2,8 @@ /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. - * * PHPWord is free software distributed under the terms of the GNU Lesser * General Public License version 3 as published by the Free Software Foundation. - * * For the full copyright and license information, please read the LICENSE * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. @@ -29,48 +27,46 @@ class Settings * * @const string */ - const ZIPARCHIVE = 'ZipArchive'; - const PCLZIP = 'PclZip'; - const OLD_LIB = \PhpOffice\PhpWord\Shared\ZipArchive::class; // @deprecated 0.11 + public const ZIPARCHIVE = 'ZipArchive'; + public const PCLZIP = 'PclZip'; + public const OLD_LIB = \PhpOffice\PhpWord\Shared\ZipArchive::class; // @deprecated 0.11 /** * PDF rendering libraries. * * @const string */ - const PDF_RENDERER_DOMPDF = 'DomPDF'; - const PDF_RENDERER_TCPDF = 'TCPDF'; - const PDF_RENDERER_MPDF = 'MPDF'; + public const PDF_RENDERER_DOMPDF = 'DomPDF'; + public const PDF_RENDERER_TCPDF = 'TCPDF'; + public const PDF_RENDERER_MPDF = 'MPDF'; /** * Measurement units multiplication factor. - * * Applied to: * - Section: margins, header/footer height, gutter, column spacing * - Tab: position * - Indentation: left, right, firstLine, hanging - * - Spacing: before, after + * - Spacing: before, after. * * @const string */ - const UNIT_TWIP = 'twip'; // = 1/20 point - const UNIT_CM = 'cm'; - const UNIT_MM = 'mm'; - const UNIT_INCH = 'inch'; - const UNIT_POINT = 'point'; // = 1/72 inch - const UNIT_PICA = 'pica'; // = 1/6 inch = 12 points + public const UNIT_TWIP = 'twip'; // = 1/20 point + public const UNIT_CM = 'cm'; + public const UNIT_MM = 'mm'; + public const UNIT_INCH = 'inch'; + public const UNIT_POINT = 'point'; // = 1/72 inch + public const UNIT_PICA = 'pica'; // = 1/6 inch = 12 points /** * Default font settings. - * * OOXML defined font size values in halfpoints, i.e. twice of what PhpWord * use, and the conversion will be conducted during XML writing. */ - const DEFAULT_FONT_NAME = 'Arial'; - const DEFAULT_FONT_SIZE = 10; - const DEFAULT_FONT_COLOR = '000000'; - const DEFAULT_FONT_CONTENT_TYPE = 'default'; // default|eastAsia|cs - const DEFAULT_PAPER = 'A4'; + public const DEFAULT_FONT_NAME = 'Arial'; + public const DEFAULT_FONT_SIZE = 10; + public const DEFAULT_FONT_COLOR = '000000'; + public const DEFAULT_FONT_CONTENT_TYPE = 'default'; // default|eastAsia|cs + public const DEFAULT_PAPER = 'A4'; /** * Compatibility option for XMLWriter. @@ -89,21 +85,21 @@ class Settings /** * Name of the external Library used for rendering PDF files. * - * @var string + * @var null|string */ private static $pdfRendererName; /** * Directory Path to the external Library used for rendering PDF files. * - * @var string + * @var null|string */ private static $pdfRendererPath; /** * Measurement unit. * - * @var float|int + * @var string */ private static $measurementUnit = self::UNIT_TWIP; @@ -117,7 +113,7 @@ class Settings /** * Default font size. * - * @var int + * @var float|int */ private static $defaultFontSize = self::DEFAULT_FONT_SIZE; @@ -148,23 +144,17 @@ class Settings * * @return bool Compatibility */ - public static function hasCompatibility() + public static function hasCompatibility(): bool { return self::$xmlWriterCompatibility; } /** * Set the compatibility option used by the XMLWriter. - * - * This sets the setIndent and setIndentString for better compatibility - * - * @param bool $compatibility - * - * @return bool + * This sets the setIndent and setIndentString for better compatibility. */ - public static function setCompatibility($compatibility) + public static function setCompatibility(bool $compatibility): bool { - $compatibility = (bool) $compatibility; self::$xmlWriterCompatibility = $compatibility; return true; @@ -172,22 +162,16 @@ public static function setCompatibility($compatibility) /** * Get zip handler class. - * - * @return string */ - public static function getZipClass() + public static function getZipClass(): string { return self::$zipClass; } /** * Set zip handler class. - * - * @param string $zipClass - * - * @return bool */ - public static function setZipClass($zipClass) + public static function setZipClass(string $zipClass): bool { if (in_array($zipClass, [self::PCLZIP, self::ZIPARCHIVE, self::OLD_LIB])) { self::$zipClass = $zipClass; @@ -201,12 +185,9 @@ public static function setZipClass($zipClass) /** * Set details of the external library for rendering PDF files. * - * @param string $libraryName - * @param string $libraryBaseDir - * * @return bool Success or failure */ - public static function setPdfRenderer($libraryName, $libraryBaseDir) + public static function setPdfRenderer(string $libraryName, string $libraryBaseDir): bool { if (!self::setPdfRendererName($libraryName)) { return false; @@ -217,22 +198,16 @@ public static function setPdfRenderer($libraryName, $libraryBaseDir) /** * Return the PDF Rendering Library. - * - * @return string */ - public static function getPdfRendererName() + public static function getPdfRendererName(): ?string { return self::$pdfRendererName; } /** * Identify the external library to use for rendering PDF files. - * - * @param string $libraryName - * - * @return bool */ - public static function setPdfRendererName($libraryName) + public static function setPdfRendererName(?string $libraryName): bool { $pdfRenderers = [self::PDF_RENDERER_DOMPDF, self::PDF_RENDERER_TCPDF, self::PDF_RENDERER_MPDF]; if (!in_array($libraryName, $pdfRenderers)) { @@ -245,10 +220,8 @@ public static function setPdfRendererName($libraryName) /** * Return the directory path to the PDF Rendering Library. - * - * @return string */ - public static function getPdfRendererPath() + public static function getPdfRendererPath(): ?string { return self::$pdfRendererPath; } @@ -256,11 +229,11 @@ public static function getPdfRendererPath() /** * Location of external library to use for rendering PDF files. * - * @param string $libraryBaseDir Directory path to the library's base folder + * @param null|string $libraryBaseDir Directory path to the library's base folder * * @return bool Success or failure */ - public static function setPdfRendererPath($libraryBaseDir) + public static function setPdfRendererPath(?string $libraryBaseDir): bool { if (!$libraryBaseDir || false === file_exists($libraryBaseDir) || false === is_readable($libraryBaseDir)) { return false; @@ -272,25 +245,25 @@ public static function setPdfRendererPath($libraryBaseDir) /** * Get measurement unit. - * - * @return string */ - public static function getMeasurementUnit() + public static function getMeasurementUnit(): string { return self::$measurementUnit; } /** * Set measurement unit. - * - * @param string $value - * - * @return bool */ - public static function setMeasurementUnit($value) + public static function setMeasurementUnit(string $value): bool { - $units = [self::UNIT_TWIP, self::UNIT_CM, self::UNIT_MM, self::UNIT_INCH, - self::UNIT_POINT, self::UNIT_PICA, ]; + $units = [ + self::UNIT_TWIP, + self::UNIT_CM, + self::UNIT_MM, + self::UNIT_INCH, + self::UNIT_POINT, + self::UNIT_PICA, + ]; if (!in_array($value, $units)) { return false; } @@ -302,11 +275,11 @@ public static function setMeasurementUnit($value) /** * Sets the user defined path to temporary directory. * - * @since 0.12.0 - * * @param string $tempDir The user defined path to temporary directory + * + * @since 0.12.0 */ - public static function setTempDir($tempDir): void + public static function setTempDir(string $tempDir): void { self::$tempDir = $tempDir; } @@ -315,10 +288,8 @@ public static function setTempDir($tempDir): void * Returns path to temporary directory. * * @since 0.12.0 - * - * @return string */ - public static function getTempDir() + public static function getTempDir(): string { if (!empty(self::$tempDir)) { $tempDir = self::$tempDir; @@ -331,44 +302,34 @@ public static function getTempDir() /** * @since 0.13.0 - * - * @return bool */ - public static function isOutputEscapingEnabled() + public static function isOutputEscapingEnabled(): bool { return self::$outputEscapingEnabled; } /** * @since 0.13.0 - * - * @param bool $outputEscapingEnabled */ - public static function setOutputEscapingEnabled($outputEscapingEnabled): void + public static function setOutputEscapingEnabled(bool $outputEscapingEnabled): void { self::$outputEscapingEnabled = $outputEscapingEnabled; } /** * Get default font name. - * - * @return string */ - public static function getDefaultFontName() + public static function getDefaultFontName(): string { return self::$defaultFontName; } /** * Set default font name. - * - * @param string $value - * - * @return bool */ - public static function setDefaultFontName($value) + public static function setDefaultFontName(string $value): bool { - if (is_string($value) && trim($value) !== '') { + if (trim($value) !== '') { self::$defaultFontName = $value; return true; @@ -380,7 +341,7 @@ public static function setDefaultFontName($value) /** * Get default font size. * - * @return int + * @return float|int */ public static function getDefaultFontSize() { @@ -390,14 +351,11 @@ public static function getDefaultFontSize() /** * Set default font size. * - * @param int $value - * - * @return bool + * @param null|float|int $value */ - public static function setDefaultFontSize($value) + public static function setDefaultFontSize($value): bool { - $value = (int) $value; - if ($value > 0) { + if ((is_int($value) || is_float($value)) && (int) $value > 0) { self::$defaultFontSize = $value; return true; @@ -408,12 +366,8 @@ public static function setDefaultFontSize($value) /** * Load setting from phpword.yml or phpword.yml.dist. - * - * @param string $filename - * - * @return array */ - public static function loadConfig($filename = null) + public static function loadConfig(?string $filename = null): array { // Get config file $configFile = null; @@ -455,24 +409,18 @@ public static function loadConfig($filename = null) /** * Get default paper. - * - * @return string */ - public static function getDefaultPaper() + public static function getDefaultPaper(): string { return self::$defaultPaper; } /** * Set default paper. - * - * @param string $value - * - * @return bool */ - public static function setDefaultPaper($value) + public static function setDefaultPaper(string $value): bool { - if (is_string($value) && trim($value) !== '') { + if (trim($value) !== '') { self::$defaultPaper = $value; return true; diff --git a/tests/PhpWordTests/SettingsTest.php b/tests/PhpWordTests/SettingsTest.php index bf4dd4bf52..58490c4a4f 100644 --- a/tests/PhpWordTests/SettingsTest.php +++ b/tests/PhpWordTests/SettingsTest.php @@ -2,10 +2,8 @@ /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. - * * PHPWord is free software distributed under the terms of the GNU Lesser * General Public License version 3 as published by the Free Software Foundation. - * * For the full copyright and license information, please read the LICENSE * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. @@ -19,15 +17,15 @@ use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Settings; +use PHPUnit\Framework\TestCase; /** * Test class for PhpOffice\PhpWord\Settings. * * @coversDefaultClass \PhpOffice\PhpWord\Settings - * * @runTestsInSeparateProcesses */ -class SettingsTest extends \PHPUnit\Framework\TestCase +class SettingsTest extends TestCase { private $compatibility; @@ -151,7 +149,6 @@ public function testPhpTempDirIsUsedByDefault(): void /** * @covers ::getTempDir * @covers ::setTempDir - * * @depends testPhpTempDirIsUsedByDefault */ public function testTempDirCanBeSet(): void @@ -189,6 +186,12 @@ public function testSetGetDefaultFontSize(): void self::assertEquals(12, Settings::getDefaultFontSize()); self::assertFalse(Settings::setDefaultFontSize(null)); self::assertEquals(12, Settings::getDefaultFontSize()); + self::assertTrue(Settings::setDefaultFontSize(12.5)); + self::assertEquals(12.5, Settings::getDefaultFontSize()); + self::assertFalse(Settings::setDefaultFontSize(0.5)); + self::assertEquals(12.5, Settings::getDefaultFontSize()); + self::assertFalse(Settings::setDefaultFontSize(0)); + self::assertEquals(12.5, Settings::getDefaultFontSize()); } /** From 08064480ea915a7283a5a09ba68ad04869cb259e Mon Sep 17 00:00:00 2001 From: Ahmad Syamim Date: Sun, 8 Jan 2023 16:39:08 +0800 Subject: [PATCH 089/246] Update recipes.rst (#2367) --- docs/recipes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/recipes.rst b/docs/recipes.rst index 5042cdedc6..b470d28615 100644 --- a/docs/recipes.rst +++ b/docs/recipes.rst @@ -29,7 +29,7 @@ Use ``php://output`` as the filename. .. code-block:: php $phpWord = new \PhpOffice\PhpWord\PhpWord(); - $section = $phpWord->createSection(); + $section = $phpWord->addSection(); $section->addText('Hello World!'); $file = 'HelloWorld.docx'; header("Content-Description: File Transfer"); From 30c101d328cb3762e00fca288d79f92d1c3b545b Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Tue, 30 May 2023 12:30:26 +0700 Subject: [PATCH 090/246] Lock all dependencies We must have `composer.lock` as part of our repository. Otherwise, the tools used for development change and break things unexpectedly. Currently, this is the case with PHPUnit 10 that introduces quite a few breaking changes. We cannot `composer install` and hope that we will get a set of compatible dependencies. Instead, we must lock our tools and upgrade them only when we want/need to upgrade them specifically, in a dedicated commit, and not part of a totally unrelated work, because it just so happenned that PHPUnit released something. `composer.lock` is based on the oldest PHP version that is officially supported by PHP core. Currently, that is 8.0. This typically gives us compatibility out of the box for 8.0, 8.1 and 8.2 with a single lock file. EOL PHP versions, that we unfortunately keep supporting in PHPWord, are "the special cases", and as such they will generate a new lock files in CI, because we cannot have a single lock files that spread over such as long time (almost 4 years for PHP 7.1) with major breaking change in the language in between. --- .github/workflows/ci.yml | 16 +- .gitignore | 1 - composer.json | 5 + composer.lock | 4922 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 4938 insertions(+), 6 deletions(-) create mode 100644 composer.lock diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b8e8cd16dd..82dd88b567 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: php-version: - - "7.1" + - "7.1.3" - "7.2" - "7.3" - "7.4" @@ -39,6 +39,10 @@ jobs: key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- + - name: Remove lock for old EOL PHP versions + if: matrix.php-version == '7.1.3' || matrix.php-version == '7.2' || matrix.php-version == '7.3' || matrix.php-version == '7.4' + run: rm composer.lock && composer config platform.php ${{ matrix.php-version }} + - name: Install dependencies run: composer install --no-progress --prefer-dist --optimize-autoloader @@ -63,7 +67,7 @@ jobs: - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib coverage: none tools: cs2pr @@ -90,11 +94,13 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib coverage: pcov @@ -115,5 +121,5 @@ jobs: - name: Coverage run: | ./vendor/bin/phpunit --coverage-clover coverage-clover.xml - curl -LO https://scrutinizer-ci.com/ocular.phar - php ocular.phar code-coverage:upload --format=php-clover coverage-clover.xml + composer global require scrutinizer/ocular + ~/.composer/vendor/bin/ocular code-coverage:upload --format=php-clover coverage-clover.xml diff --git a/.gitignore b/.gitignore index f5f6f7eb81..7e80be0d15 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ Desktop.ini _build /build phpunit.xml -composer.lock composer.phar vendor /report diff --git a/composer.json b/composer.json index 32d2711a31..0a16d01acf 100644 --- a/composer.json +++ b/composer.json @@ -57,6 +57,11 @@ "check": "Runs PHP CheckStyle and PHP Mess detector", "fix": "Fixes issues found by PHP-CS" }, + "config": { + "platform": { + "php": "8.0" + } + }, "require": { "php": "^7.1|^8.0", "ext-dom": "*", diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000000..8d5e5a58ab --- /dev/null +++ b/composer.lock @@ -0,0 +1,4922 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "941205ed12dc2bc633e2125181dc60be", + "packages": [ + { + "name": "laminas/laminas-escaper", + "version": "2.12.0", + "source": { + "type": "git", + "url": "https://github.com/laminas/laminas-escaper.git", + "reference": "ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490", + "reference": "ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-mbstring": "*", + "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0" + }, + "conflict": { + "zendframework/zend-escaper": "*" + }, + "require-dev": { + "infection/infection": "^0.26.6", + "laminas/laminas-coding-standard": "~2.4.0", + "maglnet/composer-require-checker": "^3.8.0", + "phpunit/phpunit": "^9.5.18", + "psalm/plugin-phpunit": "^0.17.0", + "vimeo/psalm": "^4.22.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Laminas\\Escaper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs", + "homepage": "https://laminas.dev/", + "keywords": [ + "escaper", + "laminas" + ], + "support": { + "chat": "https://laminas.dev/chat", + "docs": "https://docs.laminas.dev/laminas-escaper/", + "forum": "https://discourse.laminas.dev/", + "issues": "https://github.com/laminas/laminas-escaper/issues", + "rss": "https://github.com/laminas/laminas-escaper/releases.atom", + "source": "https://github.com/laminas/laminas-escaper" + }, + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2022-10-10T10:11:09+00:00" + } + ], + "packages-dev": [ + { + "name": "composer/pcre", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560", + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be/" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/1.0.1" + }, + "funding": [ + { + "url": "https://packagist.com/", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-01-21T20:24:37+00:00" + }, + { + "name": "composer/semver", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de/" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be/" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl/" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com/", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-04-01T19:23:25+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "2.0.5", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/9e36aeed4616366d2b690bdce11f71e9178c579a", + "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a", + "shasum": "" + }, + "require": { + "composer/pcre": "^1", + "php": "^5.3.2 || ^7.0 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/2.0.5" + }, + "funding": [ + { + "url": "https://packagist.com/", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-02-24T20:20:32+00:00" + }, + { + "name": "doctrine/annotations", + "version": "1.14.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", + "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^1 || ^2", + "ext-tokenizer": "*", + "php": "^7.1 || ^8.0", + "psr/cache": "^1 || ^2 || ^3" + }, + "require-dev": { + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "~1.4.10 || ^1.8.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6", + "vimeo/psalm": "^4.10" + }, + "suggest": { + "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "https://www.doctrine-project.org/projects/annotations.html", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "support": { + "issues": "https://github.com/doctrine/annotations/issues", + "source": "https://github.com/doctrine/annotations/tree/1.14.3" + }, + "time": "2023-02-01T09:20:38+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "8cffffb2218e01f3b370bf763e00e81697725259" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/8cffffb2218e01f3b370bf763e00e81697725259", + "reference": "8cffffb2218e01f3b370bf763e00e81697725259", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5|^8.5|^9.5", + "psr/log": "^1|^2|^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v1.1.0" + }, + "time": "2023-05-29T18:55:17+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^11", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-12-30T00:15:36+00:00" + }, + { + "name": "doctrine/lexer", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/2.1.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2022-12-14T08:49:07+00:00" + }, + { + "name": "dompdf/dompdf", + "version": "v2.0.3", + "source": { + "type": "git", + "url": "https://github.com/dompdf/dompdf.git", + "reference": "e8d2d5e37e8b0b30f0732a011295ab80680d7e85" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/e8d2d5e37e8b0b30f0732a011295ab80680d7e85", + "reference": "e8d2d5e37e8b0b30f0732a011295ab80680d7e85", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "masterminds/html5": "^2.0", + "phenx/php-font-lib": ">=0.5.4 <1.0.0", + "phenx/php-svg-lib": ">=0.3.3 <1.0.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "ext-json": "*", + "ext-zip": "*", + "mockery/mockery": "^1.3", + "phpunit/phpunit": "^7.5 || ^8 || ^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "suggest": { + "ext-gd": "Needed to process images", + "ext-gmagick": "Improves image processing performance", + "ext-imagick": "Improves image processing performance", + "ext-zlib": "Needed for pdf stream compression" + }, + "type": "library", + "autoload": { + "psr-4": { + "Dompdf\\": "src/" + }, + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1" + ], + "authors": [ + { + "name": "The Dompdf Community", + "homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md" + } + ], + "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", + "homepage": "https://github.com/dompdf/dompdf", + "support": { + "issues": "https://github.com/dompdf/dompdf/issues", + "source": "https://github.com/dompdf/dompdf/tree/v2.0.3" + }, + "time": "2023-02-07T12:51:48+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", + "reference": "47177af1cfb9dab5d1cc4daf91b7179c2efe7fad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/47177af1cfb9dab5d1cc4daf91b7179c2efe7fad", + "reference": "47177af1cfb9dab5d1cc4daf91b7179c2efe7fad", + "shasum": "" + }, + "require": { + "composer/semver": "^3.2", + "composer/xdebug-handler": "^2.0", + "doctrine/annotations": "^1.12", + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^7.2.5 || ^8.0", + "php-cs-fixer/diff": "^2.0", + "symfony/console": "^4.4.20 || ^5.1.3 || ^6.0", + "symfony/event-dispatcher": "^4.4.20 || ^5.0 || ^6.0", + "symfony/filesystem": "^4.4.20 || ^5.0 || ^6.0", + "symfony/finder": "^4.4.20 || ^5.0 || ^6.0", + "symfony/options-resolver": "^4.4.20 || ^5.0 || ^6.0", + "symfony/polyfill-mbstring": "^1.23", + "symfony/polyfill-php80": "^1.23", + "symfony/polyfill-php81": "^1.23", + "symfony/process": "^4.4.20 || ^5.0 || ^6.0", + "symfony/stopwatch": "^4.4.20 || ^5.0 || ^6.0" + }, + "require-dev": { + "justinrainbow/json-schema": "^5.2", + "keradus/cli-executor": "^1.5", + "mikey179/vfsstream": "^1.6.8", + "php-coveralls/php-coveralls": "^2.5.2", + "php-cs-fixer/accessible-object": "^1.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", + "phpspec/prophecy": "^1.15", + "phpspec/prophecy-phpunit": "^1.1 || ^2.0", + "phpunit/phpunit": "^8.5.21 || ^9.5", + "phpunitgoodpractices/polyfill": "^1.5", + "phpunitgoodpractices/traits": "^1.9.1", + "symfony/phpunit-bridge": "^5.2.4 || ^6.0", + "symfony/yaml": "^4.4.20 || ^5.0 || ^6.0" + }, + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "support": { + "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", + "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.4.0" + }, + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" + } + ], + "time": "2021-12-11T16:25:08+00:00" + }, + { + "name": "masterminds/html5", + "version": "2.8.0", + "source": { + "type": "git", + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "3c5d5a56d56f48a1ca08a0670f0f80c1dad368f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/3c5d5a56d56f48a1ca08a0670f0f80c1dad368f3", + "reference": "3c5d5a56d56f48a1ca08a0670f0f80c1dad368f3", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", + "keywords": [ + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" + ], + "support": { + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.8.0" + }, + "time": "2023-04-26T07:27:39+00:00" + }, + { + "name": "mpdf/mpdf", + "version": "v8.1.6", + "source": { + "type": "git", + "url": "https://github.com/mpdf/mpdf.git", + "reference": "146c7c1dfd21c826b9d5bbfe3c15e52fd933c90f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mpdf/mpdf/zipball/146c7c1dfd21c826b9d5bbfe3c15e52fd933c90f", + "reference": "146c7c1dfd21c826b9d5bbfe3c15e52fd933c90f", + "shasum": "" + }, + "require": { + "ext-gd": "*", + "ext-mbstring": "*", + "mpdf/psr-log-aware-trait": "^2.0 || ^3.0", + "myclabs/deep-copy": "^1.7", + "paragonie/random_compat": "^1.4|^2.0|^9.99.99", + "php": "^5.6 || ^7.0 || ~8.0.0 || ~8.1.0 || ~8.2.0", + "psr/http-message": "^1.0", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "setasign/fpdi": "^2.1" + }, + "require-dev": { + "mockery/mockery": "^1.3.0", + "mpdf/qrcode": "^1.1.0", + "squizlabs/php_codesniffer": "^3.5.0", + "tracy/tracy": "~2.5", + "yoast/phpunit-polyfills": "^1.0" + }, + "suggest": { + "ext-bcmath": "Needed for generation of some types of barcodes", + "ext-xml": "Needed mainly for SVG manipulation", + "ext-zlib": "Needed for compression of embedded resources, such as fonts" + }, + "type": "library", + "autoload": { + "psr-4": { + "Mpdf\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-only" + ], + "authors": [ + { + "name": "Matěj Humpál", + "role": "Developer, maintainer" + }, + { + "name": "Ian Back", + "role": "Developer (retired)" + } + ], + "description": "PHP library generating PDF files from UTF-8 encoded HTML", + "homepage": "https://mpdf.github.io/", + "keywords": [ + "pdf", + "php", + "utf-8" + ], + "support": { + "docs": "http://mpdf.github.io/", + "issues": "https://github.com/mpdf/mpdf/issues", + "source": "https://github.com/mpdf/mpdf" + }, + "funding": [ + { + "url": "https://www.paypal.me/mpdf", + "type": "custom" + } + ], + "time": "2023-05-03T19:36:43+00:00" + }, + { + "name": "mpdf/psr-log-aware-trait", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/mpdf/psr-log-aware-trait.git", + "reference": "a633da6065e946cc491e1c962850344bb0bf3e78" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mpdf/psr-log-aware-trait/zipball/a633da6065e946cc491e1c962850344bb0bf3e78", + "reference": "a633da6065e946cc491e1c962850344bb0bf3e78", + "shasum": "" + }, + "require": { + "psr/log": "^3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Mpdf\\PsrLogAwareTrait\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Dorison", + "email": "mark@chromatichq.com" + }, + { + "name": "Kristofer Widholm", + "email": "kristofer@chromatichq.com" + } + ], + "description": "Trait to allow support of different psr/log versions.", + "support": { + "issues": "https://github.com/mpdf/psr-log-aware-trait/issues", + "source": "https://github.com/mpdf/psr-log-aware-trait/tree/v3.0.0" + }, + "time": "2023-05-03T06:19:36+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.11.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2023-03-08T13:26:56+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.15.5", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/11e2663a5bc9db5d714eedb4277ee300403b4a9e", + "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.5" + }, + "time": "2023-05-19T20:20:00+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v9.99.100", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", + "shasum": "" + }, + "require": { + "php": ">= 7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com/" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" + }, + "time": "2020-10-15T08:29:30+00:00" + }, + { + "name": "pdepend/pdepend", + "version": "2.14.0", + "source": { + "type": "git", + "url": "https://github.com/pdepend/pdepend.git", + "reference": "1121d4b04af06e33e9659bac3a6741b91cab1de1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pdepend/pdepend/zipball/1121d4b04af06e33e9659bac3a6741b91cab1de1", + "reference": "1121d4b04af06e33e9659bac3a6741b91cab1de1", + "shasum": "" + }, + "require": { + "php": ">=5.3.7", + "symfony/config": "^2.3.0|^3|^4|^5|^6.0", + "symfony/dependency-injection": "^2.3.0|^3|^4|^5|^6.0", + "symfony/filesystem": "^2.3.0|^3|^4|^5|^6.0" + }, + "require-dev": { + "easy-doc/easy-doc": "0.0.0|^1.2.3", + "gregwar/rst": "^1.0", + "phpunit/phpunit": "^4.8.36|^5.7.27", + "squizlabs/php_codesniffer": "^2.0.0" + }, + "bin": [ + "src/bin/pdepend" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "PDepend\\": "src/main/php/PDepend" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Official version of pdepend to be handled with Composer", + "keywords": [ + "PHP Depend", + "PHP_Depend", + "dev", + "pdepend" + ], + "support": { + "issues": "https://github.com/pdepend/pdepend/issues", + "source": "https://github.com/pdepend/pdepend/tree/2.14.0" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/pdepend/pdepend", + "type": "tidelift" + } + ], + "time": "2023-05-26T13:15:18+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phenx/php-font-lib", + "version": "0.5.4", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-font-lib.git", + "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/dd448ad1ce34c63d09baccd05415e361300c35b4", + "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4", + "shasum": "" + }, + "require": { + "ext-mbstring": "*" + }, + "require-dev": { + "symfony/phpunit-bridge": "^3 || ^4 || ^5" + }, + "type": "library", + "autoload": { + "psr-4": { + "FontLib\\": "src/FontLib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Fabien Ménager", + "email": "fabien.menager@gmail.com" + } + ], + "description": "A library to read, parse, export and make subsets of different types of font files.", + "homepage": "https://github.com/PhenX/php-font-lib", + "support": { + "issues": "https://github.com/dompdf/php-font-lib/issues", + "source": "https://github.com/dompdf/php-font-lib/tree/0.5.4" + }, + "time": "2021-12-17T19:44:54+00:00" + }, + { + "name": "phenx/php-svg-lib", + "version": "0.5.0", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-svg-lib.git", + "reference": "76876c6cf3080bcb6f249d7d59705108166a6685" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/76876c6cf3080bcb6f249d7d59705108166a6685", + "reference": "76876c6cf3080bcb6f249d7d59705108166a6685", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0", + "sabberworm/php-css-parser": "^8.4" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Svg\\": "src/Svg" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Fabien Ménager", + "email": "fabien.menager@gmail.com" + } + ], + "description": "A library to read, parse and export to PDF SVG files.", + "homepage": "https://github.com/PhenX/php-svg-lib", + "support": { + "issues": "https://github.com/dompdf/php-svg-lib/issues", + "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.0" + }, + "time": "2022-09-06T12:16:56+00:00" + }, + { + "name": "php-cs-fixer/diff", + "version": "v2.0.2", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/diff.git", + "reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/29dc0d507e838c4580d018bd8b5cb412474f7ec3", + "reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0", + "symfony/process": "^3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "sebastian/diff v3 backport support for PHP 5.6+", + "homepage": "https://github.com/PHP-CS-Fixer", + "keywords": [ + "diff" + ], + "support": { + "issues": "https://github.com/PHP-CS-Fixer/diff/issues", + "source": "https://github.com/PHP-CS-Fixer/diff/tree/v2.0.2" + }, + "abandoned": true, + "time": "2020-10-14T08:32:19+00:00" + }, + { + "name": "phpmd/phpmd", + "version": "2.13.0", + "source": { + "type": "git", + "url": "https://github.com/phpmd/phpmd.git", + "reference": "dad0228156856b3ad959992f9748514fa943f3e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpmd/phpmd/zipball/dad0228156856b3ad959992f9748514fa943f3e3", + "reference": "dad0228156856b3ad959992f9748514fa943f3e3", + "shasum": "" + }, + "require": { + "composer/xdebug-handler": "^1.0 || ^2.0 || ^3.0", + "ext-xml": "*", + "pdepend/pdepend": "^2.12.1", + "php": ">=5.3.9" + }, + "require-dev": { + "easy-doc/easy-doc": "0.0.0 || ^1.3.2", + "ext-json": "*", + "ext-simplexml": "*", + "gregwar/rst": "^1.0", + "mikey179/vfsstream": "^1.6.8", + "phpunit/phpunit": "^4.8.36 || ^5.7.27", + "squizlabs/php_codesniffer": "^2.0" + }, + "bin": [ + "src/bin/phpmd" + ], + "type": "library", + "autoload": { + "psr-0": { + "PHPMD\\": "src/main/php" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Manuel Pichler", + "email": "github@manuel-pichler.de", + "homepage": "https://github.com/manuelpichler", + "role": "Project Founder" + }, + { + "name": "Marc Würth", + "email": "ravage@bluewin.ch", + "homepage": "https://github.com/ravage84", + "role": "Project Maintainer" + }, + { + "name": "Other contributors", + "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", + "role": "Contributors" + } + ], + "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", + "homepage": "https://phpmd.org/", + "keywords": [ + "mess detection", + "mess detector", + "pdepend", + "phpmd", + "pmd" + ], + "support": { + "irc": "irc://irc.freenode.org/phpmd", + "issues": "https://github.com/phpmd/phpmd/issues", + "source": "https://github.com/phpmd/phpmd/tree/2.13.0" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/phpmd/phpmd", + "type": "tidelift" + } + ], + "time": "2022-09-10T08:44:15+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.26", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.15", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-03-06T12:58:08+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "3.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "9.6.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "17d621b3aff84d0c8b62539e269e87d8d5baa76e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/17d621b3aff84d0c8b62539e269e87d8d5baa76e", + "reference": "17d621b3aff84d0c8b62539e269e87d8d5baa76e", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1 || ^2", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.5", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.2", + "sebastian/version": "^3.0.2" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.6-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.8" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2023-05-11T05:14:45+00:00" + }, + { + "name": "psr/cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "time": "2021-02-03T23:26:27+00:00" + }, + { + "name": "psr/container", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, + "time": "2021-11-05T16:50:12+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-message", + "version": "1.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/1.1" + }, + "time": "2023-04-04T09:50:52+00:00" + }, + { + "name": "psr/log", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "sabberworm/php-css-parser", + "version": "8.4.0", + "source": { + "type": "git", + "url": "https://github.com/sabberworm/PHP-CSS-Parser.git", + "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sabberworm/PHP-CSS-Parser/zipball/e41d2140031d533348b2192a83f02d8dd8a71d30", + "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": ">=5.6.20" + }, + "require-dev": { + "codacy/coverage": "^1.4", + "phpunit/phpunit": "^4.8.36" + }, + "suggest": { + "ext-mbstring": "for parsing UTF-8 CSS" + }, + "type": "library", + "autoload": { + "psr-4": { + "Sabberworm\\CSS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Raphael Schweikert" + } + ], + "description": "Parser for CSS Files written in PHP", + "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser", + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "support": { + "issues": "https://github.com/sabberworm/PHP-CSS-Parser/issues", + "source": "https://github.com/sabberworm/PHP-CSS-Parser/tree/8.4.0" + }, + "time": "2021-12-11T13:40:54+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:08:49+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T12:41:17+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.7", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T15:52:27+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-05-07T05:35:17+00:00" + }, + { + "name": "sebastian/environment", + "version": "5.1.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:03:51+00:00" + }, + { + "name": "sebastian/exporter", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T06:03:37+00:00" + }, + { + "name": "sebastian/global-state", + "version": "5.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-02-14T08:28:10+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.6", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-28T06:42:11+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:07:39+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:45:17+00:00" + }, + { + "name": "sebastian/type", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:13:03+00:00" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" + }, + { + "name": "setasign/fpdi", + "version": "v2.3.7", + "source": { + "type": "git", + "url": "https://github.com/Setasign/FPDI.git", + "reference": "bccc892d5fa1f48c43f8ba7db5ed4ba6f30c8c05" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Setasign/FPDI/zipball/bccc892d5fa1f48c43f8ba7db5ed4ba6f30c8c05", + "reference": "bccc892d5fa1f48c43f8ba7db5ed4ba6f30c8c05", + "shasum": "" + }, + "require": { + "ext-zlib": "*", + "php": "^5.6 || ^7.0 || ^8.0" + }, + "conflict": { + "setasign/tfpdf": "<1.31" + }, + "require-dev": { + "phpunit/phpunit": "~5.7", + "setasign/fpdf": "~1.8", + "setasign/tfpdf": "1.31", + "squizlabs/php_codesniffer": "^3.5", + "tecnickcom/tcpdf": "~6.2" + }, + "suggest": { + "setasign/fpdf": "FPDI will extend this class but as it is also possible to use TCPDF or tFPDF as an alternative. There's no fixed dependency configured." + }, + "type": "library", + "autoload": { + "psr-4": { + "setasign\\Fpdi\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Slabon", + "email": "jan.slabon@setasign.com", + "homepage": "https://www.setasign.com/" + }, + { + "name": "Maximilian Kresse", + "email": "maximilian.kresse@setasign.com", + "homepage": "https://www.setasign.com/" + } + ], + "description": "FPDI is a collection of PHP classes facilitating developers to read pages from existing PDF documents and use them as templates in FPDF. Because it is also possible to use FPDI with TCPDF, there are no fixed dependencies defined. Please see suggestions for packages which evaluates the dependencies automatically.", + "homepage": "https://www.setasign.com/fpdi", + "keywords": [ + "fpdf", + "fpdi", + "pdf" + ], + "support": { + "issues": "https://github.com/Setasign/FPDI/issues", + "source": "https://github.com/Setasign/FPDI/tree/v2.3.7" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/setasign/fpdi", + "type": "tidelift" + } + ], + "time": "2023-02-09T10:38:43+00:00" + }, + { + "name": "symfony/config", + "version": "v5.4.21", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "2a6b1111d038adfa15d52c0871e540f3b352d1e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/2a6b1111d038adfa15d52c0871e540f3b352d1e4", + "reference": "2a6b1111d038adfa15d52c0871e540f3b352d1e4", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/filesystem": "^4.4|^5.0|^6.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php80": "^1.16", + "symfony/polyfill-php81": "^1.22" + }, + "conflict": { + "symfony/finder": "<4.4" + }, + "require-dev": { + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/messenger": "^4.4|^5.0|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/yaml": "^4.4|^5.0|^6.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", + "homepage": "https://symfony.com/", + "support": { + "source": "https://github.com/symfony/config/tree/v5.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-14T08:03:56+00:00" + }, + { + "name": "symfony/console", + "version": "v5.3.16", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "2e322c76cdccb302af6b275ea2207169c8355328" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/2e322c76cdccb302af6b275ea2207169c8355328", + "reference": "2e322c76cdccb302af6b275ea2207169c8355328", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2", + "symfony/string": "^5.1" + }, + "conflict": { + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" + }, + "require-dev": { + "psr/log": "^1|^2", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com/", + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.3.16" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-03-01T08:24:05+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v5.4.24", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "4645e032d0963fb614969398ca28e47605b1a7da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/4645e032d0963fb614969398ca28e47605b1a7da", + "reference": "4645e032d0963fb614969398ca28e47605b1a7da", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16", + "symfony/polyfill-php81": "^1.22", + "symfony/service-contracts": "^1.1.6|^2" + }, + "conflict": { + "ext-psr": "<1.1|>=2", + "symfony/config": "<5.3", + "symfony/finder": "<4.4", + "symfony/proxy-manager-bridge": "<4.4", + "symfony/yaml": "<4.4.26" + }, + "provide": { + "psr/container-implementation": "1.0", + "symfony/service-implementation": "1.0|2.0" + }, + "require-dev": { + "symfony/config": "^5.3|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/yaml": "^4.4.26|^5.0|^6.0" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows you to standardize and centralize the way objects are constructed in your application", + "homepage": "https://symfony.com/", + "support": { + "source": "https://github.com/symfony/dependency-injection/tree/v5.4.24" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-05-05T14:42:55+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com/", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:53:40+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v5.4.22", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1df20e45d56da29a4b1d8259dd6e950acbf1b13f", + "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher-contracts": "^2|^3", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^4.4|^5.0|^6.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com/", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.22" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-17T11:31:58+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", + "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com/", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:53:40+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v5.4.23", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "b2f79d86cd9e7de0fff6d03baa80eaed7a5f38b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b2f79d86cd9e7de0fff6d03baa80eaed7a5f38b5", + "reference": "b2f79d86cd9e7de0fff6d03baa80eaed7a5f38b5", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com/", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v5.4.23" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-02T11:38:35+00:00" + }, + { + "name": "symfony/finder", + "version": "v5.4.21", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "078e9a5e1871fcfe6a5ce421b539344c21afef19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/078e9a5e1871fcfe6a5ce421b539344c21afef19", + "reference": "078e9a5e1871fcfe6a5ce421b539344c21afef19", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com/", + "support": { + "source": "https://github.com/symfony/finder/tree/v5.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-16T09:33:00+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v5.4.21", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", + "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php73": "~1.0", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com/", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v5.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-14T08:03:56+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com/", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com/", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com/", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com/", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", + "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com/", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com/", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", + "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com/", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/process", + "version": "v4.4.44", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "5cee9cdc4f7805e2699d9fd66991a0e6df8252a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/5cee9cdc4f7805e2699d9fd66991a0e6df8252a2", + "reference": "5cee9cdc4f7805e2699d9fd66991a0e6df8252a2", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com/", + "support": { + "source": "https://github.com/symfony/process/tree/v4.4.44" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-06-27T13:16:42+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com/", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-30T19:17:29+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v5.4.21", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/f83692cd869a6f2391691d40a01e8acb89e76fee", + "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/service-contracts": "^1|^2|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a way to profile code", + "homepage": "https://symfony.com/", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v5.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-14T08:03:56+00:00" + }, + { + "name": "symfony/string", + "version": "v5.4.22", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", + "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" + }, + "conflict": { + "symfony/translation-contracts": ">=3.0" + }, + "require-dev": { + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com/", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.4.22" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-14T06:11:53+00:00" + }, + { + "name": "tecnickcom/tcpdf", + "version": "6.6.2", + "source": { + "type": "git", + "url": "https://github.com/tecnickcom/TCPDF.git", + "reference": "e3cffc9bcbc76e89e167e9eb0bbda0cab7518459" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/e3cffc9bcbc76e89e167e9eb0bbda0cab7518459", + "reference": "e3cffc9bcbc76e89e167e9eb0bbda0cab7518459", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "config", + "include", + "tcpdf.php", + "tcpdf_parser.php", + "tcpdf_import.php", + "tcpdf_barcodes_1d.php", + "tcpdf_barcodes_2d.php", + "include/tcpdf_colors.php", + "include/tcpdf_filters.php", + "include/tcpdf_font_data.php", + "include/tcpdf_fonts.php", + "include/tcpdf_images.php", + "include/tcpdf_static.php", + "include/barcodes/datamatrix.php", + "include/barcodes/pdf417.php", + "include/barcodes/qrcode.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-only" + ], + "authors": [ + { + "name": "Nicola Asuni", + "email": "info@tecnick.com", + "role": "lead" + } + ], + "description": "TCPDF is a PHP class for generating PDF documents and barcodes.", + "homepage": "http://www.tcpdf.org/", + "keywords": [ + "PDFD32000-2008", + "TCPDF", + "barcodes", + "datamatrix", + "pdf", + "pdf417", + "qrcode" + ], + "support": { + "issues": "https://github.com/tecnickcom/TCPDF/issues", + "source": "https://github.com/tecnickcom/TCPDF/tree/6.6.2" + }, + "funding": [ + { + "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_donations¤cy_code=GBP&business=paypal@tecnick.com&item_name=donation%20for%20tcpdf%20project", + "type": "custom" + } + ], + "time": "2022-12-17T10:28:59+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2021-07-28T10:34:58+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7.1|^8.0", + "ext-dom": "*", + "ext-json": "*", + "ext-xml": "*" + }, + "platform-dev": { + "ext-zip": "*", + "ext-gd": "*", + "ext-libxml": "*" + }, + "platform-overrides": { + "php": "8.0" + }, + "plugin-api-version": "2.3.0" +} From dd0748332710b579ff10b8430acec4295922ca55 Mon Sep 17 00:00:00 2001 From: pebosi Date: Tue, 16 May 2023 11:01:31 +0200 Subject: [PATCH 091/246] Update templates-processing.rst --- docs/templates-processing.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/templates-processing.rst b/docs/templates-processing.rst index df6231287d..1f7f5f2b80 100644 --- a/docs/templates-processing.rst +++ b/docs/templates-processing.rst @@ -247,7 +247,7 @@ Applies the XSL stylesheet passed to header part, footer part and main part setComplexValue """"""""""""""" -Raplaces a ${macro} with the ComplexType passed. +Replaces a ${macro} with the ComplexType passed. See ``Sample_40_TemplateSetComplexValue.php`` for examples. .. code-block:: php @@ -258,7 +258,7 @@ See ``Sample_40_TemplateSetComplexValue.php`` for examples. setComplexBlock """"""""""""""" -Raplaces a ${macro} with the ComplexType passed. +Replaces a ${macro} with the ComplexType passed. See ``Sample_40_TemplateSetComplexValue.php`` for examples. .. code-block:: php From 2c56271070292eb534f149ff182ed1b44937634a Mon Sep 17 00:00:00 2001 From: pebosi Date: Tue, 16 May 2023 11:04:25 +0200 Subject: [PATCH 092/246] Update TemplateProcessor.php --- src/PhpWord/TemplateProcessor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index dac2a2a6a6..e6731b0357 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -1266,7 +1266,7 @@ protected function indexClonedVariables($count, $xmlBlock) } /** - * Raplaces variables with values from array, array keys are the variable names. + * Replaces variables with values from array, array keys are the variable names. * * @param array $variableReplacements * @param string $xmlBlock From c5a1f9186ed3b4bcb4779b4748a629eb8509ced6 Mon Sep 17 00:00:00 2001 From: SarahTrees Date: Thu, 4 May 2023 19:49:20 +0200 Subject: [PATCH 093/246] Update Language.php Add FR_CH Add DE_CH --- src/PhpWord/Style/Language.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index e47cceb3e9..d32f518163 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -35,16 +35,22 @@ final class Language extends AbstractStyle const EN_GB_ID = 2057; const FR_FR = 'fr-FR'; - const FR_FR_ID = 1036; + const FR_FR_ID = 1036; const FR_BE = 'fr-BE'; const FR_BE_ID = 2060; + + const FR_CH = 'fr-CH'; + const FR_CH_ID = 4108; const ES_ES = 'es-ES'; const ES_ES_ID = 3082; const DE_DE = 'de-DE'; const DE_DE_ID = 1031; + + const DE_CH = 'de-CH'; + const DE_CH_ID = 2055; const HE_IL = 'he-IL'; const HE_IL_ID = 1037; From 6742f47eda3a980e2133724ba5a05e185b97c5d1 Mon Sep 17 00:00:00 2001 From: SarahTrees Date: Thu, 4 May 2023 20:05:34 +0200 Subject: [PATCH 094/246] Update Language.php remove space --- src/PhpWord/Style/Language.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index d32f518163..f105478aed 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -35,7 +35,7 @@ final class Language extends AbstractStyle const EN_GB_ID = 2057; const FR_FR = 'fr-FR'; - const FR_FR_ID = 1036; + const FR_FR_ID = 1036; const FR_BE = 'fr-BE'; const FR_BE_ID = 2060; From 338ff0b4e69c5084b58db43ba8b7ecbf4e874007 Mon Sep 17 00:00:00 2001 From: SarahTrees Date: Thu, 4 May 2023 22:10:34 +0200 Subject: [PATCH 095/246] Update Language.php IT_CH add language IT_CH (2064) --- src/PhpWord/Style/Language.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index f105478aed..37b4793cdd 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -57,6 +57,9 @@ final class Language extends AbstractStyle const IT_IT = 'it-IT'; const IT_IT_ID = 1040; + + const IT_CH = 'it-CH'; + const IT_CH_ID = 2064; const JA_JP = 'ja-JP'; const JA_JP_ID = 1041; From 4ea4abc0e60ce67d0767d41f5bc86528b7a20b51 Mon Sep 17 00:00:00 2001 From: Severin J <48485375+sevjan@users.noreply.github.com> Date: Tue, 11 Apr 2023 09:40:12 +0200 Subject: [PATCH 096/246] docs: Better suited sample for list item Replaces table sample in list item with the better suited list item sample. --- docs/elements.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/elements.rst b/docs/elements.rst index 3b7dc1d6a5..d95a0e5b5f 100644 --- a/docs/elements.rst +++ b/docs/elements.rst @@ -177,7 +177,7 @@ Parameters: TYPE\_ALPHANUM, TYPE\_BULLET\_FILLED, etc. See list of constants in PHPWord\\Style\\ListItem. - ``$paragraphStyle``. See :ref:`paragraph-style`. -See ``Sample_09_Tables.php`` for more code sample. +See ``Sample_14_ListItem.php`` for more code sample. Advanced usage: From ee42aa30c961a53d065cb0de3facb61a9a110d35 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Tue, 30 May 2023 13:22:41 +0700 Subject: [PATCH 097/246] Code style --- src/PhpWord/Style/Language.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index 37b4793cdd..39d5aa1f06 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -39,7 +39,7 @@ final class Language extends AbstractStyle const FR_BE = 'fr-BE'; const FR_BE_ID = 2060; - + const FR_CH = 'fr-CH'; const FR_CH_ID = 4108; @@ -48,7 +48,7 @@ final class Language extends AbstractStyle const DE_DE = 'de-DE'; const DE_DE_ID = 1031; - + const DE_CH = 'de-CH'; const DE_CH_ID = 2055; @@ -57,7 +57,7 @@ final class Language extends AbstractStyle const IT_IT = 'it-IT'; const IT_IT_ID = 1040; - + const IT_CH = 'it-CH'; const IT_CH_ID = 2064; From 34eb13bf02f00b696b5a8bff24d35a24a8aa4848 Mon Sep 17 00:00:00 2001 From: MegaChriz Date: Tue, 25 Oct 2022 16:41:50 +0200 Subject: [PATCH 098/246] Added image quality support, with the maximum quality as default This sets the quality of JPEG files to their maximum. It does this by: - defining a property called `$imageQuality` and a method called `getImageQuality()` to PhpOffice\PhpWord\Element\Image - setting the property `$imageQuality` to `100` for JPG, but keep default compression level for PNG - refactor fragile string callbacks into proper closure that use the new `$imageQuality` In the case of a PNG, this is not the _quality_ of the image, but the _filesize_ of the image. So we use the default value for best speed/filesize balance. --- src/PhpWord/Element/Image.php | 90 +++++++++++++++++------- src/PhpWord/Media.php | 3 +- src/PhpWord/Writer/AbstractWriter.php | 11 +-- tests/PhpWordTests/Element/ImageTest.php | 63 +++++++++-------- 4 files changed, 103 insertions(+), 64 deletions(-) diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php index 15c6997d29..2bb78acb74 100644 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -89,7 +89,7 @@ class Image extends AbstractElement /** * Image function. * - * @var string + * @var null|callable(resource): void */ private $imageFunc; @@ -100,6 +100,16 @@ class Image extends AbstractElement */ private $imageExtension; + /** + * Image quality. + * + * Functions imagepng() and imagejpeg() have an optional parameter for + * quality. + * + * @var null|int + */ + private $imageQuality; + /** * Is memory image. * @@ -249,13 +259,21 @@ public function getImageCreateFunction() /** * Get image function. * - * @return string + * @return null|callable(resource): void */ - public function getImageFunction() + public function getImageFunction(): ?callable { return $this->imageFunc; } + /** + * Get image quality. + */ + public function getImageQuality(): ?int + { + return $this->imageQuality; + } + /** * Get image extension. * @@ -317,20 +335,13 @@ public function setMediaIndex($value): void } /** - * Get image string data. - * - * @param bool $base64 - * - * @return null|string - * - * @since 0.11.0 + * Get image string. */ - public function getImageStringData($base64 = false) + public function getImageString(): ?string { $source = $this->source; $actualSource = null; $imageBinary = null; - $imageData = null; $isTemp = false; // Get actual source from archive image or other source @@ -367,7 +378,8 @@ public function getImageStringData($base64 = false) imagesavealpha($imageResource, true); } ob_start(); - call_user_func($this->imageFunc, $imageResource); + $callback = $this->imageFunc; + $callback($imageResource); $imageBinary = ob_get_contents(); ob_end_clean(); } elseif ($this->sourceType == self::SOURCE_STRING) { @@ -379,20 +391,36 @@ public function getImageStringData($base64 = false) fclose($fileHandle); } } - if ($imageBinary !== null) { - if ($base64) { - $imageData = chunk_split(base64_encode($imageBinary)); - } else { - $imageData = chunk_split(bin2hex($imageBinary)); - } - } // Delete temporary file if necessary if ($isTemp === true) { @unlink($actualSource); } - return $imageData; + return $imageBinary; + } + + /** + * Get image string data. + * + * @param bool $base64 + * + * @return null|string + * + * @since 0.11.0 + */ + public function getImageStringData($base64 = false) + { + $imageBinary = $this->getImageString(); + if ($imageBinary === null) { + return null; + } + + if ($base64) { + return chunk_split(base64_encode($imageBinary)); + } + + return chunk_split(bin2hex($imageBinary)); } /** @@ -503,31 +531,45 @@ private function setFunctions(): void switch ($this->imageType) { case 'image/png': $this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefrompng'; - $this->imageFunc = 'imagepng'; + $this->imageFunc = function ($resource): void { + imagepng($resource, null, $this->imageQuality); + }; $this->imageExtension = 'png'; + $this->imageQuality = -1; break; case 'image/gif': $this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefromgif'; - $this->imageFunc = 'imagegif'; + $this->imageFunc = function ($resource): void { + imagegif($resource); + }; $this->imageExtension = 'gif'; + $this->imageQuality = null; break; case 'image/jpeg': case 'image/jpg': $this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefromjpeg'; - $this->imageFunc = 'imagejpeg'; + $this->imageFunc = function ($resource): void { + imagejpeg($resource, null, $this->imageQuality); + }; $this->imageExtension = 'jpg'; + $this->imageQuality = 100; break; case 'image/bmp': case 'image/x-ms-bmp': $this->imageType = 'image/bmp'; + $this->imageFunc = null; $this->imageExtension = 'bmp'; + $this->imageQuality = null; break; case 'image/tiff': + $this->imageType = 'image/tiff'; + $this->imageFunc = null; $this->imageExtension = 'tif'; + $this->imageQuality = null; break; } diff --git a/src/PhpWord/Media.php b/src/PhpWord/Media.php index 22b0b06b3a..35aeeb9658 100644 --- a/src/PhpWord/Media.php +++ b/src/PhpWord/Media.php @@ -74,8 +74,7 @@ public static function addElement($container, $mediaType, $source, ?Image $image $mediaData['imageType'] = $image->getImageType(); if ($isMemImage) { $mediaData['isMemImage'] = true; - $mediaData['createFunction'] = $image->getImageCreateFunction(); - $mediaData['imageFunction'] = $image->getImageFunction(); + $mediaData['imageString'] = $image->getImageString(); } $target = "{$container}_image{$mediaTypeCount}.{$extension}"; $image->setTarget($target); diff --git a/src/PhpWord/Writer/AbstractWriter.php b/src/PhpWord/Writer/AbstractWriter.php index 3131dbafbc..8ebf98c7b5 100644 --- a/src/PhpWord/Writer/AbstractWriter.php +++ b/src/PhpWord/Writer/AbstractWriter.php @@ -347,17 +347,8 @@ protected function addFilesToPackage(ZipArchive $zip, $elements): void // Retrive GD image content or get local media if (isset($element['isMemImage']) && $element['isMemImage']) { - $image = call_user_func($element['createFunction'], $element['source']); - if ($element['imageType'] === 'image/png') { - // PNG images need to preserve alpha channel information - imagesavealpha($image, true); - } - ob_start(); - call_user_func($element['imageFunction'], $image); - $imageContents = ob_get_contents(); - ob_end_clean(); + $imageContents = $element['imageString']; $zip->addFromString($target, $imageContents); - imagedestroy($image); } else { $this->addFileToPackage($zip, $element['source'], $target); } diff --git a/tests/PhpWordTests/Element/ImageTest.php b/tests/PhpWordTests/Element/ImageTest.php index b30801cad5..9f1773eb4e 100644 --- a/tests/PhpWordTests/Element/ImageTest.php +++ b/tests/PhpWordTests/Element/ImageTest.php @@ -23,8 +23,6 @@ /** * Test class for PhpOffice\PhpWord\Element\Image. - * - * @runTestsInSeparateProcesses */ class ImageTest extends AbstractWebServerEmbeddedTest { @@ -65,33 +63,40 @@ public function testConstructWithStyle(): void /** * Valid image types. + * + * @dataProvider providerImages */ - public function testImages(): void + public function testImages($source, $type, $extension, $createFunction, $imageFunction, $imageQuality): void { - $images = [ - ['mars.jpg', 'image/jpeg', 'jpg', 'imagecreatefromjpeg', 'imagejpeg'], - ['mario.gif', 'image/gif', 'gif', 'imagecreatefromgif', 'imagegif'], - ['firefox.png', 'image/png', 'png', 'imagecreatefrompng', 'imagepng'], - ['duke_nukem.bmp', 'image/bmp', 'bmp', null, null], - ['angela_merkel.tif', 'image/tiff', 'tif', null, null], - ]; - - foreach ($images as $imageData) { - [$source, $type, $extension, $createFunction, $imageFunction] = $imageData; - $nam = ucfirst(strtok($source, '.')); - $source = __DIR__ . "/../_files/images/{$source}"; - $image = new Image($source, null, null, $nam); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $image); - self::assertEquals($source, $image->getSource()); - self::assertEquals($nam, $image->getName()); - self::assertEquals(md5($source), $image->getMediaId()); - self::assertEquals($type, $image->getImageType()); - self::assertEquals($extension, $image->getImageExtension()); - self::assertEquals($createFunction, $image->getImageCreateFunction()); - self::assertEquals($imageFunction, $image->getImageFunction()); - self::assertFalse($image->isMemImage()); - self::assertNotNull($image->getImageStringData()); + $nam = ucfirst(strtok($source, '.')); + $source = __DIR__ . "/../_files/images/{$source}"; + $image = new Image($source, null, null, $nam); + self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $image); + self::assertEquals($source, $image->getSource()); + self::assertEquals($nam, $image->getName()); + self::assertEquals(md5($source), $image->getMediaId()); + self::assertEquals($type, $image->getImageType()); + self::assertEquals($extension, $image->getImageExtension()); + self::assertEquals($createFunction, $image->getImageCreateFunction()); + if ($imageFunction) { + self::assertNotNull($image->getImageFunction()); + } else { + self::assertNull($image->getImageFunction()); } + self::assertEquals($imageQuality, $image->getImageQuality()); + self::assertFalse($image->isMemImage()); + self::assertNotNull($image->getImageStringData()); + } + + public function providerImages(): array + { + return [ + ['mars.jpg', 'image/jpeg', 'jpg', 'imagecreatefromjpeg', true, 100], + ['mario.gif', 'image/gif', 'gif', 'imagecreatefromgif', true, null], + ['firefox.png', 'image/png', 'png', 'imagecreatefrompng', true, -1], + ['duke_nukem.bmp', 'image/bmp', 'bmp', null, false, null], + ['angela_merkel.tif', 'image/tiff', 'tif', null, false, null], + ]; } /** @@ -204,7 +209,8 @@ public function testConstructFromString(): void self::assertEquals('image/jpeg', $image->getImageType()); self::assertEquals('jpg', $image->getImageExtension()); self::assertEquals('imagecreatefromstring', $image->getImageCreateFunction()); - self::assertEquals('imagejpeg', $image->getImageFunction()); + self::assertNotNull($image->getImageFunction()); + self::assertEquals(100, $image->getImageQuality()); self::assertTrue($image->isMemImage()); self::assertNotNull($image->getImageStringData()); @@ -225,7 +231,8 @@ public function testConstructFromGd(): void self::assertEquals('image/png', $image->getImageType()); self::assertEquals('png', $image->getImageExtension()); self::assertEquals('imagecreatefrompng', $image->getImageCreateFunction()); - self::assertEquals('imagepng', $image->getImageFunction()); + self::assertNotNull($image->getImageFunction()); + self::assertEquals(-1, $image->getImageQuality()); self::assertTrue($image->isMemImage()); self::assertNotNull($image->getImageStringData()); From fda449860ae2556f2ca68d5849a5eff4860481a1 Mon Sep 17 00:00:00 2001 From: Luke Lanchester Date: Thu, 8 Dec 2022 10:08:36 +0000 Subject: [PATCH 099/246] Re-add support for reading nested tables This commit re-adds supports for nested tables as provided by @mathieuweber in PR #571 --- src/PhpWord/Reader/Word2007/AbstractPart.php | 2 ++ .../Reader/Word2007/ElementTest.php | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 3e3198fde7..f1bea082df 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -376,6 +376,8 @@ protected function readTable(XMLReader $xmlReader, DOMElement $domNode, $parent, foreach ($cellNodes as $cellNode) { if ('w:p' == $cellNode->nodeName) { // Paragraph $this->readParagraph($xmlReader, $cellNode, $cell, $docPart); + } elseif ($cellNode->nodeName == 'w:tbl') { // Table + $this->readTable($xmlReader, $cellNode, $cell, $docPart); } } } diff --git a/tests/PhpWordTests/Reader/Word2007/ElementTest.php b/tests/PhpWordTests/Reader/Word2007/ElementTest.php index 8403f44f7b..d8574be31d 100644 --- a/tests/PhpWordTests/Reader/Word2007/ElementTest.php +++ b/tests/PhpWordTests/Reader/Word2007/ElementTest.php @@ -277,6 +277,38 @@ public function testReadTitleStyle(): void self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $formattedTitle->getText()); } + /** + * Test reading of nested table + */ + public function testReadNestedTable() + { + $documentXml = ' + + + + + + + ${Field} + + + + + + + + '; + + $phpWord = $this->getDocumentFromString(array('document' => $documentXml)); + + $section = $phpWord->getSection(0); + $table = $section->getElement(0); + $rows = $table->getRows(); + $cells = $rows[0]->getCells(); + $nestedTable = $cells[0]->getElement(0); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Table', $nestedTable); + } + /** * Test reading Drawing. */ From 8e0285d1b2ddfd66fe4e7376d329c1d41e335134 Mon Sep 17 00:00:00 2001 From: Luke Lanchester Date: Thu, 8 Dec 2022 10:38:35 +0000 Subject: [PATCH 100/246] Add required CS fixes --- tests/PhpWordTests/Reader/Word2007/ElementTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/PhpWordTests/Reader/Word2007/ElementTest.php b/tests/PhpWordTests/Reader/Word2007/ElementTest.php index d8574be31d..e4c74f2242 100644 --- a/tests/PhpWordTests/Reader/Word2007/ElementTest.php +++ b/tests/PhpWordTests/Reader/Word2007/ElementTest.php @@ -278,9 +278,9 @@ public function testReadTitleStyle(): void } /** - * Test reading of nested table + * Test reading of nested table. */ - public function testReadNestedTable() + public function testReadNestedTable(): void { $documentXml = ' @@ -299,14 +299,14 @@ public function testReadNestedTable() '; - $phpWord = $this->getDocumentFromString(array('document' => $documentXml)); + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); $section = $phpWord->getSection(0); $table = $section->getElement(0); $rows = $table->getRows(); $cells = $rows[0]->getCells(); $nestedTable = $cells[0]->getElement(0); - $this->assertInstanceOf('PhpOffice\PhpWord\Element\Table', $nestedTable); + self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $nestedTable); } /** From 90a55955e6a772bb4cd9b1ef6a7e88c8976c2561 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Tue, 30 May 2023 14:59:14 +0700 Subject: [PATCH 101/246] 1.1.0 --- CHANGELOG.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef3da07c7d..469abf6a2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,31 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [1.1.0](https://github.com/PHPOffice/PHPWord/tree/1.1.0) (2023-05-30) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.0.0...1.1.0) + +### Enhancements + +- Introduce deleteRow() method for TemplateProcessor +- HTML Reader: Add basic support for CSS Style Tag +- Allow customizing macro syntax in TemplateProcessor +- Add background color support for textboxes +- Add softhyphen support to word reader +- Add support table row height when importing HTML +- Add support for fractional font sizes +- Added image quality support, with the maximum quality as default +- Support for reading nested tables + +### Bug fixes + +- DOCX reader: Read empty vmerge +- Fixed setting width of Cell Style + +### Miscellaneous + +- `master` is the new default branch + ## [1.0.0](https://github.com/PHPOffice/PHPWord/tree/1.0.0) (2022-11-15) [Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.18.3...1.0.0) From 77438025265482ddcf050bce520d3c2b51645108 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Tue, 30 May 2023 17:24:54 +0700 Subject: [PATCH 102/246] Introduce PHPStan --- .github/workflows/ci.yml | 31 + composer.json | 6 +- composer.lock | 120 +- phpstan-baseline.neon | 2151 +++++++++++++++++ phpstan.neon | 26 +- src/PhpWord/Collection/AbstractCollection.php | 4 +- src/PhpWord/ComplexType/TrackChangesView.php | 8 +- src/PhpWord/Element/AbstractElement.php | 8 +- src/PhpWord/Element/Cell.php | 8 +- src/PhpWord/Element/Chart.php | 4 +- src/PhpWord/Element/Field.php | 2 +- src/PhpWord/Element/Footnote.php | 4 +- src/PhpWord/Element/FormField.php | 12 +- src/PhpWord/Element/Image.php | 4 +- src/PhpWord/Element/Line.php | 4 +- src/PhpWord/Element/Link.php | 8 +- src/PhpWord/Element/ListItem.php | 4 +- src/PhpWord/Element/ListItemRun.php | 4 +- src/PhpWord/Element/OLEObject.php | 4 +- src/PhpWord/Element/PreserveText.php | 12 +- src/PhpWord/Element/Row.php | 8 +- src/PhpWord/Element/SDT.php | 6 +- src/PhpWord/Element/Section.php | 6 +- src/PhpWord/Element/Shape.php | 4 +- src/PhpWord/Element/Table.php | 8 +- src/PhpWord/Element/Text.php | 4 +- src/PhpWord/Element/TextBox.php | 4 +- src/PhpWord/Element/TextBreak.php | 8 +- src/PhpWord/Element/Title.php | 6 +- src/PhpWord/Escaper/AbstractEscaper.php | 2 +- src/PhpWord/Escaper/Rtf.php | 2 +- src/PhpWord/Metadata/DocInfo.php | 2 +- src/PhpWord/Metadata/Settings.php | 20 +- src/PhpWord/PhpWord.php | 2 +- src/PhpWord/Shared/Converter.php | 2 +- src/PhpWord/Shared/Html.php | 2 +- src/PhpWord/Shared/XMLReader.php | 4 +- src/PhpWord/Shared/ZipArchive.php | 6 +- src/PhpWord/Style.php | 2 +- src/PhpWord/Style/AbstractStyle.php | 14 +- src/PhpWord/Style/Cell.php | 4 +- src/PhpWord/Style/Paragraph.php | 2 +- src/PhpWord/Style/Section.php | 10 +- src/PhpWord/Style/Table.php | 14 +- src/PhpWord/TemplateProcessor.php | 2 +- .../Writer/HTML/Style/AbstractStyle.php | 4 +- src/PhpWord/Writer/ODText/Part/Content.php | 1 - .../Reader/Word2007/ElementTest.php | 4 +- tests/PhpWordTests/Shared/XMLReaderTest.php | 2 +- tests/PhpWordTests/XmlDocument.php | 16 +- 50 files changed, 2446 insertions(+), 149 deletions(-) create mode 100644 phpstan-baseline.neon diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82dd88b567..adc97146fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,6 +89,37 @@ jobs: - name: Code style with PHP-CS-Fixer run: ./vendor/bin/php-cs-fixer fix --dry-run --diff + phpstan: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 + with: + php-version: 8.0 + extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib + coverage: none + tools: cs2pr + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Static analysis with PHPStan + run: ./vendor/bin/phpstan analyse + coverage: runs-on: ubuntu-latest steps: diff --git a/composer.json b/composer.json index 0a16d01acf..89ebee9a10 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,8 @@ "php-cs-fixer fix --ansi --dry-run --diff", "phpcs --report-width=200 --report-summary --report-full samples/ src/ tests/ --ignore=src/PhpWord/Shared/PCLZip --standard=PSR2 -n", "phpmd src/,tests/ text ./phpmd.xml.dist --exclude pclzip.lib.php", - "@test-no-coverage" + "@test-no-coverage", + "phpstan analyse --ansi" ], "fix": [ "php-cs-fixer fix --ansi" @@ -79,7 +80,8 @@ "phpunit/phpunit": ">=7.0", "tecnickcom/tcpdf": "^6.5", "symfony/process": "^4.4", - "friendsofphp/php-cs-fixer": "^3.3" + "friendsofphp/php-cs-fixer": "^3.3", + "phpstan/phpstan-phpunit": "@stable" }, "suggest": { "ext-zip": "Allows writing OOXML and ODF", diff --git a/composer.lock b/composer.lock index 8d5e5a58ab..004b063a11 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "941205ed12dc2bc633e2125181dc60be", + "content-hash": "dbc28cee4451207beb40bbf5aeff9f1d", "packages": [ { "name": "laminas/laminas-escaper", @@ -1459,6 +1459,120 @@ ], "time": "2022-09-10T08:44:15+00:00" }, + { + "name": "phpstan/phpstan", + "version": "1.10.15", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/762c4dac4da6f8756eebb80e528c3a47855da9bd", + "reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2023-05-09T15:28:01+00:00" + }, + { + "name": "phpstan/phpstan-phpunit", + "version": "1.3.13", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-phpunit.git", + "reference": "d8bdab0218c5eb0964338d24a8511b65e9c94fa5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/d8bdab0218c5eb0964338d24a8511b65e9c94fa5", + "reference": "d8bdab0218c5eb0964338d24a8511b65e9c94fa5", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.10" + }, + "conflict": { + "phpunit/phpunit": "<7.0" + }, + "require-dev": { + "nikic/php-parser": "^4.13.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "extension.neon", + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPUnit extensions and rules for PHPStan", + "support": { + "issues": "https://github.com/phpstan/phpstan-phpunit/issues", + "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.13" + }, + "time": "2023-05-26T11:05:59+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "9.2.26", @@ -4901,7 +5015,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "phpstan/phpstan-phpunit": 0 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000000..937798bfdd --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,2151 @@ +parameters: + ignoreErrors: + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractContainer\\:\\:__call\\(\\) should return PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement but returns null\\.$#" + count: 1 + path: src/PhpWord/Element/AbstractContainer.php + + - + message: "#^Parameter \\#1 \\$objectOrClass of class ReflectionClass constructor expects class\\-string\\\\|T of object, string given\\.$#" + count: 1 + path: src/PhpWord/Element/AbstractContainer.php + + - + message: "#^Parameter \\#1 \\$string of function md5 expects string, int\\<0, max\\> given\\.$#" + count: 1 + path: src/PhpWord/Element/AbstractElement.php + + - + message: "#^Parameter \\#2 \\$styleValue of method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:setNewStyle\\(\\) expects array\\|PhpOffice\\\\PhpWord\\\\Style\\|string\\|null, array\\|PhpOffice\\\\PhpWord\\\\Style\\\\Cell\\|null given\\.$#" + count: 1 + path: src/PhpWord/Element/Cell.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Element\\\\Field\\:\\:setOptions\\(\\) should return PhpOffice\\\\PhpWord\\\\Element\\\\Field but returns array\\.$#" + count: 1 + path: src/PhpWord/Element/Field.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Element\\\\Field\\:\\:setProperties\\(\\) should return PhpOffice\\\\PhpWord\\\\Element\\\\Field but returns array\\.$#" + count: 1 + path: src/PhpWord/Element/Field.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Element\\\\Field\\:\\:\\$fontStyle \\(PhpOffice\\\\PhpWord\\\\Style\\\\Font\\|string\\) does not accept null\\.$#" + count: 1 + path: src/PhpWord/Element/Field.php + + - + message: "#^Result of \\|\\| is always true\\.$#" + count: 1 + path: src/PhpWord/Element/Field.php + + - + message: "#^Parameter \\#2 \\$styleValue of method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:setNewStyle\\(\\) expects array\\|PhpOffice\\\\PhpWord\\\\Style\\|string\\|null, array\\|PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\|string\\|null given\\.$#" + count: 1 + path: src/PhpWord/Element/Footnote.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Element\\\\Image\\:\\:getArchiveImageSize\\(\\) should return array\\|null but returns array\\|false\\|null\\.$#" + count: 1 + path: src/PhpWord/Element/Image.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Element\\\\Image\\:\\:getImageString\\(\\) should return string\\|null but returns string\\|false\\|null\\.$#" + count: 1 + path: src/PhpWord/Element/Image.php + + - + message: "#^Parameter \\#1 \\$callback of function call_user_func expects callable\\(\\)\\: mixed, string given\\.$#" + count: 1 + path: src/PhpWord/Element/Image.php + + - + message: "#^Parameter \\#2 \\$length of function fread expects int\\<0, max\\>, int\\<0, max\\>\\|false given\\.$#" + count: 1 + path: src/PhpWord/Element/Image.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Element\\\\Image\\:\\:\\$source \\(string\\) does not accept string\\|false\\.$#" + count: 1 + path: src/PhpWord/Element/Image.php + + - + message: "#^Offset 'extension' does not exist on array\\{dirname\\?\\: string, basename\\: string, extension\\?\\: string, filename\\: string\\}\\.$#" + count: 2 + path: src/PhpWord/Element/OLEObject.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Element\\\\OLEObject\\:\\:\\$icon \\(string\\) does not accept string\\|false\\.$#" + count: 1 + path: src/PhpWord/Element/OLEObject.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Element\\\\Section\\:\\:addHeader\\(\\) should return PhpOffice\\\\PhpWord\\\\Element\\\\Header but returns PhpOffice\\\\PhpWord\\\\Element\\\\Footer\\.$#" + count: 1 + path: src/PhpWord/Element/Section.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Element\\\\Section\\:\\:addHeaderFooter\\(\\) should return PhpOffice\\\\PhpWord\\\\Element\\\\Footer but returns PhpOffice\\\\PhpWord\\\\Element\\\\AbstractContainer\\.$#" + count: 1 + path: src/PhpWord/Element/Section.php + + - + message: "#^Parameter \\#2 \\$styleValue of method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:setNewStyle\\(\\) expects array\\|PhpOffice\\\\PhpWord\\\\Style\\|string\\|null, array\\|PhpOffice\\\\PhpWord\\\\Style\\|PhpOffice\\\\PhpWord\\\\Style\\\\Section\\|string given\\.$#" + count: 1 + path: src/PhpWord/Element/Section.php + + - + message: "#^Parameter \\#3 \\$length of function substr expects int\\|null, int\\|false given\\.$#" + count: 1 + path: src/PhpWord/Element/Section.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Escaper\\\\Rtf\\:\\:escapeAsciiCharacter\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Escaper/Rtf.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Escaper\\\\Rtf\\:\\:escapeAsciiCharacter\\(\\) has parameter \\$code with no type specified\\.$#" + count: 1 + path: src/PhpWord/Escaper/Rtf.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Escaper\\\\Rtf\\:\\:escapeMultibyteCharacter\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Escaper/Rtf.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Escaper\\\\Rtf\\:\\:escapeMultibyteCharacter\\(\\) has parameter \\$code with no type specified\\.$#" + count: 1 + path: src/PhpWord/Escaper/Rtf.php + + - + message: "#^Cannot instantiate interface PhpOffice\\\\PhpWord\\\\Writer\\\\WriterInterface\\.$#" + count: 1 + path: src/PhpWord/IOFactory.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\IOFactory\\:\\:createObject\\(\\) should return PhpOffice\\\\PhpWord\\\\Reader\\\\ReaderInterface\\|PhpOffice\\\\PhpWord\\\\Writer\\\\WriterInterface but returns object\\.$#" + count: 1 + path: src/PhpWord/IOFactory.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\IOFactory\\:\\:createReader\\(\\) should return PhpOffice\\\\PhpWord\\\\Reader\\\\ReaderInterface but returns PhpOffice\\\\PhpWord\\\\Reader\\\\ReaderInterface\\|PhpOffice\\\\PhpWord\\\\Writer\\\\WriterInterface\\.$#" + count: 1 + path: src/PhpWord/IOFactory.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\IOFactory\\:\\:createWriter\\(\\) should return PhpOffice\\\\PhpWord\\\\Writer\\\\WriterInterface but returns PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\|PhpOffice\\\\PhpWord\\\\Writer\\\\WriterInterface\\.$#" + count: 1 + path: src/PhpWord/IOFactory.php + + - + message: "#^Parameter \\#1 \\$objectOrClass of class ReflectionClass constructor expects class\\-string\\\\|T of object, string given\\.$#" + count: 1 + path: src/PhpWord/IOFactory.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\PhpWord\\:\\:getDefaultFontSize\\(\\) should return int but returns float\\|int\\.$#" + count: 1 + path: src/PhpWord/PhpWord.php + + - + message: "#^Parameter \\#1 \\$callback of function forward_static_call_array expects callable\\(\\)\\: mixed, array\\{'PhpOffice\\\\\\\\PhpWord…', string\\} given\\.$#" + count: 1 + path: src/PhpWord/PhpWord.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Reader\\\\AbstractReader\\:\\:openFile\\(\\) should return resource but return statement is missing\\.$#" + count: 1 + path: src/PhpWord/Reader/AbstractReader.php + + - + message: "#^Parameter \\#2 \\$html of static method PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:addHtml\\(\\) expects string, string\\|false given\\.$#" + count: 1 + path: src/PhpWord/Reader/HTML.php + + - + message: "#^Call to an undefined method DOMNode\\:\\:getAttribute\\(\\)\\.$#" + count: 2 + path: src/PhpWord/Reader/ODText/Content.php + + - + message: "#^Offset 'textNodes' on array\\{changed\\: PhpOffice\\\\PhpWord\\\\Element\\\\TrackChange, textNodes\\: DOMNodeList\\\\} in isset\\(\\) always exists and is not nullable\\.$#" + count: 1 + path: src/PhpWord/Reader/ODText/Content.php + + - + message: "#^Parameter \\#2 \\$contextNode of method PhpOffice\\\\PhpWord\\\\Shared\\\\XMLReader\\:\\:getElements\\(\\) expects DOMElement\\|null, DOMNode\\|null given\\.$#" + count: 2 + path: src/PhpWord/Reader/ODText/Content.php + + - + message: "#^Parameter \\#2 \\$depth of method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractContainer\\:\\:addTitle\\(\\) expects int, string\\|null given\\.$#" + count: 1 + path: src/PhpWord/Reader/ODText/Content.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Reader\\\\RTF\\\\Document\\:\\:\\$rtf \\(string\\) does not accept string\\|false\\.$#" + count: 1 + path: src/PhpWord/Reader/RTF.php + + - + message: "#^Cannot call method setStyleByArray\\(\\) on PhpOffice\\\\PhpWord\\\\Style\\\\Font\\|string\\.$#" + count: 1 + path: src/PhpWord/Reader/RTF/Document.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Reader\\\\RTF\\\\Document\\:\\:\\$phpWord is never read, only written\\.$#" + count: 1 + path: src/PhpWord/Reader/RTF/Document.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Reader\\\\ReaderInterface\\:\\:load\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Reader/ReaderInterface.php + + - + message: "#^Parameter \\#1 \\$string of function substr expects string, string\\|false given\\.$#" + count: 2 + path: src/PhpWord/Reader/Word2007.php + + - + message: "#^Parameter \\#2 \\$xmlFile of method PhpOffice\\\\PhpWord\\\\Reader\\\\Word2007\\:\\:getRels\\(\\) expects string, string\\|false given\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007.php + + - + message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, string\\|false given\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007.php + + - + message: "#^Binary operation \"/\" between string\\|null and 2 results in an error\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/AbstractPart.php + + - + message: "#^Call to an undefined method DOMNode\\:\\:getAttribute\\(\\)\\.$#" + count: 2 + path: src/PhpWord/Reader/Word2007/AbstractPart.php + + - + message: "#^Call to method setChangeInfo\\(\\) on an unknown class PhpOffice\\\\PhpWord\\\\Reader\\\\Word2007\\\\AbstractElement\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/AbstractPart.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Reader\\\\Word2007\\\\AbstractPart\\:\\:getHeadingDepth\\(\\) never returns float so it can be removed from the return type\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/AbstractPart.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Reader\\\\Word2007\\\\AbstractPart\\:\\:getHeadingDepth\\(\\) should return float\\|int\\|null but returns string\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/AbstractPart.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Reader\\\\Word2007\\\\AbstractPart\\:\\:read\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/AbstractPart.php + + - + message: "#^PHPDoc tag @var for variable \\$element contains unknown class PhpOffice\\\\PhpWord\\\\Reader\\\\Word2007\\\\AbstractElement\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/AbstractPart.php + + - + message: "#^Parameter \\#1 \\$count of method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractContainer\\:\\:addTextBreak\\(\\) expects int, null given\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/AbstractPart.php + + - + message: "#^Parameter \\#1 \\$depth of method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractContainer\\:\\:addListItemRun\\(\\) expects int, string\\|null given\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/AbstractPart.php + + - + message: "#^Parameter \\#1 \\$height of method PhpOffice\\\\PhpWord\\\\Element\\\\Table\\:\\:addRow\\(\\) expects int\\|null, string\\|null given\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/AbstractPart.php + + - + message: "#^Parameter \\#1 \\$value of method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:setRelationId\\(\\) expects int, string\\|null given\\.$#" + count: 2 + path: src/PhpWord/Reader/Word2007/AbstractPart.php + + - + message: "#^Parameter \\#1 \\$width of method PhpOffice\\\\PhpWord\\\\Element\\\\Row\\:\\:addCell\\(\\) expects int\\|null, string\\|null given\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/AbstractPart.php + + - + message: "#^Parameter \\#2 \\$contextNode of method PhpOffice\\\\PhpWord\\\\Shared\\\\XMLReader\\:\\:getAttribute\\(\\) expects DOMElement\\|null, DOMNode\\|null given\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/AbstractPart.php + + - + message: "#^Parameter \\#2 \\$depth of method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractContainer\\:\\:addTitle\\(\\) expects int, float\\|int given\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/AbstractPart.php + + - + message: "#^Strict comparison using \\=\\=\\= between null and DOMElement will always evaluate to false\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/AbstractPart.php + + - + message: "#^Parameter \\#2 \\$relationId of method PhpOffice\\\\PhpWord\\\\Reader\\\\Word2007\\\\Footnotes\\:\\:getElement\\(\\) expects int, string\\|null given\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/Footnotes.php + + - + message: "#^Parameter \\#3 \\$levelId of method PhpOffice\\\\PhpWord\\\\Reader\\\\Word2007\\\\Numbering\\:\\:readLevel\\(\\) expects int, string\\|null given\\.$#" + count: 2 + path: src/PhpWord/Reader/Word2007/Numbering.php + + - + message: "#^Parameter \\#1 \\$comments of method PhpOffice\\\\PhpWord\\\\ComplexType\\\\TrackChangesView\\:\\:setComments\\(\\) expects bool\\|null, string\\|null given\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/Settings.php + + - + message: "#^Parameter \\#1 \\$consecutiveHyphenLimit of method PhpOffice\\\\PhpWord\\\\Metadata\\\\Settings\\:\\:setConsecutiveHyphenLimit\\(\\) expects int, string given\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/Settings.php + + - + message: "#^Parameter \\#1 \\$hyphenationZone of method PhpOffice\\\\PhpWord\\\\Metadata\\\\Settings\\:\\:setHyphenationZone\\(\\) expects float\\|int\\|null, string given\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/Settings.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Reader\\\\Word2007\\\\Settings\\:\\:\\$booleanProperties has no type specified\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/Settings.php + + - + message: "#^Static property PhpOffice\\\\PhpWord\\\\Reader\\\\Word2007\\\\Settings\\:\\:\\$booleanProperties is never read, only written\\.$#" + count: 1 + path: src/PhpWord/Reader/Word2007/Settings.php + + - + message: "#^Parameter \\#1 \\$filename of function parse_ini_file expects string, string\\|false given\\.$#" + count: 1 + path: src/PhpWord/Settings.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\AbstractEnum\\:\\:getConstants\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/AbstractEnum.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Shared\\\\AbstractEnum\\:\\:\\$constCacheArray has no type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/AbstractEnum.php + + - + message: "#^Binary operation \"/\" between string and 10 results in an error\\.$#" + count: 1 + path: src/PhpWord/Shared/Converter.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Converter\\:\\:angleToDegree\\(\\) should return int but returns float\\.$#" + count: 1 + path: src/PhpWord/Shared/Converter.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Converter\\:\\:cssToPoint\\(\\) should return float\\|null but returns string\\.$#" + count: 1 + path: src/PhpWord/Shared/Converter.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Converter\\:\\:htmlToRgb\\(\\) should return array but returns false\\.$#" + count: 1 + path: src/PhpWord/Shared/Converter.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Converter\\:\\:inchToEmu\\(\\) should return int but returns float\\.$#" + count: 1 + path: src/PhpWord/Shared/Converter.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Converter\\:\\:pixelToEmu\\(\\) should return int but returns float\\.$#" + count: 1 + path: src/PhpWord/Shared/Converter.php + + - + message: "#^Parameter \\#1 \\$centimeter of static method PhpOffice\\\\PhpWord\\\\Shared\\\\Converter\\:\\:cmToPoint\\(\\) expects float, string given\\.$#" + count: 1 + path: src/PhpWord/Shared/Converter.php + + - + message: "#^Parameter \\#1 \\$inch of static method PhpOffice\\\\PhpWord\\\\Shared\\\\Converter\\:\\:inchToPoint\\(\\) expects float, string given\\.$#" + count: 1 + path: src/PhpWord/Shared/Converter.php + + - + message: "#^Parameter \\#1 \\$pica of static method PhpOffice\\\\PhpWord\\\\Shared\\\\Converter\\:\\:picaToPoint\\(\\) expects float, string given\\.$#" + count: 1 + path: src/PhpWord/Shared/Converter.php + + - + message: "#^Parameter \\#1 \\$pixel of static method PhpOffice\\\\PhpWord\\\\Shared\\\\Converter\\:\\:pixelToPoint\\(\\) expects float, string given\\.$#" + count: 1 + path: src/PhpWord/Shared/Converter.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Drawing\\:\\:angleToDegrees\\(\\) should return int but returns float\\.$#" + count: 1 + path: src/PhpWord/Shared/Drawing.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Drawing\\:\\:emuToPixels\\(\\) should return int but returns float\\.$#" + count: 1 + path: src/PhpWord/Shared/Drawing.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Drawing\\:\\:pixelsToEmu\\(\\) should return int but returns float\\.$#" + count: 1 + path: src/PhpWord/Shared/Drawing.php + + - + message: "#^Access to an undefined property DOMNode\\:\\:\\$value\\.$#" + count: 6 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Binary operation \"\\*\" between string and 50 results in an error\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Call to an undefined method DOMNode\\:\\:getAttribute\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Cannot call method setBorderSize\\(\\) on PhpOffice\\\\PhpWord\\\\Style\\\\Table\\|string\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Cannot call method setStyleName\\(\\) on PhpOffice\\\\PhpWord\\\\Style\\\\Table\\|string\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^If condition is always true\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:addHtml\\(\\) has parameter \\$options with no type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:filterOutNonInheritedStyles\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:mapBorderColor\\(\\) has parameter \\$cssBorderColor with no type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:mapBorderColor\\(\\) has parameter \\$styles with no type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:mapListType\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:parseLink\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:parseList\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:parseStyleDeclarations\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:recursiveParseStylesInHierarchy\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Parameter \\#1 \\$attribute of static method PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:parseStyle\\(\\) expects DOMAttr, DOMNode given\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Parameter \\#2 \\$element of static method PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:parseNode\\(\\) expects PhpOffice\\\\PhpWord\\\\Element\\\\AbstractContainer, PhpOffice\\\\PhpWord\\\\Element\\\\AbstractContainer\\|PhpOffice\\\\PhpWord\\\\Element\\\\Row\\|PhpOffice\\\\PhpWord\\\\Element\\\\Table given\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:\\$listIndex has no type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:\\$options has no type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:\\$xpath has no type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Result of \\|\\| is always true\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Right side of && is always true\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Variable \\$cNodes in empty\\(\\) always exists and is not falsy\\.$#" + count: 2 + path: src/PhpWord/Shared/Html.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Shared\\\\Microsoft\\\\PasswordEncoder\\:\\:\\$encryptionMatrix has no type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Microsoft/PasswordEncoder.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Shared\\\\Microsoft\\\\PasswordEncoder\\:\\:\\$initialCodeArray has no type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Microsoft/PasswordEncoder.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Shared\\\\Microsoft\\\\PasswordEncoder\\:\\:\\$passwordMaxLength has no type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Microsoft/PasswordEncoder.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\XMLReader\\:\\:getElements\\(\\) should return DOMNodeList\\ but returns DOMNodeList\\\\.$#" + count: 1 + path: src/PhpWord/Shared/XMLReader.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\XMLReader\\:\\:getElements\\(\\) should return DOMNodeList\\ but returns DOMNodeList\\\\|false\\.$#" + count: 2 + path: src/PhpWord/Shared/XMLReader.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\XMLWriter\\:\\:getData\\(\\) should return string but returns string\\|false\\.$#" + count: 1 + path: src/PhpWord/Shared/XMLWriter.php + + - + message: "#^Parameter \\#1 \\$uri of method XMLWriter\\:\\:openUri\\(\\) expects string, string\\|false given\\.$#" + count: 1 + path: src/PhpWord/Shared/XMLWriter.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Shared\\\\XMLWriter\\:\\:\\$tempFileName \\(string\\) does not accept string\\|false\\.$#" + count: 1 + path: src/PhpWord/Shared/XMLWriter.php + + - + message: "#^Call to method add\\(\\) on an unknown class PclZip\\.$#" + count: 2 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Call to method addFromString\\(\\) on an unknown class PclZip\\.$#" + count: 1 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Call to method close\\(\\) on an unknown class PclZip\\.$#" + count: 1 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Call to method extract\\(\\) on an unknown class PclZip\\.$#" + count: 1 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Call to method extractByIndex\\(\\) on an unknown class PclZip\\.$#" + count: 3 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Call to method extractTo\\(\\) on an unknown class PclZip\\.$#" + count: 1 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Call to method getFromName\\(\\) on an unknown class PclZip\\.$#" + count: 2 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Call to method listContent\\(\\) on an unknown class PclZip\\.$#" + count: 3 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Comparison operation \"\\!\\=\" between array and 0 results in an error\\.$#" + count: 1 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Constant PCLZIP_OPT_ADD_PATH not found\\.$#" + count: 2 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Constant PCLZIP_OPT_EXTRACT_AS_STRING not found\\.$#" + count: 2 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Constant PCLZIP_OPT_PATH not found\\.$#" + count: 2 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Constant PCLZIP_OPT_REMOVE_PATH not found\\.$#" + count: 2 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Instantiated class PclZip not found\\.$#" + count: 1 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\ZipArchive\\:\\:getFromName\\(\\) should return string but returns string\\|false\\.$#" + count: 1 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\ZipArchive\\:\\:open\\(\\) should return bool but returns int\\|true\\.$#" + count: 1 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Offset 'dirname' does not exist on array\\{dirname\\?\\: string, basename\\: string, extension\\?\\: string, filename\\: string\\}\\.$#" + count: 3 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^PHPDoc tag @var for variable \\$zip contains unknown class PclZip\\.$#" + count: 6 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Parameter \\#1 \\$callback of function call_user_func_array expects callable\\(\\)\\: mixed, array\\{\\$this\\(PhpOffice\\\\PhpWord\\\\Shared\\\\ZipArchive\\)\\|PclZip\\|ZipArchive, mixed\\} given\\.$#" + count: 1 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Parameter \\#1 \\$stream of function fclose expects resource, resource\\|false given\\.$#" + count: 1 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Parameter \\#1 \\$stream of function fwrite expects resource, resource\\|false given\\.$#" + count: 1 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Shared\\\\ZipArchive\\:\\:\\$zip has unknown class PclZip as its type\\.$#" + count: 1 + path: src/PhpWord/Shared/ZipArchive.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\:\\:addFontStyle\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Font but returns PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\.$#" + count: 1 + path: src/PhpWord/Style.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\:\\:addLinkStyle\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Font but returns PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\.$#" + count: 1 + path: src/PhpWord/Style.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\:\\:addNumberingStyle\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Numbering but returns PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\.$#" + count: 1 + path: src/PhpWord/Style.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\:\\:addParagraphStyle\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph but returns PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\.$#" + count: 1 + path: src/PhpWord/Style.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\:\\:addTableStyle\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Table but returns PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\.$#" + count: 1 + path: src/PhpWord/Style.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\:\\:addTitleStyle\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Font but returns PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\.$#" + count: 1 + path: src/PhpWord/Style.php + + - + message: "#^Call to an undefined method object\\:\\:setStyleByArray\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Style/AbstractStyle.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\:\\:setFloatVal\\(\\) should return float\\|null but returns float\\|int\\|string\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/AbstractStyle.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\:\\:setNumericVal\\(\\) should return float\\|int\\|null but returns float\\|int\\|string\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/AbstractStyle.php + + - + message: "#^Parameter \\#3 \\$length of function substr expects int\\|null, int\\|false given\\.$#" + count: 1 + path: src/PhpWord/Style/AbstractStyle.php + + - + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 1 + path: src/PhpWord/Style/AbstractStyle.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Border\\:\\:getBorderSize\\(\\) should return array\\ but returns array\\\\.$#" + count: 1 + path: src/PhpWord/Style/Border.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Cell\\:\\:getBgColor\\(\\) should return string but returns null\\.$#" + count: 1 + path: src/PhpWord/Style/Cell.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Cell\\:\\:setUnit\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Style/Cell.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Cell\\:\\:\\$shading is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Cell.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Chart\\:\\:getMajorTickPosition\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Style/Chart.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Chart\\:\\:setCategoryAxisTitle\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Style/Chart.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Chart\\:\\:setValueAxisTitle\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Style/Chart.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Chart\\:\\:setValueLabelPosition\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Style/Chart.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Chart\\:\\:showAxisLabels\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Style/Chart.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Chart\\:\\:showGridY\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Style/Chart.php + + - + message: "#^PHPDoc tag @param has invalid value \\(string\\)\\: Unexpected token \"\\\\n \\* \", expected variable at offset 250$#" + count: 1 + path: src/PhpWord/Style/Chart.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:setAllCaps\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Font but returns PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\.$#" + count: 1 + path: src/PhpWord/Style/Font.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:setBgColor\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Table but return statement is missing\\.$#" + count: 1 + path: src/PhpWord/Style/Font.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:setDoubleStrikethrough\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Font but returns PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\.$#" + count: 1 + path: src/PhpWord/Style/Font.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:setSmallCaps\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Font but returns PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\.$#" + count: 1 + path: src/PhpWord/Style/Font.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:setStrikethrough\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Font but returns PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\.$#" + count: 1 + path: src/PhpWord/Style/Font.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:setSubScript\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Font but returns PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\.$#" + count: 1 + path: src/PhpWord/Style/Font.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:setSuperScript\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Font but returns PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\.$#" + count: 1 + path: src/PhpWord/Style/Font.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$allCaps is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Font.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$doubleStrikethrough is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Font.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$lang is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Font.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$paragraph is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Font.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$shading is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Font.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$smallCaps is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Font.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$strikethrough is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Font.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Line\\:\\:\\$weight \\(int\\) does not accept float\\|int\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/Line.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\ListItem\\:\\:getListTypeStyle\\(\\) should return array but empty return statement found\\.$#" + count: 1 + path: src/PhpWord/Style/ListItem.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\ListItem\\:\\:getListTypeStyle\\(\\) should return array but return statement is missing\\.$#" + count: 1 + path: src/PhpWord/Style/ListItem.php + + - + message: "#^Parameter \\#2 \\$string of function explode expects string, array\\\\|string given\\.$#" + count: 1 + path: src/PhpWord/Style/ListItem.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\:\\:setStyleValue\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph but returns PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\.$#" + count: 1 + path: src/PhpWord/Style/Paragraph.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\:\\:\\$indentation is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Paragraph.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\:\\:\\$shading is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Paragraph.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\:\\:\\$spacing is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Paragraph.php + + - + message: "#^Result of && is always false\\.$#" + count: 1 + path: src/PhpWord/Style/Paragraph.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Section\\:\\:setSettingValue\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Section but returns PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\.$#" + count: 1 + path: src/PhpWord/Style/Section.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Section\\:\\:\\$lineNumbering is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Section.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Shape\\:\\:\\$extrusion is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Shape.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Shape\\:\\:\\$fill is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Shape.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Shape\\:\\:\\$frame is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Shape.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Shape\\:\\:\\$outline is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Shape.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Shape\\:\\:\\$shadow is never written, only read\\.$#" + count: 1 + path: src/PhpWord/Style/Shape.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\TOC\\:\\:setTabLeader\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\TOC but returns PhpOffice\\\\PhpWord\\\\Style\\\\Tab\\.$#" + count: 1 + path: src/PhpWord/Style/TOC.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\TOC\\:\\:setTabPos\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\TOC but returns PhpOffice\\\\PhpWord\\\\Style\\\\Tab\\.$#" + count: 1 + path: src/PhpWord/Style/TOC.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Table\\:\\:getBorderInsideHColor\\(\\) should return string but returns int\\|string\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/Table.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Table\\:\\:getBorderInsideHSize\\(\\) should return int but returns int\\|string\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/Table.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Table\\:\\:getBorderInsideVColor\\(\\) should return string but returns int\\|string\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/Table.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Table\\:\\:getBorderInsideVSize\\(\\) should return int but returns int\\|string\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/Table.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Table\\:\\:getBorderSize\\(\\) should return array\\ but returns array\\\\.$#" + count: 1 + path: src/PhpWord/Style/Table.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Table\\:\\:getCellMarginBottom\\(\\) should return int but returns int\\|string\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/Table.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Table\\:\\:getCellMarginLeft\\(\\) should return int but returns int\\|string\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/Table.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Table\\:\\:getCellMarginRight\\(\\) should return int but returns int\\|string\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/Table.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Table\\:\\:getCellMarginTop\\(\\) should return int but returns int\\|string\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/Table.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\TablePosition\\:\\:\\$bottomFromText \\(int\\) does not accept float\\|int\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/TablePosition.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\TablePosition\\:\\:\\$leftFromText \\(int\\) does not accept float\\|int\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/TablePosition.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\TablePosition\\:\\:\\$rightFromText \\(int\\) does not accept float\\|int\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/TablePosition.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\TablePosition\\:\\:\\$tblpX \\(int\\) does not accept float\\|int\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/TablePosition.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\TablePosition\\:\\:\\$tblpY \\(int\\) does not accept float\\|int\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/TablePosition.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\TablePosition\\:\\:\\$topFromText \\(int\\) does not accept float\\|int\\|null\\.$#" + count: 1 + path: src/PhpWord/Style/TablePosition.php + + - + message: "#^Call to an undefined method object\\:\\:write\\(\\)\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Cannot access offset 'end' on array\\\\|true\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Cannot access offset 'start' on array\\\\|true\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:addImageToRelations\\(\\) has parameter \\$imageMimeType with no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:addImageToRelations\\(\\) has parameter \\$imgPath with no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:addImageToRelations\\(\\) has parameter \\$partFileName with no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:addImageToRelations\\(\\) has parameter \\$rid with no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:chooseImageDimension\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:chooseImageDimension\\(\\) has parameter \\$baseValue with no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:chooseImageDimension\\(\\) has parameter \\$defaultValue with no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:chooseImageDimension\\(\\) has parameter \\$inlineValue with no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:fixImageWidthHeightRatio\\(\\) has parameter \\$actualHeight with no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:fixImageWidthHeightRatio\\(\\) has parameter \\$actualWidth with no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:fixImageWidthHeightRatio\\(\\) has parameter \\$height with no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:fixImageWidthHeightRatio\\(\\) has parameter \\$width with no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:getImageArgs\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:getImageArgs\\(\\) has parameter \\$varNameWithArgs with no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:getNextRelationsIndex\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:getNextRelationsIndex\\(\\) has parameter \\$documentPartName with no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:indexClonedVariables\\(\\) should return string but returns array\\, string\\|null\\>\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:prepareImageAttrs\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:prepareImageAttrs\\(\\) has parameter \\$replaceImage with no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:prepareImageAttrs\\(\\) has parameter \\$varInlineArgs with no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:setValueForPart\\(\\) should return string but returns array\\\\|string\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:setValueForPart\\(\\) should return string but returns array\\\\|string\\|null\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Parameter \\#1 \\$element of method PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Part\\\\Chart\\:\\:setElement\\(\\) expects PhpOffice\\\\PhpWord\\\\Element\\\\Chart, PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement given\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Parameter \\#1 \\$str of function preg_quote expects string, int\\|string given\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Parameter \\#2 \\$array of function implode expects array\\|null, array\\\\|string given\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Parameter \\#2 \\$array of function implode expects array\\|null, string given\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:\\$macroClosingChars has no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:\\$macroOpeningChars has no type specified\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:\\$tempDocumentFilename \\(string\\) does not accept string\\|false\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:\\$tempDocumentFooters \\(array\\\\) does not accept string\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:\\$tempDocumentHeaders \\(array\\\\) does not accept string\\.$#" + count: 1 + path: src/PhpWord/TemplateProcessor.php + + - + message: "#^Argument of an invalid type array\\\\|false supplied for foreach, only iterables are supported\\.$#" + count: 1 + path: src/PhpWord/Writer/AbstractWriter.php + + - + message: "#^PHPDoc tag @param has invalid value \\(\\\\PhpOffice\\\\PhpWord\\\\PhpWord\\)\\: Unexpected token \"\\\\n \\*\", expected variable at offset 78$#" + count: 1 + path: src/PhpWord/Writer/AbstractWriter.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\HTML\\\\Element\\\\AbstractElement\\:\\:write\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/HTML/Element/AbstractElement.php + + - + message: "#^Call to an undefined method Laminas\\\\Escaper\\\\Escaper\\|PhpOffice\\\\PhpWord\\\\Escaper\\\\AbstractEscaper\\:\\:escapeHtml\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Writer/HTML/Element/Link.php + + - + message: "#^Call to an undefined method Laminas\\\\Escaper\\\\Escaper\\|PhpOffice\\\\PhpWord\\\\Escaper\\\\AbstractEscaper\\:\\:escapeHtmlAttr\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Writer/HTML/Element/Link.php + + - + message: "#^Call to an undefined method Laminas\\\\Escaper\\\\Escaper\\|PhpOffice\\\\PhpWord\\\\Escaper\\\\AbstractEscaper\\:\\:escapeHtml\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Writer/HTML/Element/ListItem.php + + - + message: "#^Variable \\$row in PHPDoc tag @var does not match assigned variable \\$rowStyle\\.$#" + count: 1 + path: src/PhpWord/Writer/HTML/Element/Table.php + + - + message: "#^Call to an undefined method Laminas\\\\Escaper\\\\Escaper\\|PhpOffice\\\\PhpWord\\\\Escaper\\\\AbstractEscaper\\:\\:escapeHtml\\(\\)\\.$#" + count: 2 + path: src/PhpWord/Writer/HTML/Element/Text.php + + - + message: "#^Call to an undefined method Laminas\\\\Escaper\\\\Escaper\\|PhpOffice\\\\PhpWord\\\\Escaper\\\\AbstractEscaper\\:\\:escapeHtml\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Writer/HTML/Element/Title.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\HTML\\\\Style\\\\AbstractStyle\\:\\:write\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/HTML/Style/AbstractStyle.php + + - + message: "#^Else branch is unreachable because previous condition is always true\\.$#" + count: 1 + path: src/PhpWord/Writer/HTML/Style/Paragraph.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Element\\\\Field\\:\\:writeDefault\\(\\) has parameter \\$type with no type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/ODText/Element/Field.php + + - + message: "#^Variable \\$row in PHPDoc tag @var does not match any variable in the foreach loop\\: \\$cell$#" + count: 1 + path: src/PhpWord/Writer/ODText/Element/Table.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Element\\\\Text\\:\\:replacetabs\\(\\) has parameter \\$text with no type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/ODText/Element/Text.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Element\\\\Text\\:\\:replacetabs\\(\\) has parameter \\$xmlWriter with no type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/ODText/Element/Text.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Element\\\\Text\\:\\:replacetabs\\(\\) is unused\\.$#" + count: 1 + path: src/PhpWord/Writer/ODText/Element/Text.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Element\\\\Text\\:\\:writeChangeInsertion\\(\\) has parameter \\$start with no type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/ODText/Element/Text.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:getParagraphStyle\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Writer/ODText/Element/TextRun.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\:\\:setColumnWidths\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Writer/ODText/Part/Content.php + + - + message: "#^Parameter \\#1 \\$container of method PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Part\\\\Content\\:\\:collectTrackedChanges\\(\\) expects PhpOffice\\\\PhpWord\\\\Element\\\\AbstractContainer, PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement given\\.$#" + count: 1 + path: src/PhpWord/Writer/ODText/Part/Content.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Part\\\\Content\\:\\:\\$imageParagraphStyles has no type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/ODText/Part/Content.php + + - + message: "#^Call to an undefined method object\\:\\:write\\(\\)\\.$#" + count: 2 + path: src/PhpWord/Writer/ODText/Part/Styles.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Part\\\\Styles\\:\\:cvttwiptostr\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/ODText/Part/Styles.php + + - + message: "#^Variable \\$indent in empty\\(\\) always exists and is not falsy\\.$#" + count: 1 + path: src/PhpWord/Writer/ODText/Style/Paragraph.php + + - + message: "#^Parameter \\#1 \\$callback of function call_user_func_array expects callable\\(\\)\\: mixed, array\\{PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\\\AbstractRenderer, string\\} given\\.$#" + count: 1 + path: src/PhpWord/Writer/PDF.php + + - + message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, string\\|false given\\.$#" + count: 1 + path: src/PhpWord/Writer/PDF.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:\\$renderer \\(PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\\\AbstractRenderer\\) does not accept object\\.$#" + count: 1 + path: src/PhpWord/Writer/PDF.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\\\DomPDF\\:\\:loadHtml\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Writer/PDF/DomPDF.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\\\DomPDF\\:\\:output\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Writer/PDF/DomPDF.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\\\DomPDF\\:\\:render\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Writer/PDF/DomPDF.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\\\DomPDF\\:\\:setPaper\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Writer/PDF/DomPDF.php + + - + message: "#^Class PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\\\DomPDF referenced with incorrect case\\: PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\\\Dompdf\\.$#" + count: 1 + path: src/PhpWord/Writer/PDF/DomPDF.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\\\DomPDF\\:\\:createExternalWriterInstance\\(\\) should return PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\\\DomPDF but returns Dompdf\\\\Dompdf\\.$#" + count: 1 + path: src/PhpWord/Writer/PDF/DomPDF.php + + - + message: "#^Binary operation \"\\+\" between int\\|string and 1 results in an error\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Element/AbstractElement.php + + - + message: "#^Call to an undefined method Laminas\\\\Escaper\\\\Escaper\\|PhpOffice\\\\PhpWord\\\\Escaper\\\\AbstractEscaper\\:\\:escape\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Element/AbstractElement.php + + - + message: "#^Parameter \\#1 \\$value of method PhpOffice\\\\PhpWord\\\\Writer\\\\RTF\\\\Style\\\\Font\\:\\:setNameIndex\\(\\) expects int, int\\|string given\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Element/AbstractElement.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Writer\\\\RTF\\\\Element\\\\AbstractElement\\:\\:\\$fontStyle \\(PhpOffice\\\\PhpWord\\\\Style\\\\Font\\) does not accept PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\|null\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Element/AbstractElement.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Writer\\\\RTF\\\\Element\\\\AbstractElement\\:\\:\\$fontStyle \\(PhpOffice\\\\PhpWord\\\\Style\\\\Font\\) does not accept PhpOffice\\\\PhpWord\\\\Style\\\\Font\\|string\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Element/AbstractElement.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Writer\\\\RTF\\\\Element\\\\AbstractElement\\:\\:\\$paragraphStyle \\(PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\) does not accept PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\|null\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Element/AbstractElement.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Writer\\\\RTF\\\\Element\\\\AbstractElement\\:\\:\\$paragraphStyle \\(PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\) does not accept PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\|string\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Element/AbstractElement.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Writer\\\\RTF\\\\Element\\\\AbstractElement\\:\\:\\$paragraphStyle \\(PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\) does not accept null\\.$#" + count: 2 + path: src/PhpWord/Writer/RTF/Element/AbstractElement.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\RTF\\\\Element\\\\Field\\:\\:write\\(\\) should return string but empty return statement found\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Element/Field.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\RTF\\\\Element\\\\Field\\:\\:writeDate\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Element/Field.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\RTF\\\\Element\\\\Field\\:\\:writeNumpages\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Element/Field.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\RTF\\\\Element\\\\Field\\:\\:writePage\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Element/Field.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:getImageStringData\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Element/Image.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:getStyle\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Element/Image.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:getSource\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Element/Link.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:getText\\(\\)\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Element/Link.php + + - + message: "#^Call to an undefined method object\\:\\:write\\(\\)\\.$#" + count: 2 + path: src/PhpWord/Writer/RTF/Part/Document.php + + - + message: "#^Binary operation \"\\+\" between int\\|string and 1 results in an error\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Style/Border.php + + - + message: "#^Variable \\$spaceAfter on left side of \\?\\? always exists and is not nullable\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Style/Paragraph.php + + - + message: "#^Variable \\$spaceBefore on left side of \\?\\? always exists and is not nullable\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Style/Paragraph.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\RTF\\\\Style\\\\Tab\\:\\:write\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/RTF/Style/Tab.php + + - + message: "#^PHPDoc tag @param has invalid value \\(\\\\PhpOffice\\\\PhpWord\\\\PhpWord\\)\\: Unexpected token \"\\\\n \", expected variable at offset 86$#" + count: 1 + path: src/PhpWord/Writer/Word2007.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Element\\\\AbstractElement\\:\\:write\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Element/AbstractElement.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Element\\\\Field\\:\\:buildPropertiesAndOptions\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Element/Field.php + + - + message: "#^Parameter \\#1 \\$content of method PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Element\\\\AbstractElement\\:\\:writeText\\(\\) expects string, bool\\|int\\|string given\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Element/FormField.php + + - + message: "#^Parameter \\#3 \\$value of method PhpOffice\\\\PhpWord\\\\Shared\\\\XMLWriter\\:\\:writeElementBlock\\(\\) expects string\\|null, bool\\|int\\|string given\\.$#" + count: 3 + path: src/PhpWord/Writer/Word2007/Element/FormField.php + + - + message: "#^Parameter \\#3 \\$value of method PhpOffice\\\\PhpWord\\\\Shared\\\\XMLWriter\\:\\:writeElementBlock\\(\\) expects string\\|null, int given\\.$#" + count: 4 + path: src/PhpWord/Writer/Word2007/Element/FormField.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Element\\\\ParagraphAlignment\\:\\:\\$attributes has no type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Element/ParagraphAlignment.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Element\\\\ParagraphAlignment\\:\\:\\$name has no type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Element/ParagraphAlignment.php + + - + message: "#^Parameter \\#2 \\$content of method PhpOffice\\\\PhpWord\\\\Shared\\\\XMLWriter\\:\\:writeElement\\(\\) expects string\\|null, bool\\|int\\|string given\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Element/SDT.php + + - + message: "#^Parameter \\#3 \\$value of method PhpOffice\\\\PhpWord\\\\Shared\\\\XMLWriter\\:\\:writeElementBlock\\(\\) expects string\\|null, int\\<100000000, 999999999\\> given\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Element/SDT.php + + - + message: "#^Parameter \\#1 \\$content of method PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Element\\\\AbstractElement\\:\\:writeText\\(\\) expects string, PhpOffice\\\\PhpWord\\\\Element\\\\TextRun\\|string given\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Element/TOC.php + + - + message: "#^Parameter \\#3 \\$indent of method PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Element\\\\TOC\\:\\:writeStyle\\(\\) expects int, float\\|int given\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Element/TOC.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Element\\\\TableAlignment\\:\\:\\$attributes has no type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Element/TableAlignment.php + + - + message: "#^Property PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Element\\\\TableAlignment\\:\\:\\$name has no type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Element/TableAlignment.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\PhpWord\\:\\:addBookmark\\(\\) invoked with 0 parameters, 1 required\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Element/Title.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Part\\\\Chart\\:\\:writeAxisTitle\\(\\) has parameter \\$title with no type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Part/Chart.php + + - + message: "#^Parameter \\#3 \\$value of method PhpOffice\\\\PhpWord\\\\Shared\\\\XMLWriter\\:\\:writeElementBlock\\(\\) expects string\\|null, int given\\.$#" + count: 9 + path: src/PhpWord/Writer/Word2007/Part/Chart.php + + - + message: "#^Parameter \\#3 \\$value of method PhpOffice\\\\PhpWord\\\\Shared\\\\XMLWriter\\:\\:writeElementBlock\\(\\) expects string\\|null, int\\<0, max\\> given\\.$#" + count: 4 + path: src/PhpWord/Writer/Word2007/Part/Chart.php + + - + message: "#^Parameter \\#1 \\$string of function md5 expects string, int\\<0, max\\> given\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Part/Numbering.php + + - + message: "#^Parameter \\#1 \\$haystack of function strpos expects string, int given\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Part/Rels.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Style\\\\AbstractStyle\\:\\:write\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Style/AbstractStyle.php + + - + message: "#^Parameter \\#1 \\$styleName of static method PhpOffice\\\\PhpWord\\\\Style\\:\\:getStyle\\(\\) expects string, PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\|string given\\.$#" + count: 1 + path: src/PhpWord/Writer/Word2007/Style/Font.php + + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\WriterInterface\\:\\:save\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Writer/WriterInterface.php + + - + message: "#^Call to an undefined method object\\:\\:read\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/AbstractTestReader.php + + - + message: "#^Property PhpOffice\\\\PhpWordTests\\\\AbstractTestReader\\:\\:\\$parts has no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/AbstractTestReader.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbeddedTest\\:\\:getBaseUrl\\(\\) has no return type specified\\.$#" + count: 1 + path: tests/PhpWordTests/AbstractWebServerEmbeddedTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbeddedTest\\:\\:getRemoteBmpImageUrl\\(\\) has no return type specified\\.$#" + count: 1 + path: tests/PhpWordTests/AbstractWebServerEmbeddedTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbeddedTest\\:\\:getRemoteGifImageUrl\\(\\) has no return type specified\\.$#" + count: 1 + path: tests/PhpWordTests/AbstractWebServerEmbeddedTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbeddedTest\\:\\:getRemoteImageUrl\\(\\) has no return type specified\\.$#" + count: 1 + path: tests/PhpWordTests/AbstractWebServerEmbeddedTest.php + + - + message: "#^Property PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbeddedTest\\:\\:\\$httpServer has no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/AbstractWebServerEmbeddedTest.php + + - + message: "#^Parameter \\#1 \\$width of class PhpOffice\\\\PhpWord\\\\Element\\\\Cell constructor expects int\\|null, string given\\.$#" + count: 2 + path: tests/PhpWordTests/Element/CellTest.php + + - + message: "#^Parameter \\#2 \\$style of class PhpOffice\\\\PhpWord\\\\Element\\\\Cell constructor expects array\\|PhpOffice\\\\PhpWord\\\\Style\\\\Cell\\|null, int given\\.$#" + count: 2 + path: tests/PhpWordTests/Element/CellTest.php + + - + message: "#^Parameter \\#1 \\$text of method PhpOffice\\\\PhpWord\\\\Element\\\\Field\\:\\:setText\\(\\) expects PhpOffice\\\\PhpWord\\\\Element\\\\TextRun\\|string\\|null, array given\\.$#" + count: 1 + path: tests/PhpWordTests/Element/FieldTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Element\\\\ImageTest\\:\\:testImages\\(\\) has parameter \\$createFunction with no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Element/ImageTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Element\\\\ImageTest\\:\\:testImages\\(\\) has parameter \\$extension with no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Element/ImageTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Element\\\\ImageTest\\:\\:testImages\\(\\) has parameter \\$imageFunction with no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Element/ImageTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Element\\\\ImageTest\\:\\:testImages\\(\\) has parameter \\$imageQuality with no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Element/ImageTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Element\\\\ImageTest\\:\\:testImages\\(\\) has parameter \\$source with no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Element/ImageTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Element\\\\ImageTest\\:\\:testImages\\(\\) has parameter \\$type with no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Element/ImageTest.php + + - + message: "#^Parameter \\#1 \\$source of class PhpOffice\\\\PhpWord\\\\Element\\\\Image constructor expects string, string\\|false given\\.$#" + count: 1 + path: tests/PhpWordTests/Element/ImageTest.php + + - + message: "#^Parameter \\#1 \\$string of function md5 expects string, string\\|false given\\.$#" + count: 1 + path: tests/PhpWordTests/Element/ImageTest.php + + - + message: "#^Parameter \\#1 \\$string of function ucfirst expects string, string\\|false given\\.$#" + count: 1 + path: tests/PhpWordTests/Element/ImageTest.php + + - + message: "#^Parameter \\#3 \\$watermark of class PhpOffice\\\\PhpWord\\\\Element\\\\Image constructor expects bool, null given\\.$#" + count: 1 + path: tests/PhpWordTests/Element/ImageTest.php + + - + message: "#^Parameter \\#2 \\$style of class PhpOffice\\\\PhpWord\\\\Element\\\\Section constructor expects array\\|PhpOffice\\\\PhpWord\\\\Style\\|string\\|null, PhpOffice\\\\PhpWord\\\\Style\\\\Section given\\.$#" + count: 1 + path: tests/PhpWordTests/Element/SectionTest.php + + - + message: "#^Parameter \\#1 \\$text of class PhpOffice\\\\PhpWord\\\\Element\\\\Title constructor expects PhpOffice\\\\PhpWord\\\\Element\\\\TextRun\\|string, PhpOffice\\\\PhpWord\\\\Element\\\\PageBreak given\\.$#" + count: 1 + path: tests/PhpWordTests/Element/TitleTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Escaper\\\\RtfEscaper2Test\\:\\:escapestring\\(\\) has no return type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Escaper/RtfEscaper2Test.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Escaper\\\\RtfEscaper2Test\\:\\:escapestring\\(\\) has parameter \\$str with no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Escaper/RtfEscaper2Test.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Escaper\\\\RtfEscaper2Test\\:\\:expect\\(\\) has no return type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Escaper/RtfEscaper2Test.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Escaper\\\\RtfEscaper2Test\\:\\:expect\\(\\) has parameter \\$str with no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Escaper/RtfEscaper2Test.php + + - + message: "#^Parameter \\#1 \\$expected of static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) expects class\\-string\\, string given\\.$#" + count: 1 + path: tests/PhpWordTests/IOFactoryTest.php + + - + message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" + count: 1 + path: tests/PhpWordTests/IOFactoryTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\PhpWord\\:\\:undefinedMethod\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/PhpWordTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:getElements\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Reader/Word2007/ElementTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:getRows\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Reader/Word2007/ElementTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:getText\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Reader/Word2007/ElementTest.php + + - + message: "#^Cannot access offset 0 on PhpOffice\\\\PhpWord\\\\Element\\\\TextRun\\.$#" + count: 1 + path: tests/PhpWordTests/Reader/Word2007/ElementTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:getElement\\(\\)\\.$#" + count: 2 + path: tests/PhpWordTests/Reader/Word2007/PartTest.php + + - + message: "#^Cannot call method getElement\\(\\) on PhpOffice\\\\PhpWord\\\\Element\\\\TextRun\\|string\\.$#" + count: 3 + path: tests/PhpWordTests/Reader/Word2007/PartTest.php + + - + message: "#^Cannot call method isBold\\(\\) on PhpOffice\\\\PhpWord\\\\Style\\\\Font\\|string\\.$#" + count: 1 + path: tests/PhpWordTests/Reader/Word2007/PartTest.php + + - + message: "#^Variable \\$endnote in PHPDoc tag @var does not match assigned variable \\$documentEndnote\\.$#" + count: 1 + path: tests/PhpWordTests/Reader/Word2007/PartTest.php + + - + message: "#^Variable \\$footnote in PHPDoc tag @var does not match assigned variable \\$documentFootnote\\.$#" + count: 1 + path: tests/PhpWordTests/Reader/Word2007/PartTest.php + + - + message: "#^Cannot access offset 0 on PhpOffice\\\\PhpWord\\\\Element\\\\TextRun\\.$#" + count: 2 + path: tests/PhpWordTests/Reader/Word2007/StyleTest.php + + - + message: "#^Else branch is unreachable because ternary operator condition is always true\\.$#" + count: 1 + path: tests/PhpWordTests/SettingsTest.php + + - + message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" + count: 1 + path: tests/PhpWordTests/SettingsTest.php + + - + message: "#^Property PhpOffice\\\\PhpWordTests\\\\SettingsTest\\:\\:\\$compatibility has no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/SettingsTest.php + + - + message: "#^Property PhpOffice\\\\PhpWordTests\\\\SettingsTest\\:\\:\\$defaultFontName has no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/SettingsTest.php + + - + message: "#^Property PhpOffice\\\\PhpWordTests\\\\SettingsTest\\:\\:\\$defaultFontSize has no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/SettingsTest.php + + - + message: "#^Property PhpOffice\\\\PhpWordTests\\\\SettingsTest\\:\\:\\$defaultPaper has no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/SettingsTest.php + + - + message: "#^Property PhpOffice\\\\PhpWordTests\\\\SettingsTest\\:\\:\\$measurementUnit has no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/SettingsTest.php + + - + message: "#^Property PhpOffice\\\\PhpWordTests\\\\SettingsTest\\:\\:\\$outputEscapingEnabled has no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/SettingsTest.php + + - + message: "#^Property PhpOffice\\\\PhpWordTests\\\\SettingsTest\\:\\:\\$pdfRendererName has no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/SettingsTest.php + + - + message: "#^Property PhpOffice\\\\PhpWordTests\\\\SettingsTest\\:\\:\\$pdfRendererPath has no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/SettingsTest.php + + - + message: "#^Property PhpOffice\\\\PhpWordTests\\\\SettingsTest\\:\\:\\$tempDir has no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/SettingsTest.php + + - + message: "#^Property PhpOffice\\\\PhpWordTests\\\\SettingsTest\\:\\:\\$zipClass has no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/SettingsTest.php + + - + message: "#^Cannot call method getStyleName\\(\\) on PhpOffice\\\\PhpWord\\\\Style\\\\Table\\|string\\.$#" + count: 1 + path: tests/PhpWordTests/Shared/HtmlTest.php + + - + message: "#^Parameter \\#1 \\$number of static method PhpOffice\\\\PhpWord\\\\Shared\\\\Text\\:\\:numberFormat\\(\\) expects float, string given\\.$#" + count: 2 + path: tests/PhpWordTests/Shared/TextTest.php + + - + message: "#^Parameter \\#2 \\$locale of function setlocale expects array\\|string\\|null, int given\\.$#" + count: 1 + path: tests/PhpWordTests/Shared/XMLWriterTest.php + + - + message: "#^Parameter \\#2 \\$locale of function setlocale expects string\\|null, string\\|false given\\.$#" + count: 1 + path: tests/PhpWordTests/Shared/XMLWriterTest.php + + - + message: "#^Argument of an invalid type array\\\\|false supplied for foreach, only iterables are supported\\.$#" + count: 1 + path: tests/PhpWordTests/Shared/ZipArchiveTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Style\\\\AbstractStyleTest\\:\\:callProtectedMethod\\(\\) has no return type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Style/AbstractStyleTest.php + + - + message: "#^Parameter \\#1 \\$objectOrClass of class ReflectionClass constructor expects class\\-string\\\\|object, class\\-string\\|false given\\.$#" + count: 1 + path: tests/PhpWordTests/Style/AbstractStyleTest.php + + - + message: "#^Cannot call method setLineHeight\\(\\) on PhpOffice\\\\PhpWord\\\\Style\\\\Font\\|string\\.$#" + count: 1 + path: tests/PhpWordTests/Style/FontTest.php + + - + message: "#^Parameter \\#1 \\$type of class PhpOffice\\\\PhpWord\\\\Style\\\\Font constructor expects string, null given\\.$#" + count: 1 + path: tests/PhpWordTests/Style/FontTest.php + + - + message: "#^Parameter \\#2 \\$value of method PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\:\\:setStyleValue\\(\\) expects array\\|int\\|string, null given\\.$#" + count: 1 + path: tests/PhpWordTests/Style/FontTest.php + + - + message: "#^Binary operation \"\\*\" between 1\\|120\\|240\\|'atLeast'\\|'auto'\\|'Normal'\\|'numStyle'\\|bool and 720 results in an error\\.$#" + count: 1 + path: tests/PhpWordTests/Style/ParagraphTest.php + + - + message: "#^Cannot call method setLineHeight\\(\\) on PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\|string\\.$#" + count: 1 + path: tests/PhpWordTests/Style/ParagraphTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Style\\\\ParagraphTest\\:\\:findGetter\\(\\) has no return type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Style/ParagraphTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Style\\\\ParagraphTest\\:\\:findGetter\\(\\) has parameter \\$key with no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Style/ParagraphTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Style\\\\ParagraphTest\\:\\:findGetter\\(\\) has parameter \\$object with no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Style/ParagraphTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Style\\\\ParagraphTest\\:\\:findGetter\\(\\) has parameter \\$value with no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Style/ParagraphTest.php + + - + message: "#^Parameter \\#2 \\$value of method PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\:\\:setStyleValue\\(\\) expects array\\|int\\|string, bool given\\.$#" + count: 1 + path: tests/PhpWordTests/Style/RowTest.php + + - + message: "#^Parameter \\#2 \\$value of method PhpOffice\\\\PhpWord\\\\Style\\\\Section\\:\\:setSettingValue\\(\\) expects array\\|int\\|string, null given\\.$#" + count: 1 + path: tests/PhpWordTests/Style/SectionTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:getText\\(\\)\\.$#" + count: 2 + path: tests/PhpWordTests/TemplateProcessorTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Shared\\\\ZipArchive\\:\\:AddFromString\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/TemplateProcessorTest.php + + - + message: "#^Cannot access offset 'end' on array\\\\|bool\\.$#" + count: 2 + path: tests/PhpWordTests/TemplateProcessorTest.php + + - + message: "#^Cannot access offset 'start' on array\\\\|bool\\.$#" + count: 2 + path: tests/PhpWordTests/TemplateProcessorTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\TemplateProcessorTest\\:\\:testTemplateCanBeSavedInTemporaryLocation\\(\\) has no return type specified\\.$#" + count: 1 + path: tests/PhpWordTests/TemplateProcessorTest.php + + - + message: "#^Parameter \\#1 \\$expectedXml of static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertXmlStringEqualsXmlString\\(\\) expects DOMDocument\\|string, string\\|false given\\.$#" + count: 3 + path: tests/PhpWordTests/TemplateProcessorTest.php + + - + message: "#^Parameter \\#2 \\$actualXml of static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertXmlStringEqualsXmlString\\(\\) expects DOMDocument\\|string, string\\|false given\\.$#" + count: 3 + path: tests/PhpWordTests/TemplateProcessorTest.php + + - + message: "#^Parameter \\#2 \\$haystack of static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertStringContainsString\\(\\) expects string, string\\|false given\\.$#" + count: 6 + path: tests/PhpWordTests/TemplateProcessorTest.php + + - + message: "#^Parameter \\#2 \\$haystack of static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertStringNotContainsString\\(\\) expects string, string\\|false given\\.$#" + count: 4 + path: tests/PhpWordTests/TemplateProcessorTest.php + + - + message: "#^Part \\$documentZip \\(ZipArchive\\) of encapsed string cannot be cast to string\\.$#" + count: 1 + path: tests/PhpWordTests/TemplateProcessorTest.php + + - + message: "#^Part \\$templateZip \\(ZipArchive\\) of encapsed string cannot be cast to string\\.$#" + count: 1 + path: tests/PhpWordTests/TemplateProcessorTest.php + + - + message: "#^Argument of an invalid type array\\\\|false supplied for foreach, only iterables are supported\\.$#" + count: 1 + path: tests/PhpWordTests/TestHelperDOCX.php + + - + message: "#^Static property PhpOffice\\\\PhpWordTests\\\\TestHelperDOCX\\:\\:\\$file \\(string\\) does not accept string\\|false\\.$#" + count: 1 + path: tests/PhpWordTests/TestHelperDOCX.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\TestableTemplateProcesor\\:\\:__construct\\(\\) has parameter \\$mainPart with no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/TestableTemplateProcesor.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\TestableTemplateProcesor\\:\\:__construct\\(\\) has parameter \\$settingsPart with no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/TestableTemplateProcesor.php + + - + message: "#^Cannot access property \\$length on DOMNodeList\\\\|false\\.$#" + count: 6 + path: tests/PhpWordTests/Writer/HTML/ElementTest.php + + - + message: "#^Cannot call method item\\(\\) on DOMNodeList\\\\|false\\.$#" + count: 8 + path: tests/PhpWordTests/Writer/HTML/ElementTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Writer\\\\HTML\\\\ElementTest\\:\\:getAsHTML\\(\\) has no return type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/HTML/ElementTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Writer\\\\ODText\\\\Style\\\\FontTest\\:\\:providerAllNamedColors\\(\\) has no return type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/ODText/Style/FontTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:getFont\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDF/DomPDFTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:getOrientation\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDF/DomPDFTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:getPaperSize\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDF/DomPDFTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:getTempDir\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDF/DomPDFTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:save\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDF/DomPDFTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:setFont\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDF/DomPDFTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:setOrientation\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDF/DomPDFTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:setPaperSize\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDF/DomPDFTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:setTempDir\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDF/DomPDFTest.php + + - + message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" + count: 2 + path: tests/PhpWordTests/Writer/PDF/DomPDFTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:save\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDF/MPDFTest.php + + - + message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDF/MPDFTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:save\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDF/TCPDFTest.php + + - + message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDF/TCPDFTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:save\\(\\)\\.$#" + count: 2 + path: tests/PhpWordTests/Writer/PDFTest.php + + - + message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDFTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Writer\\\\RTF\\\\ElementTest\\:\\:removeCr\\(\\) has no return type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/RTF/ElementTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Writer\\\\RTF\\\\ElementTest\\:\\:removeCr\\(\\) has parameter \\$field with no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/RTF/ElementTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Writer\\\\RTF\\\\StyleTest\\:\\:removeCr\\(\\) has no return type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/RTF/StyleTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\Writer\\\\RTF\\\\StyleTest\\:\\:removeCr\\(\\) has parameter \\$field with no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/RTF/StyleTest.php + + - + message: "#^Property PhpOffice\\\\PhpWordTests\\\\Writer\\\\Word2007\\\\Element\\\\ChartTest\\:\\:\\$outputEscapingEnabled has no type specified\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/Word2007/Element/ChartTest.php + + - + message: "#^Call to an undefined method object\\:\\:write\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/Word2007/ElementTest.php + + - + message: "#^Call to an undefined method object\\:\\:write\\(\\)\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/Word2007/StyleTest.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\XmlDocument\\:\\:getElement\\(\\) should return DOMElement\\|null but returns DOMNode\\|null\\.$#" + count: 1 + path: tests/PhpWordTests/XmlDocument.php + + - + message: "#^Method PhpOffice\\\\PhpWordTests\\\\XmlDocument\\:\\:getNodeList\\(\\) should return DOMNodeList\\ but returns DOMNodeList\\\\|false\\.$#" + count: 1 + path: tests/PhpWordTests/XmlDocument.php + + - + message: "#^Property PhpOffice\\\\PhpWordTests\\\\XmlDocument\\:\\:\\$path \\(string\\) does not accept string\\|false\\.$#" + count: 1 + path: tests/PhpWordTests/XmlDocument.php + + - + message: "#^Property PhpOffice\\\\PhpWordTests\\\\XmlDocument\\:\\:\\$xpath \\(DOMXPath\\) does not accept null\\.$#" + count: 1 + path: tests/PhpWordTests/XmlDocument.php diff --git a/phpstan.neon b/phpstan.neon index 666c63b9c1..e490e1b179 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,13 +1,17 @@ includes: - - vendor/phpstan/phpstan/conf/config.level1.neon + - phpstan-baseline.neon + - vendor/phpstan/phpstan-phpunit/extension.neon + - vendor/phpstan/phpstan-phpunit/rules.neon parameters: - memory-limit: 20000000 - autoload_directories: - - tests - autoload_files: - - tests/bootstrap.php - excludes_analyse: - - */pclzip.lib.php - - src/PhpWord/Shared/OLERead.php - - src/PhpWord/Reader/MsDoc.php - - src/PhpWord/Writer/PDF/MPDF.php \ No newline at end of file + level: 7 + paths: + - src/ + - tests/ + excludePaths: + - */pclzip.lib.php + - src/PhpWord/Shared/OLERead.php + - src/PhpWord/Reader/MsDoc.php + - src/PhpWord/Writer/PDF/MPDF.php + bootstrapFiles: + - tests/bootstrap.php + checkMissingIterableValueType: false diff --git a/src/PhpWord/Collection/AbstractCollection.php b/src/PhpWord/Collection/AbstractCollection.php index 225b361566..70c92689b8 100644 --- a/src/PhpWord/Collection/AbstractCollection.php +++ b/src/PhpWord/Collection/AbstractCollection.php @@ -46,7 +46,7 @@ public function getItems() * * @param int $index * - * @return \PhpOffice\PhpWord\Element\AbstractContainer + * @return ?\PhpOffice\PhpWord\Element\AbstractContainer */ public function getItem($index) { @@ -61,7 +61,7 @@ public function getItem($index) * Set item. * * @param int $index - * @param \PhpOffice\PhpWord\Element\AbstractContainer $item + * @param ?\PhpOffice\PhpWord\Element\AbstractContainer $item */ public function setItem($index, $item): void { diff --git a/src/PhpWord/ComplexType/TrackChangesView.php b/src/PhpWord/ComplexType/TrackChangesView.php index 170c56033c..4331047414 100644 --- a/src/PhpWord/ComplexType/TrackChangesView.php +++ b/src/PhpWord/ComplexType/TrackChangesView.php @@ -72,7 +72,7 @@ public function hasMarkup() /** * Set Display Visual Indicator Of Markup Area. * - * @param bool $markup + * @param ?bool $markup * Set to true to show markup */ public function setMarkup($markup): void @@ -93,7 +93,7 @@ public function hasComments() /** * Set Display Comments. * - * @param bool $comments + * @param ?bool $comments * Set to true to show comments */ public function setComments($comments): void @@ -114,7 +114,7 @@ public function hasInsDel() /** * Set Display Content Revisions. * - * @param bool $insDel + * @param ?bool $insDel * Set to true to show content revisions */ public function setInsDel($insDel): void @@ -156,7 +156,7 @@ public function hasInkAnnotations() /** * Set Display Ink Annotations. * - * @param bool $inkAnnotations + * @param ?bool $inkAnnotations * Set to true to show ink annotations */ public function setInkAnnotations($inkAnnotations): void diff --git a/src/PhpWord/Element/AbstractElement.php b/src/PhpWord/Element/AbstractElement.php index 3b59d06cd4..90a1f8e46d 100644 --- a/src/PhpWord/Element/AbstractElement.php +++ b/src/PhpWord/Element/AbstractElement.php @@ -32,7 +32,7 @@ abstract class AbstractElement /** * PhpWord object. * - * @var \PhpOffice\PhpWord\PhpWord + * @var ?\PhpOffice\PhpWord\PhpWord */ protected $phpWord; @@ -147,7 +147,7 @@ abstract class AbstractElement /** * Get PhpWord. * - * @return \PhpOffice\PhpWord\PhpWord + * @return ?\PhpOffice\PhpWord\PhpWord */ public function getPhpWord() { @@ -156,8 +156,6 @@ public function getPhpWord() /** * Set PhpWord as reference. - * - * @param \PhpOffice\PhpWord\PhpWord $phpWord */ public function setPhpWord(?PhpWord $phpWord = null): void { @@ -432,7 +430,7 @@ public function isInSection() * Set new style value. * * @param mixed $styleObject Style object - * @param mixed $styleValue Style value + * @param null|array|\PhpOffice\PhpWord\Style|string $styleValue Style value * @param bool $returnObject Always return object * * @return mixed diff --git a/src/PhpWord/Element/Cell.php b/src/PhpWord/Element/Cell.php index f07d246d5d..7f2a189b83 100644 --- a/src/PhpWord/Element/Cell.php +++ b/src/PhpWord/Element/Cell.php @@ -32,14 +32,14 @@ class Cell extends AbstractContainer /** * Cell width. * - * @var int + * @var ?int */ private $width; /** * Cell style. * - * @var \PhpOffice\PhpWord\Style\Cell + * @var ?\PhpOffice\PhpWord\Style\Cell */ private $style; @@ -58,7 +58,7 @@ public function __construct($width = null, $style = null) /** * Get cell style. * - * @return \PhpOffice\PhpWord\Style\Cell + * @return ?\PhpOffice\PhpWord\Style\Cell */ public function getStyle() { @@ -68,7 +68,7 @@ public function getStyle() /** * Get cell width. * - * @return int + * @return ?int */ public function getWidth() { diff --git a/src/PhpWord/Element/Chart.php b/src/PhpWord/Element/Chart.php index f2277c4476..4f652f2512 100644 --- a/src/PhpWord/Element/Chart.php +++ b/src/PhpWord/Element/Chart.php @@ -50,7 +50,7 @@ class Chart extends AbstractElement /** * Chart style. * - * @var \PhpOffice\PhpWord\Style\Chart + * @var ?\PhpOffice\PhpWord\Style\Chart */ private $style; @@ -120,7 +120,7 @@ public function getSeries() /** * Get chart style. * - * @return \PhpOffice\PhpWord\Style\Chart + * @return ?\PhpOffice\PhpWord\Style\Chart */ public function getStyle() { diff --git a/src/PhpWord/Element/Field.php b/src/PhpWord/Element/Field.php index a912f3ca22..68a5296d7a 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -268,7 +268,7 @@ public function getOptions() /** * Set Field text. * - * @param string|TextRun $text + * @param null|string|TextRun $text * * @return null|string|TextRun */ diff --git a/src/PhpWord/Element/Footnote.php b/src/PhpWord/Element/Footnote.php index 2c1bd26f97..7a08091abc 100644 --- a/src/PhpWord/Element/Footnote.php +++ b/src/PhpWord/Element/Footnote.php @@ -29,7 +29,7 @@ class Footnote extends AbstractContainer /** * Paragraph style. * - * @var \PhpOffice\PhpWord\Style\Paragraph|string + * @var null|\PhpOffice\PhpWord\Style\Paragraph|string */ protected $paragraphStyle; @@ -54,7 +54,7 @@ public function __construct($paragraphStyle = null) /** * Get paragraph style. * - * @return \PhpOffice\PhpWord\Style\Paragraph|string + * @return null|\PhpOffice\PhpWord\Style\Paragraph|string */ public function getParagraphStyle() { diff --git a/src/PhpWord/Element/FormField.php b/src/PhpWord/Element/FormField.php index 23cded7229..ef8c22fe47 100644 --- a/src/PhpWord/Element/FormField.php +++ b/src/PhpWord/Element/FormField.php @@ -35,7 +35,7 @@ class FormField extends Text /** * Form field name. * - * @var bool|int|string + * @var ?string */ private $name; @@ -53,7 +53,7 @@ class FormField extends Text /** * Value. * - * @var bool|int|string + * @var null|bool|int|string */ private $value; @@ -105,7 +105,7 @@ public function setType($value) /** * Get name. * - * @return string + * @return ?string */ public function getName() { @@ -115,7 +115,7 @@ public function getName() /** * Set name. * - * @param bool|int|string $value + * @param ?string $value * * @return self */ @@ -153,7 +153,7 @@ public function setDefault($value) /** * Get value. * - * @return bool|int|string + * @return null|bool|int|string */ public function getValue() { @@ -163,7 +163,7 @@ public function getValue() /** * Set value. * - * @param bool|int|string $value + * @param null|bool|int|string $value * * @return self */ diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php index 2bb78acb74..f92f4bd572 100644 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -54,7 +54,7 @@ class Image extends AbstractElement /** * Image style. * - * @var ImageStyle + * @var ?ImageStyle */ private $style; @@ -159,7 +159,7 @@ public function __construct($source, $style = null, $watermark = false, $name = /** * Get Image style. * - * @return ImageStyle + * @return ?ImageStyle */ public function getStyle() { diff --git a/src/PhpWord/Element/Line.php b/src/PhpWord/Element/Line.php index 7659a11483..40ad75c799 100644 --- a/src/PhpWord/Element/Line.php +++ b/src/PhpWord/Element/Line.php @@ -27,7 +27,7 @@ class Line extends AbstractElement /** * Line style. * - * @var \PhpOffice\PhpWord\Style\Line + * @var ?\PhpOffice\PhpWord\Style\Line */ private $style; @@ -44,7 +44,7 @@ public function __construct($style = null) /** * Get line style. * - * @return \PhpOffice\PhpWord\Style\Line + * @return ?\PhpOffice\PhpWord\Style\Line */ public function getStyle() { diff --git a/src/PhpWord/Element/Link.php b/src/PhpWord/Element/Link.php index 0e6ada43c5..b8acba1d3b 100644 --- a/src/PhpWord/Element/Link.php +++ b/src/PhpWord/Element/Link.php @@ -43,14 +43,14 @@ class Link extends AbstractElement /** * Font style. * - * @var \PhpOffice\PhpWord\Style\Font|string + * @var null|\PhpOffice\PhpWord\Style\Font|string */ private $fontStyle; /** * Paragraph style. * - * @var \PhpOffice\PhpWord\Style\Paragraph|string + * @var null|\PhpOffice\PhpWord\Style\Paragraph|string */ private $paragraphStyle; @@ -109,7 +109,7 @@ public function getText() /** * Get Text style. * - * @return \PhpOffice\PhpWord\Style\Font|string + * @return null|\PhpOffice\PhpWord\Style\Font|string */ public function getFontStyle() { @@ -119,7 +119,7 @@ public function getFontStyle() /** * Get Paragraph style. * - * @return \PhpOffice\PhpWord\Style\Paragraph|string + * @return null|\PhpOffice\PhpWord\Style\Paragraph|string */ public function getParagraphStyle() { diff --git a/src/PhpWord/Element/ListItem.php b/src/PhpWord/Element/ListItem.php index 36484d90f9..d3f25c29b7 100644 --- a/src/PhpWord/Element/ListItem.php +++ b/src/PhpWord/Element/ListItem.php @@ -28,7 +28,7 @@ class ListItem extends AbstractElement /** * Element style. * - * @var \PhpOffice\PhpWord\Style\ListItem + * @var ?\PhpOffice\PhpWord\Style\ListItem */ private $style; @@ -71,7 +71,7 @@ public function __construct($text, $depth = 0, $fontStyle = null, $listStyle = n /** * Get style. * - * @return \PhpOffice\PhpWord\Style\ListItem + * @return ?\PhpOffice\PhpWord\Style\ListItem */ public function getStyle() { diff --git a/src/PhpWord/Element/ListItemRun.php b/src/PhpWord/Element/ListItemRun.php index 69274a520c..7a63337093 100644 --- a/src/PhpWord/Element/ListItemRun.php +++ b/src/PhpWord/Element/ListItemRun.php @@ -32,7 +32,7 @@ class ListItemRun extends TextRun /** * ListItem Style. * - * @var \PhpOffice\PhpWord\Style\ListItem + * @var ?\PhpOffice\PhpWord\Style\ListItem */ private $style; @@ -66,7 +66,7 @@ public function __construct($depth = 0, $listStyle = null, $paragraphStyle = nul /** * Get ListItem style. * - * @return \PhpOffice\PhpWord\Style\ListItem + * @return ?\PhpOffice\PhpWord\Style\ListItem */ public function getStyle() { diff --git a/src/PhpWord/Element/OLEObject.php b/src/PhpWord/Element/OLEObject.php index df7396cfe1..73645e07f2 100644 --- a/src/PhpWord/Element/OLEObject.php +++ b/src/PhpWord/Element/OLEObject.php @@ -35,7 +35,7 @@ class OLEObject extends AbstractElement /** * Image Style. * - * @var \PhpOffice\PhpWord\Style\Image + * @var ?\PhpOffice\PhpWord\Style\Image */ private $style; @@ -100,7 +100,7 @@ public function getSource() /** * Get object style. * - * @return \PhpOffice\PhpWord\Style\Image + * @return ?\PhpOffice\PhpWord\Style\Image */ public function getStyle() { diff --git a/src/PhpWord/Element/PreserveText.php b/src/PhpWord/Element/PreserveText.php index 19f468bb41..7370b63743 100644 --- a/src/PhpWord/Element/PreserveText.php +++ b/src/PhpWord/Element/PreserveText.php @@ -29,21 +29,21 @@ class PreserveText extends AbstractElement /** * Text content. * - * @var array|string + * @var null|array|string */ private $text; /** * Text style. * - * @var \PhpOffice\PhpWord\Style\Font|string + * @var null|\PhpOffice\PhpWord\Style\Font|string */ private $fontStyle; /** * Paragraph style. * - * @var \PhpOffice\PhpWord\Style\Paragraph|string + * @var null|\PhpOffice\PhpWord\Style\Paragraph|string */ private $paragraphStyle; @@ -69,7 +69,7 @@ public function __construct($text = null, $fontStyle = null, $paragraphStyle = n /** * Get Text style. * - * @return \PhpOffice\PhpWord\Style\Font|string + * @return null|\PhpOffice\PhpWord\Style\Font|string */ public function getFontStyle() { @@ -79,7 +79,7 @@ public function getFontStyle() /** * Get Paragraph style. * - * @return \PhpOffice\PhpWord\Style\Paragraph|string + * @return null|\PhpOffice\PhpWord\Style\Paragraph|string */ public function getParagraphStyle() { @@ -89,7 +89,7 @@ public function getParagraphStyle() /** * Get Text content. * - * @return array|string + * @return null|array|string */ public function getText() { diff --git a/src/PhpWord/Element/Row.php b/src/PhpWord/Element/Row.php index d2f0ecac89..f97df595f2 100644 --- a/src/PhpWord/Element/Row.php +++ b/src/PhpWord/Element/Row.php @@ -29,14 +29,14 @@ class Row extends AbstractElement /** * Row height. * - * @var int + * @var ?int */ private $height; /** * Row style. * - * @var \PhpOffice\PhpWord\Style\Row + * @var ?\PhpOffice\PhpWord\Style\Row */ private $style; @@ -89,7 +89,7 @@ public function getCells() /** * Get row style. * - * @return \PhpOffice\PhpWord\Style\Row + * @return ?\PhpOffice\PhpWord\Style\Row */ public function getStyle() { @@ -99,7 +99,7 @@ public function getStyle() /** * Get row height. * - * @return int + * @return ?int */ public function getHeight() { diff --git a/src/PhpWord/Element/SDT.php b/src/PhpWord/Element/SDT.php index b7ff31ec21..561cb9dd9e 100644 --- a/src/PhpWord/Element/SDT.php +++ b/src/PhpWord/Element/SDT.php @@ -34,7 +34,7 @@ class SDT extends Text /** * Value. * - * @var bool|int|string + * @var null|bool|int|string */ private $value; @@ -100,7 +100,7 @@ public function setType($value) /** * Get value. * - * @return bool|int|string + * @return null|bool|int|string */ public function getValue() { @@ -110,7 +110,7 @@ public function getValue() /** * Set value. * - * @param bool|int|string $value + * @param null|bool|int|string $value * * @return self */ diff --git a/src/PhpWord/Element/Section.php b/src/PhpWord/Element/Section.php index d77645ff62..68af674016 100644 --- a/src/PhpWord/Element/Section.php +++ b/src/PhpWord/Element/Section.php @@ -31,7 +31,7 @@ class Section extends AbstractContainer /** * Section style. * - * @var \PhpOffice\PhpWord\Style\Section + * @var ?\PhpOffice\PhpWord\Style\Section */ private $style; @@ -60,7 +60,7 @@ class Section extends AbstractContainer * Create new instance. * * @param int $sectionCount - * @param null|array|\PhpOffice\PhpWord\Style $style + * @param null|array|\PhpOffice\PhpWord\Style|string $style */ public function __construct($sectionCount, $style = null) { @@ -87,7 +87,7 @@ public function setStyle($style = null): void /** * Get section style. * - * @return \PhpOffice\PhpWord\Style\Section + * @return ?\PhpOffice\PhpWord\Style\Section */ public function getStyle() { diff --git a/src/PhpWord/Element/Shape.php b/src/PhpWord/Element/Shape.php index 930ed8a95d..15161f892e 100644 --- a/src/PhpWord/Element/Shape.php +++ b/src/PhpWord/Element/Shape.php @@ -36,7 +36,7 @@ class Shape extends AbstractElement /** * Shape style. * - * @var \PhpOffice\PhpWord\Style\Shape + * @var ?\PhpOffice\PhpWord\Style\Shape */ private $style; @@ -80,7 +80,7 @@ public function setType($value = null) /** * Get shape style. * - * @return \PhpOffice\PhpWord\Style\Shape + * @return ?\PhpOffice\PhpWord\Style\Shape */ public function getStyle() { diff --git a/src/PhpWord/Element/Table.php b/src/PhpWord/Element/Table.php index 308e7bc63e..53a828a9ea 100644 --- a/src/PhpWord/Element/Table.php +++ b/src/PhpWord/Element/Table.php @@ -27,7 +27,7 @@ class Table extends AbstractElement /** * Table style. * - * @var \PhpOffice\PhpWord\Style\Table + * @var ?\PhpOffice\PhpWord\Style\Table */ private $style; @@ -41,7 +41,7 @@ class Table extends AbstractElement /** * Table width. * - * @var int + * @var ?int */ private $width; @@ -102,7 +102,7 @@ public function getRows() /** * Get table style. * - * @return \PhpOffice\PhpWord\Style\Table + * @return null|\PhpOffice\PhpWord\Style\Table|string */ public function getStyle() { @@ -112,7 +112,7 @@ public function getStyle() /** * Get table width. * - * @return int + * @return ?int */ public function getWidth() { diff --git a/src/PhpWord/Element/Text.php b/src/PhpWord/Element/Text.php index 6a11e82f75..9695395324 100644 --- a/src/PhpWord/Element/Text.php +++ b/src/PhpWord/Element/Text.php @@ -29,7 +29,7 @@ class Text extends AbstractElement /** * Text content. * - * @var string + * @var ?string */ protected $text; @@ -147,7 +147,7 @@ public function setText($text) /** * Get Text content. * - * @return string + * @return ?string */ public function getText() { diff --git a/src/PhpWord/Element/TextBox.php b/src/PhpWord/Element/TextBox.php index 7472f4bc34..af37f65772 100644 --- a/src/PhpWord/Element/TextBox.php +++ b/src/PhpWord/Element/TextBox.php @@ -34,7 +34,7 @@ class TextBox extends AbstractContainer /** * TextBox style. * - * @var \PhpOffice\PhpWord\Style\TextBox + * @var ?\PhpOffice\PhpWord\Style\TextBox */ private $style; @@ -51,7 +51,7 @@ public function __construct($style = null) /** * Get textbox style. * - * @return \PhpOffice\PhpWord\Style\TextBox + * @return ?\PhpOffice\PhpWord\Style\TextBox */ public function getStyle() { diff --git a/src/PhpWord/Element/TextBreak.php b/src/PhpWord/Element/TextBreak.php index 088503a40e..c3cd087d74 100644 --- a/src/PhpWord/Element/TextBreak.php +++ b/src/PhpWord/Element/TextBreak.php @@ -28,14 +28,14 @@ class TextBreak extends AbstractElement /** * Paragraph style. * - * @var \PhpOffice\PhpWord\Style\Paragraph|string + * @var null|\PhpOffice\PhpWord\Style\Paragraph|string */ private $paragraphStyle; /** * Text style. * - * @var \PhpOffice\PhpWord\Style\Font|string + * @var null|\PhpOffice\PhpWord\Style\Font|string */ private $fontStyle; @@ -82,7 +82,7 @@ public function setFontStyle($style = null, $paragraphStyle = null) /** * Get Text style. * - * @return \PhpOffice\PhpWord\Style\Font|string + * @return null|\PhpOffice\PhpWord\Style\Font|string */ public function getFontStyle() { @@ -113,7 +113,7 @@ public function setParagraphStyle($style = null) /** * Get Paragraph style. * - * @return \PhpOffice\PhpWord\Style\Paragraph|string + * @return null|\PhpOffice\PhpWord\Style\Paragraph|string */ public function getParagraphStyle() { diff --git a/src/PhpWord/Element/Title.php b/src/PhpWord/Element/Title.php index 947e941696..461a03fc5a 100644 --- a/src/PhpWord/Element/Title.php +++ b/src/PhpWord/Element/Title.php @@ -43,7 +43,7 @@ class Title extends AbstractElement /** * Name of the heading style, e.g. 'Heading1'. * - * @var string + * @var ?string */ private $style; @@ -80,7 +80,7 @@ public function __construct($text, $depth = 1) /** * Get Title Text content. * - * @return string + * @return string|TextRun */ public function getText() { @@ -100,7 +100,7 @@ public function getDepth() /** * Get Title style. * - * @return string + * @return ?string */ public function getStyle() { diff --git a/src/PhpWord/Escaper/AbstractEscaper.php b/src/PhpWord/Escaper/AbstractEscaper.php index 571d5df92e..28e33818a4 100644 --- a/src/PhpWord/Escaper/AbstractEscaper.php +++ b/src/PhpWord/Escaper/AbstractEscaper.php @@ -25,7 +25,7 @@ abstract class AbstractEscaper implements EscaperInterface { /** - * @param string $input + * @param ?string $input * * @return string */ diff --git a/src/PhpWord/Escaper/Rtf.php b/src/PhpWord/Escaper/Rtf.php index b627bcd11e..842e3adc91 100644 --- a/src/PhpWord/Escaper/Rtf.php +++ b/src/PhpWord/Escaper/Rtf.php @@ -47,7 +47,7 @@ protected function escapeMultibyteCharacter($code) /** * @see http://www.randomchaos.com/documents/?source=php_and_unicode * - * @param string $input + * @param ?string $input */ protected function escapeSingleValue($input) { diff --git a/src/PhpWord/Metadata/DocInfo.php b/src/PhpWord/Metadata/DocInfo.php index bdb2b7d37b..f7229cf0a5 100644 --- a/src/PhpWord/Metadata/DocInfo.php +++ b/src/PhpWord/Metadata/DocInfo.php @@ -441,7 +441,7 @@ public function getCustomPropertyValue($propertyName) * * @param string $propertyName * - * @return string + * @return ?string */ public function getCustomPropertyType($propertyName) { diff --git a/src/PhpWord/Metadata/Settings.php b/src/PhpWord/Metadata/Settings.php index e0e5ae0a66..e3e3cd9b7f 100644 --- a/src/PhpWord/Metadata/Settings.php +++ b/src/PhpWord/Metadata/Settings.php @@ -149,7 +149,7 @@ class Settings /** * The allowed amount of whitespace before hyphenation is applied. * - * @var null|float + * @var null|float|int */ private $hyphenationZone; @@ -213,7 +213,7 @@ public function hasHideSpellingErrors() /** * Hide spelling errors. * - * @param bool $hideSpellingErrors + * @param ?bool $hideSpellingErrors */ public function setHideSpellingErrors($hideSpellingErrors): void { @@ -233,7 +233,7 @@ public function hasHideGrammaticalErrors() /** * Hide grammatical errors. * - * @param bool $hideGrammaticalErrors + * @param ?bool $hideGrammaticalErrors */ public function setHideGrammaticalErrors($hideGrammaticalErrors): void { @@ -249,7 +249,7 @@ public function hasEvenAndOddHeaders() } /** - * @param bool $evenAndOddHeaders + * @param ?bool $evenAndOddHeaders */ public function setEvenAndOddHeaders($evenAndOddHeaders): void { @@ -285,7 +285,7 @@ public function hasTrackRevisions() } /** - * @param bool $trackRevisions + * @param ?bool $trackRevisions */ public function setTrackRevisions($trackRevisions): void { @@ -301,7 +301,7 @@ public function hasDoNotTrackMoves() } /** - * @param bool $doNotTrackMoves + * @param ?bool $doNotTrackMoves */ public function setDoNotTrackMoves($doNotTrackMoves): void { @@ -317,7 +317,7 @@ public function hasDoNotTrackFormatting() } /** - * @param bool $doNotTrackFormatting + * @param ?bool $doNotTrackFormatting */ public function setDoNotTrackFormatting($doNotTrackFormatting): void { @@ -391,7 +391,7 @@ public function hasUpdateFields() } /** - * @param bool $updateFields + * @param ?bool $updateFields */ public function setUpdateFields($updateFields): void { @@ -451,7 +451,7 @@ public function setConsecutiveHyphenLimit($consecutiveHyphenLimit): void } /** - * @return null|float + * @return null|float|int */ public function getHyphenationZone() { @@ -459,7 +459,7 @@ public function getHyphenationZone() } /** - * @param float $hyphenationZone Measurement unit is twip + * @param null|float|int $hyphenationZone Measurement unit is twip */ public function setHyphenationZone($hyphenationZone): void { diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index 70ee652b29..69efa76723 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -211,7 +211,7 @@ public function getSection($index) /** * Create new section. * - * @param array $style + * @param null|array|string $style * * @return \PhpOffice\PhpWord\Element\Section */ diff --git a/src/PhpWord/Shared/Converter.php b/src/PhpWord/Shared/Converter.php index 53891f5292..365aa141b0 100644 --- a/src/PhpWord/Shared/Converter.php +++ b/src/PhpWord/Shared/Converter.php @@ -374,7 +374,7 @@ public static function htmlToRgb($value) * * @param string $value * - * @return float + * @return ?float */ public static function cssToPoint($value) { diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 0b35158507..4a9057e60c 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -271,7 +271,7 @@ protected static function parseNode($node, $element, $styles = [], $data = []): * Parse child nodes. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param \PhpOffice\PhpWord\Element\AbstractContainer|Row|Table $element * @param array $styles * @param array $data */ diff --git a/src/PhpWord/Shared/XMLReader.php b/src/PhpWord/Shared/XMLReader.php index 73762db2ea..99c59931e9 100644 --- a/src/PhpWord/Shared/XMLReader.php +++ b/src/PhpWord/Shared/XMLReader.php @@ -99,12 +99,12 @@ public function getDomFromString($content) * @param string $path * @param DOMElement $contextNode * - * @return DOMNodeList + * @return DOMNodeList */ public function getElements($path, ?DOMElement $contextNode = null) { if ($this->dom === null) { - return []; + return new DOMNodeList(); } if ($this->xpath === null) { $this->xpath = new DOMXpath($this->dom); diff --git a/src/PhpWord/Shared/ZipArchive.php b/src/PhpWord/Shared/ZipArchive.php index 74922b2c2b..ce4d22533e 100644 --- a/src/PhpWord/Shared/ZipArchive.php +++ b/src/PhpWord/Shared/ZipArchive.php @@ -30,8 +30,8 @@ * * @method bool addFile(string $filename, string $localname = null) * @method bool addFromString(string $localname, string $contents) - * @method string getNameIndex(int $index) - * @method int locateName(string $name) + * @method false|string getNameIndex(int $index) + * @method false|int locateName(string $name) * * @since 0.10.0 */ @@ -396,7 +396,7 @@ public function pclzipGetNameIndex($index) * * @param string $filename Filename for the file in zip archive * - * @return int + * @return false|int */ public function pclzipLocateName($filename) { diff --git a/src/PhpWord/Style.php b/src/PhpWord/Style.php index 23107ef535..cd27bffec6 100644 --- a/src/PhpWord/Style.php +++ b/src/PhpWord/Style.php @@ -173,7 +173,7 @@ public static function getStyles() * * @param string $styleName * - * @return \PhpOffice\PhpWord\Style\AbstractStyle Paragraph|Font|Table|Numbering + * @return ?\PhpOffice\PhpWord\Style\AbstractStyle Paragraph|Font|Table|Numbering */ public static function getStyle($styleName) { diff --git a/src/PhpWord/Style/AbstractStyle.php b/src/PhpWord/Style/AbstractStyle.php index a4be670dac..4e5def618d 100644 --- a/src/PhpWord/Style/AbstractStyle.php +++ b/src/PhpWord/Style/AbstractStyle.php @@ -30,7 +30,7 @@ abstract class AbstractStyle /** * Style name. * - * @var string + * @var ?string */ protected $styleName; @@ -62,7 +62,7 @@ abstract class AbstractStyle /** * Get style name. * - * @return string + * @return ?string */ public function getStyleName() { @@ -161,7 +161,7 @@ public function getChildStyleValue($substyleObject, $substyleProperty) * Check if the set method is exists. Throws an exception? * * @param string $key - * @param string $value + * @param array|int|string $value * * @return self */ @@ -202,10 +202,10 @@ public function setStyleByArray($values = []) /** * Set default for null and empty value. * - * @param string $value (was: mixed) - * @param string $default (was: mixed) + * @param ?string $value + * @param string $default * - * @return string (was: mixed) + * @return string */ protected function setNonEmptyVal($value, $default) { @@ -253,7 +253,7 @@ protected function setNumericVal($value, $default = null) /** * Set integer value: Convert string that contains only numeric into integer. * - * @param null|int $value + * @param null|float|int|string $value * @param null|int $default * * @return null|int diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index b2bd9aeb21..07596a3911 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -107,7 +107,7 @@ class Cell extends Border /** * Width. * - * @var int + * @var ?int */ private $width; @@ -270,7 +270,7 @@ public function setShading($value = null) /** * Get cell width. * - * @return int + * @return ?int */ public function getWidth() { diff --git a/src/PhpWord/Style/Paragraph.php b/src/PhpWord/Style/Paragraph.php index e22016517b..e7b97afb1b 100644 --- a/src/PhpWord/Style/Paragraph.php +++ b/src/PhpWord/Style/Paragraph.php @@ -99,7 +99,7 @@ class Paragraph extends Border /** * Text line height. * - * @var int + * @var float|int */ private $lineHeight; diff --git a/src/PhpWord/Style/Section.php b/src/PhpWord/Style/Section.php index 29e06bf3cf..d4ede285e7 100644 --- a/src/PhpWord/Style/Section.php +++ b/src/PhpWord/Style/Section.php @@ -159,7 +159,7 @@ class Section extends Border * - evenPage: Even page section break * - oddPage: Odd page section break * - * @var string + * @var ?string */ private $breakType; @@ -176,7 +176,7 @@ class Section extends Border * Vertical Text Alignment on Page * One of \PhpOffice\PhpWord\SimpleType\VerticalJc. * - * @var string + * @var ?string */ private $vAlign; @@ -224,7 +224,7 @@ public function setPaperSize($value = '') * Set Setting Value. * * @param string $key - * @param string $value + * @param array|int|string $value * * @return self */ @@ -587,7 +587,7 @@ public function setColsSpace($value = null) /** * Get Break Type. * - * @return string + * @return ?string */ public function getBreakType() { @@ -635,7 +635,7 @@ public function setLineNumbering($value = null) /** * Get vertical alignment. * - * @return string + * @return ?string */ public function getVAlign() { diff --git a/src/PhpWord/Style/Table.php b/src/PhpWord/Style/Table.php index b267c7568f..1833024d14 100644 --- a/src/PhpWord/Style/Table.php +++ b/src/PhpWord/Style/Table.php @@ -131,7 +131,7 @@ class Table extends Border private $unit = TblWidth::AUTO; /** - * @var float|int cell spacing value + * @var null|float|int cell spacing value */ protected $cellSpacing; @@ -143,7 +143,7 @@ class Table extends Border /** * Position. * - * @var \PhpOffice\PhpWord\Style\TablePosition + * @var ?\PhpOffice\PhpWord\Style\TablePosition */ private $position; @@ -188,7 +188,7 @@ public function __construct($tableStyle = null, $firstRowStyle = null) } /** - * @param float|int $cellSpacing + * @param null|float|int $cellSpacing */ public function setCellSpacing($cellSpacing = null): void { @@ -196,7 +196,7 @@ public function setCellSpacing($cellSpacing = null): void } /** - * @return float|int + * @return null|float|int */ public function getCellSpacing() { @@ -216,7 +216,7 @@ public function getFirstRow() /** * Get background. * - * @return string + * @return ?string */ public function getBgColor() { @@ -704,7 +704,7 @@ private function setTableOnlyProperty($property, $value, $isNumeric = true) /** * Get position. * - * @return \PhpOffice\PhpWord\Style\TablePosition + * @return ?\PhpOffice\PhpWord\Style\TablePosition */ public function getPosition() { @@ -726,7 +726,7 @@ public function setPosition($value = null) } /** - * @return TblWidthComplexType + * @return ?TblWidthComplexType */ public function getIndent() { diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index e6731b0357..6ef22fc538 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -250,7 +250,7 @@ protected static function ensureMacroCompleted($macro) } /** - * @param string $subject + * @param ?string $subject * * @return string */ diff --git a/src/PhpWord/Writer/HTML/Style/AbstractStyle.php b/src/PhpWord/Writer/HTML/Style/AbstractStyle.php index 19362d3670..5a5fcacd79 100644 --- a/src/PhpWord/Writer/HTML/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/HTML/Style/AbstractStyle.php @@ -36,7 +36,7 @@ abstract class AbstractStyle /** * Style. * - * @var array|\PhpOffice\PhpWord\Style\AbstractStyle + * @var null|array|\PhpOffice\PhpWord\Style\AbstractStyle */ private $style; @@ -78,7 +78,7 @@ public function getParentWriter() /** * Get style. * - * @return array|\PhpOffice\PhpWord\Style\AbstractStyle $style + * @return null|array|\PhpOffice\PhpWord\Style\AbstractStyle|string */ public function getStyle() { diff --git a/src/PhpWord/Writer/ODText/Part/Content.php b/src/PhpWord/Writer/ODText/Part/Content.php index d4b92cfd79..8c96650240 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -280,7 +280,6 @@ private function getContainerStyle($container, &$paragraphStyleCount, &$fontStyl $sty->setAlignment($style->getAlignment()); $this->imageParagraphStyles[] = $sty; } elseif ($element instanceof Table) { - /** @var \PhpOffice\PhpWord\Style\Table $style */ $style = $element->getStyle(); if (is_string($style)) { $style = Style::getStyle($style); diff --git a/tests/PhpWordTests/Reader/Word2007/ElementTest.php b/tests/PhpWordTests/Reader/Word2007/ElementTest.php index e4c74f2242..9c002236ed 100644 --- a/tests/PhpWordTests/Reader/Word2007/ElementTest.php +++ b/tests/PhpWordTests/Reader/Word2007/ElementTest.php @@ -270,11 +270,11 @@ public function testReadTitleStyle(): void self::assertEquals('Title', $title->getStyle()); self::assertEquals('This is a non formatted title', $title->getText()); - self::assertInstanceOf('PhpOffice\PhpWord\Element\Title', $elements[1]); + self::assertInstanceOf(\PhpOffice\PhpWord\Element\Title::class, $elements[1]); /** @var \PhpOffice\PhpWord\Element\Title $formattedTitle */ $formattedTitle = $elements[1]; self::assertEquals('Title', $formattedTitle->getStyle()); - self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $formattedTitle->getText()); + self::assertInstanceOf(\PhpOffice\PhpWord\Element\TextRun::class, $formattedTitle->getText()); } /** diff --git a/tests/PhpWordTests/Shared/XMLReaderTest.php b/tests/PhpWordTests/Shared/XMLReaderTest.php index 43090cfba1..9ba8e4548b 100644 --- a/tests/PhpWordTests/Shared/XMLReaderTest.php +++ b/tests/PhpWordTests/Shared/XMLReaderTest.php @@ -87,7 +87,7 @@ public function testCountElements(): void public function testReturnNullOnNonExistingNode(): void { $reader = new XMLReader(); - self::assertEmpty($reader->getElements('/element/children')); + self::assertSame(0, $reader->getElements('/element/children')->length); $reader->getDomFromString('AAA'); self::assertNull($reader->getElement('/element/children')); diff --git a/tests/PhpWordTests/XmlDocument.php b/tests/PhpWordTests/XmlDocument.php index 6604eccfa0..80d64c4357 100644 --- a/tests/PhpWordTests/XmlDocument.php +++ b/tests/PhpWordTests/XmlDocument.php @@ -19,6 +19,7 @@ use DOMDocument; use DOMElement; +use DOMNode; use DOMNodeList; use DOMXPath; @@ -135,7 +136,7 @@ public function getFileDom($file = '') * @param string $path * @param string $file * - * @return DOMNodeList + * @return DOMNodeList */ public function getNodeList($path, $file = '') { @@ -160,7 +161,7 @@ public function getNodeList($path, $file = '') * @param string $path * @param string $file * - * @return DOMElement + * @return null|DOMElement */ public function getElement($path, $file = '') { @@ -216,7 +217,7 @@ public function getElementAttribute($path, $attribute, $file = '') * @param string $path * @param string $file * - * @return string + * @return bool */ public function elementExists($path, $file = '') { @@ -234,20 +235,15 @@ public function elementExists($path, $file = '') * @param string $path * @param string $file * - * @return string + * @return false|string */ public function printXml($path = '/', $file = '') { if (!$file) { $file = $this->defaultFile; } - $element = $this->getElement($path, $file); - if ($element instanceof DOMDocument) { - $element->formatOutput = true; - $element->preserveWhiteSpace = false; - return $element->saveXML(); - } + $element = $this->getElement($path, $file); $newdoc = new DOMDocument(); $newdoc->formatOutput = true; From 9b8a84c39c67443aa89b9b7759e9fd5bb8b89c44 Mon Sep 17 00:00:00 2001 From: Levi Voorintholt Date: Thu, 29 Jun 2023 15:33:06 +0200 Subject: [PATCH 103/246] Change order of files inside Word file to be compatible with common mimetype detection --- src/PhpWord/Writer/Word2007.php | 5 +++-- tests/PhpWordTests/Writer/Word2007Test.php | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/Writer/Word2007.php b/src/PhpWord/Writer/Word2007.php index 3895584671..9e17efa611 100644 --- a/src/PhpWord/Writer/Word2007.php +++ b/src/PhpWord/Writer/Word2007.php @@ -52,14 +52,15 @@ public function __construct(?PhpWord $phpWord = null) $this->setPhpWord($phpWord); // Create parts + // The first four files need to be in this order for Mimetype detection to work $this->parts = [ 'ContentTypes' => '[Content_Types].xml', 'Rels' => '_rels/.rels', + 'RelsDocument' => 'word/_rels/document.xml.rels', + 'Document' => 'word/document.xml', 'DocPropsApp' => 'docProps/app.xml', 'DocPropsCore' => 'docProps/core.xml', 'DocPropsCustom' => 'docProps/custom.xml', - 'RelsDocument' => 'word/_rels/document.xml.rels', - 'Document' => 'word/document.xml', 'Comments' => 'word/comments.xml', 'Styles' => 'word/styles.xml', 'Numbering' => 'word/numbering.xml', diff --git a/tests/PhpWordTests/Writer/Word2007Test.php b/tests/PhpWordTests/Writer/Word2007Test.php index 32b046f01d..94f9caf8a1 100644 --- a/tests/PhpWordTests/Writer/Word2007Test.php +++ b/tests/PhpWordTests/Writer/Word2007Test.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWordTests\Writer; +use finfo; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\Writer\Word2007; @@ -192,4 +193,25 @@ public function testSetUseDiskCachingException(): void $object = new Word2007(); $object->setUseDiskCaching(true, $dir); } + + /** + * File is detected as Word 2007. + */ + public function testMime(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $section->addText('Test 1'); + + $writer = new Word2007($phpWord); + $file = __DIR__ . '/../_files/temp.docx'; + $writer->save($file); + + $finfo = new finfo(FILEINFO_MIME_TYPE); + $mime = $finfo->file($file); + + self::assertEquals('application/vnd.openxmlformats-officedocument.wordprocessingml.document', $mime); + + unlink($file); + } } From 66c794257be6e330f6a9b083f0187abebb8c4914 Mon Sep 17 00:00:00 2001 From: Terry Date: Tue, 1 Aug 2023 15:08:03 +0800 Subject: [PATCH 104/246] Update Cell.php --- src/PhpWord/Style/Cell.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index 07596a3911..6a313d549f 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -34,6 +34,10 @@ class Cell extends Border * Top to Bottom, Right to Left. */ const TEXT_DIR_TBRL = 'tbRl'; + /** + * Top to Bottom, Right to Left, Vertical + */ + const TEXT_DIR_TBRLV = 'tbRlV'; /** * Bottom to Top, Left to Right. */ From f5e9bcd7f3f6ea3b17f48bd0c6c85b0901757270 Mon Sep 17 00:00:00 2001 From: Terry Date: Tue, 1 Aug 2023 15:21:43 +0800 Subject: [PATCH 105/246] Update Cell.php --- src/PhpWord/Style/Cell.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index 6a313d549f..73ccb67a92 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -166,7 +166,14 @@ public function getTextDirection() */ public function setTextDirection($value = null) { - $enum = [self::TEXT_DIR_BTLR, self::TEXT_DIR_TBRL]; + $enum = [ + self::TEXT_DIR_BTLR, + self::TEXT_DIR_TBRL, + self::TEXT_DIR_LRTB, + self::TEXT_DIR_LRTBV, + self::TEXT_DIR_TBRLV, + self::TEXT_DIR_TBLRV, + ]; $this->textDirection = $this->setEnumVal($value, $enum, $this->textDirection); return $this; From 8d0466221e682c05e3635cabd4815cb756745e76 Mon Sep 17 00:00:00 2001 From: Terry Date: Tue, 1 Aug 2023 15:23:47 +0800 Subject: [PATCH 106/246] Update Cell.php --- src/PhpWord/Style/Cell.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index 73ccb67a92..6015c8b43a 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -34,10 +34,6 @@ class Cell extends Border * Top to Bottom, Right to Left. */ const TEXT_DIR_TBRL = 'tbRl'; - /** - * Top to Bottom, Right to Left, Vertical - */ - const TEXT_DIR_TBRLV = 'tbRlV'; /** * Bottom to Top, Left to Right. */ From 39f379c2f03ed66202d861345afd62c355996ae4 Mon Sep 17 00:00:00 2001 From: Terry Date: Tue, 1 Aug 2023 15:29:48 +0800 Subject: [PATCH 107/246] Update Cell.php --- src/PhpWord/Style/Cell.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index 6015c8b43a..aa065f01de 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -163,12 +163,12 @@ public function getTextDirection() public function setTextDirection($value = null) { $enum = [ - self::TEXT_DIR_BTLR, - self::TEXT_DIR_TBRL, - self::TEXT_DIR_LRTB, - self::TEXT_DIR_LRTBV, - self::TEXT_DIR_TBRLV, - self::TEXT_DIR_TBLRV, + self::TEXT_DIR_BTLR, + self::TEXT_DIR_TBRL, + self::TEXT_DIR_LRTB, + self::TEXT_DIR_LRTBV, + self::TEXT_DIR_TBRLV, + self::TEXT_DIR_TBLRV, ]; $this->textDirection = $this->setEnumVal($value, $enum, $this->textDirection); From ecde3258f7395f86698d51f1279eaeaa1f839a13 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 11:13:48 +0000 Subject: [PATCH 108/246] Bump symfony/process from 4.4.44 to 5.4.26 Bumps [symfony/process](https://github.com/symfony/process) from 4.4.44 to 5.4.26. - [Release notes](https://github.com/symfony/process/releases) - [Changelog](https://github.com/symfony/process/blob/6.3/CHANGELOG.md) - [Commits](https://github.com/symfony/process/compare/v4.4.44...v5.4.26) --- updated-dependencies: - dependency-name: symfony/process dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- composer.lock | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index 89ebee9a10..445b372f5f 100644 --- a/composer.json +++ b/composer.json @@ -79,7 +79,7 @@ "phpmd/phpmd": "^2.13", "phpunit/phpunit": ">=7.0", "tecnickcom/tcpdf": "^6.5", - "symfony/process": "^4.4", + "symfony/process": "^4.4 || ^5.0", "friendsofphp/php-cs-fixer": "^3.3", "phpstan/phpstan-phpunit": "@stable" }, diff --git a/composer.lock b/composer.lock index 004b063a11..11cb71fe1e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "dbc28cee4451207beb40bbf5aeff9f1d", + "content-hash": "2d45739d1122eb36186b5cfe7cd6d6ab", "packages": [ { "name": "laminas/laminas-escaper", @@ -4599,20 +4599,20 @@ }, { "name": "symfony/process", - "version": "v4.4.44", + "version": "v5.4.26", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "5cee9cdc4f7805e2699d9fd66991a0e6df8252a2" + "reference": "1a44dc377ec86a50fab40d066cd061e28a6b482f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/5cee9cdc4f7805e2699d9fd66991a0e6df8252a2", - "reference": "5cee9cdc4f7805e2699d9fd66991a0e6df8252a2", + "url": "https://api.github.com/repos/symfony/process/zipball/1a44dc377ec86a50fab40d066cd061e28a6b482f", + "reference": "1a44dc377ec86a50fab40d066cd061e28a6b482f", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", "symfony/polyfill-php80": "^1.16" }, "type": "library", @@ -4641,7 +4641,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com/", "support": { - "source": "https://github.com/symfony/process/tree/v4.4.44" + "source": "https://github.com/symfony/process/tree/v5.4.26" }, "funding": [ { @@ -4657,7 +4657,7 @@ "type": "tidelift" } ], - "time": "2022-06-27T13:16:42+00:00" + "time": "2023-07-12T15:44:31+00:00" }, { "name": "symfony/service-contracts", From 6fe34e354b25811faa9bd01403609c8bc5c4b196 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Wed, 2 Aug 2023 10:25:31 +0200 Subject: [PATCH 109/246] Bug fix: strtr using empty string The php function strtr doesn't support empty strings as replacement. To delete a character str_replace is required. --- src/PhpWord/Shared/PCLZip/pclzip.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Shared/PCLZip/pclzip.lib.php b/src/PhpWord/Shared/PCLZip/pclzip.lib.php index 62927497bb..5243b3c3a0 100644 --- a/src/PhpWord/Shared/PCLZip/pclzip.lib.php +++ b/src/PhpWord/Shared/PCLZip/pclzip.lib.php @@ -1597,7 +1597,7 @@ public function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_ if (is_string($p_options_list[$i + 1])) { // ----- Remove spaces - $p_options_list[$i + 1] = strtr($p_options_list[$i + 1], ' ', ''); + $p_options_list[$i + 1] = str_replace(' ', '', $p_options_list[$i + 1]); // ----- Parse items $v_work_list = explode(",", $p_options_list[$i + 1]); From 1bd6155fd918fa3019fff77d8c4cf01b7192f079 Mon Sep 17 00:00:00 2001 From: Hannes Dorn Date: Wed, 2 Aug 2023 14:24:15 +0200 Subject: [PATCH 110/246] Hotfix: In headings hyperlinks are ignored. Added w:hyperlink to xpath filter --- src/PhpWord/Reader/Word2007/AbstractPart.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index f1bea082df..3691df1297 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -151,7 +151,11 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par } elseif ($headingDepth !== null) { // Heading or Title $textContent = null; - $nodes = $xmlReader->getElements('w:r', $domNode); + // 2023-08-02 hannes@dorn.cc + // $nodes = $xmlReader->getElements('w:r', $domNode); + // delivers only text paragraphs, but no hyperlinks + // I extended xpath with w:hyperlink + $nodes = $xmlReader->getElements('w:r|w:hyperlink', $domNode); if ($nodes->length === 1) { $textContent = htmlspecialchars($xmlReader->getValue('w:t', $nodes->item(0)), ENT_QUOTES, 'UTF-8'); } else { From 736353409dca4a295f3e4362857b5db28dbe4624 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Aug 2023 09:57:23 +0000 Subject: [PATCH 111/246] Bump phpunit/phpunit from 9.6.8 to 9.6.10 Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.8 to 9.6.10. - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/9.6.10/ChangeLog-9.6.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.6.8...9.6.10) --- updated-dependencies: - dependency-name: phpunit/phpunit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/composer.lock b/composer.lock index 11cb71fe1e..189f67eb60 100644 --- a/composer.lock +++ b/composer.lock @@ -955,16 +955,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.15.5", + "version": "v4.16.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e" + "reference": "19526a33fb561ef417e822e85f08a00db4059c17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/11e2663a5bc9db5d714eedb4277ee300403b4a9e", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", + "reference": "19526a33fb561ef417e822e85f08a00db4059c17", "shasum": "" }, "require": { @@ -1005,9 +1005,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.5" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" }, - "time": "2023-05-19T20:20:00+00:00" + "time": "2023-06-25T14:52:30+00:00" }, { "name": "paragonie/random_compat", @@ -1575,16 +1575,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.26", + "version": "9.2.27", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1" + "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", - "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/b0a88255cb70d52653d80c890bd7f38740ea50d1", + "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1", "shasum": "" }, "require": { @@ -1640,7 +1640,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.27" }, "funding": [ { @@ -1648,7 +1649,7 @@ "type": "github" } ], - "time": "2023-03-06T12:58:08+00:00" + "time": "2023-07-26T13:44:30+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1893,16 +1894,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.8", + "version": "9.6.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "17d621b3aff84d0c8b62539e269e87d8d5baa76e" + "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/17d621b3aff84d0c8b62539e269e87d8d5baa76e", - "reference": "17d621b3aff84d0c8b62539e269e87d8d5baa76e", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a6d351645c3fe5a30f5e86be6577d946af65a328", + "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328", "shasum": "" }, "require": { @@ -1976,7 +1977,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.8" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.10" }, "funding": [ { @@ -1992,7 +1993,7 @@ "type": "tidelift" } ], - "time": "2023-05-11T05:14:45+00:00" + "time": "2023-07-10T04:04:23+00:00" }, { "name": "psr/cache", @@ -2803,16 +2804,16 @@ }, { "name": "sebastian/global-state", - "version": "5.0.5", + "version": "5.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + "reference": "bde739e7565280bda77be70044ac1047bc007e34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", + "reference": "bde739e7565280bda77be70044ac1047bc007e34", "shasum": "" }, "require": { @@ -2855,7 +2856,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" }, "funding": [ { @@ -2863,7 +2864,7 @@ "type": "github" } ], - "time": "2022-02-14T08:28:10+00:00" + "time": "2023-08-02T09:26:13+00:00" }, { "name": "sebastian/lines-of-code", From f5f1ea35cf3445ccfc33eba8be601132553fa352 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Sat, 12 Aug 2023 12:10:59 +0200 Subject: [PATCH 112/246] Removed comments --- src/PhpWord/Reader/Word2007/AbstractPart.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 3691df1297..6814540290 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -151,10 +151,6 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par } elseif ($headingDepth !== null) { // Heading or Title $textContent = null; - // 2023-08-02 hannes@dorn.cc - // $nodes = $xmlReader->getElements('w:r', $domNode); - // delivers only text paragraphs, but no hyperlinks - // I extended xpath with w:hyperlink $nodes = $xmlReader->getElements('w:r|w:hyperlink', $domNode); if ($nodes->length === 1) { $textContent = htmlspecialchars($xmlReader->getValue('w:t', $nodes->item(0)), ENT_QUOTES, 'UTF-8'); From fb090270a0fa7dd55ce18a0370422da73250f78a Mon Sep 17 00:00:00 2001 From: David Gagnaire Date: Wed, 23 Aug 2023 11:22:28 +0200 Subject: [PATCH 113/246] Fix PHP 8.2 deprecated about Allow access to an undefined property --- src/PhpWord/Reader/MsDoc.php | 10 ++++++++++ src/PhpWord/Shared/OLERead.php | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/PhpWord/Reader/MsDoc.php b/src/PhpWord/Reader/MsDoc.php index 68c732f533..c76f5df3e0 100644 --- a/src/PhpWord/Reader/MsDoc.php +++ b/src/PhpWord/Reader/MsDoc.php @@ -57,6 +57,16 @@ class MsDoc extends AbstractReader implements ReaderInterface */ private $dataObjectPool; + /** + * Object Stream. + */ + private $_SummaryInformation; + + /** + * Object Stream. + */ + private $_DocumentSummaryInformation; + /** * @var stdClass[] */ diff --git a/src/PhpWord/Shared/OLERead.php b/src/PhpWord/Shared/OLERead.php index 316e7812e6..d4399d6fb7 100644 --- a/src/PhpWord/Shared/OLERead.php +++ b/src/PhpWord/Shared/OLERead.php @@ -61,6 +61,17 @@ class OLERead public $wrkObjectPool = null; public $summaryInformation = null; public $docSummaryInfos = null; + public $numBigBlockDepotBlocks = null; + public $rootStartBlock = null; + public $sbdStartBlock = null; + public $extensionBlock = null; + public $numExtensionBlocks = null; + public $bigBlockChain = null; + public $smallBlockChain = null; + public $entry = null; + public $rootentry = null; + public $wrkObjectPoolelseif = null; + public $props = array(); /** * Read the file From 7601a3ed25c5c14f3b257d82acb14683519ad97f Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 30 Aug 2023 09:05:11 +0200 Subject: [PATCH 114/246] Fixed some typehint --- src/PhpWord/Style/Cell.php | 9 +++++---- src/PhpWord/Writer/Word2007/Style/Cell.php | 5 +---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index e96fb65422..2ba0713c27 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -123,7 +123,7 @@ class Cell extends Border * * @var bool */ - private $noWrap; + private $noWrap = true; /** * Get vertical align. @@ -323,9 +323,10 @@ public function setUnit($value) /** * Set noWrap. * - * @param $value + * @param bool $value + * @return self */ - public function setNoWrap($value) + public function setNoWrap(bool $value): self { $this->noWrap = $this->setBoolVal($value, true); @@ -337,7 +338,7 @@ public function setNoWrap($value) * * @return bool */ - public function getNoWrap() + public function getNoWrap(): bool { return $this->noWrap; } diff --git a/src/PhpWord/Writer/Word2007/Style/Cell.php b/src/PhpWord/Writer/Word2007/Style/Cell.php index 870419cadd..6e22597dd3 100644 --- a/src/PhpWord/Writer/Word2007/Style/Cell.php +++ b/src/PhpWord/Writer/Word2007/Style/Cell.php @@ -88,10 +88,7 @@ public function write(): void $vMerge = $style->getVMerge(); $xmlWriter->writeElementIf(null !== $gridSpan, 'w:gridSpan', 'w:val', $gridSpan); $xmlWriter->writeElementIf(null !== $vMerge, 'w:vMerge', 'w:val', $vMerge); - - // noWrap - $noWrap = $style->getNoWrap(); - $xmlWriter->writeElementIf(true === $noWrap, 'w:noWrap'); + $xmlWriter->writeElementIf($style->getNoWrap(), 'w:noWrap'); $xmlWriter->endElement(); // w:tcPr } From 32aa83e197d4c13a4c1d5da73ba5bd67354d6a32 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 30 Aug 2023 09:07:20 +0200 Subject: [PATCH 115/246] Removed PHPDoc --- src/PhpWord/Style/Cell.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index 2ba0713c27..3bd4a6cae6 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -322,9 +322,6 @@ public function setUnit($value) /** * Set noWrap. - * - * @param bool $value - * @return self */ public function setNoWrap(bool $value): self { @@ -335,8 +332,6 @@ public function setNoWrap(bool $value): self /** * Get noWrap. - * - * @return bool */ public function getNoWrap(): bool { From 63db12440585eb5e463f6a734f43d25fdee3d20f Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 30 Aug 2023 09:37:10 +0200 Subject: [PATCH 116/246] Word2007 Writer : Added unit test --- .../Writer/Word2007/Part/DocumentTest.php | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php index 98449f3b6d..95cdcf87fc 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php @@ -645,6 +645,44 @@ public function testWriteCellStyleCellGridSpan(): void self::assertEquals(5, $element->getAttribute('w:val')); } + /** + * covers ::_writeCellStyle. + */ + public function testWriteCellStyleCellNoWrapEnabled(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + + $table = $section->addTable(); + $table->addRow(); + + $cell = $table->addCell(200); + $cell->getStyle()->setNoWrap(true); + + $doc = TestHelperDOCX::getDocument($phpWord); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr/w:tc/w:tcPr/w:noWrap')); + } + + /** + * covers ::_writeCellStyle. + */ + public function testWriteCellStyleCellNoWrapDisabled(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + + $table = $section->addTable(); + $table->addRow(); + + $cell = $table->addCell(200); + $cell->getStyle()->setNoWrap(false); + + $doc = TestHelperDOCX::getDocument($phpWord); + + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr/w:tc/w:tcPr/w:noWrap')); + } + /** * Test write gutter and line numbering. */ From 87c17d4a68401121cde4f974539a9f6a4ddbb500 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 30 Aug 2023 09:55:12 +0200 Subject: [PATCH 117/246] Word2007 Reader : Added unit test --- .../Reader/Word2007/StyleTest.php | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/PhpWordTests/Reader/Word2007/StyleTest.php b/tests/PhpWordTests/Reader/Word2007/StyleTest.php index 2aeb651c60..be80dc513e 100644 --- a/tests/PhpWordTests/Reader/Word2007/StyleTest.php +++ b/tests/PhpWordTests/Reader/Word2007/StyleTest.php @@ -190,6 +190,27 @@ public function testReadHidden(): void self::assertTrue($fontStyle->isHidden()); } + public function testReadTableCellNoWrap(): void + { + $documentXml = ' + + + + + + + + '; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $elements = $phpWord->getSection(0)->getElements(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); + $rows = $elements[0]->getRows(); + $cells = $rows[0]->getCells(); + self::assertTrue($cells[0]->getStyle()->getNoWrap()); + } + public function testReadHeading(): void { Style::resetStyles(); From e458249d7f9c67901c2cfe4e53bc69c1c116fd06 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 30 Aug 2023 12:05:32 +0200 Subject: [PATCH 118/246] HTML Reader : Support for `font-variant: small-caps` Co-authored-by: cambraca --- src/PhpWord/Shared/Html.php | 8 ++++++++ tests/PhpWordTests/Shared/HtmlTest.php | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 4a9057e60c..15c5246a0c 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -771,6 +771,14 @@ protected static function parseStyleDeclarations(array $selectors, array $styles } $styles['italic'] = $tValue; + break; + case 'font-variant': + $tValue = false; + if (preg_match('#small-caps#', $value)) { + $tValue = true; + } + $styles['smallCaps'] = $tValue; + break; case 'margin': $value = Converter::cssToTwip($value); diff --git a/tests/PhpWordTests/Shared/HtmlTest.php b/tests/PhpWordTests/Shared/HtmlTest.php index 7340b219ab..6887c61829 100644 --- a/tests/PhpWordTests/Shared/HtmlTest.php +++ b/tests/PhpWordTests/Shared/HtmlTest.php @@ -176,6 +176,21 @@ public function testParseTextDecoration(): void self::assertEquals('single', $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:rPr/w:u', 'w:val')); } + /** + * Test font-variant style. + */ + public function testParseFontVariant(): void + { + $html = 'test'; + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:rPr/w:smallCaps')); + self::assertEquals('1', $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:rPr/w:smallCaps', 'w:val')); + } + /** * Test font. */ From c19e0381cfd58cc2f8e72cf6363de84af34c3798 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 30 Aug 2023 14:02:41 +0200 Subject: [PATCH 119/246] 1.2.0 : Update Changelog --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 469abf6a2f..c69542b4ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,28 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [1.2.0](https://github.com/PHPOffice/PHPWord/tree/1.2.0) (WIP) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.1.0...1.2.0) + +## Enhancements + +- Word2007 Reader/Writer : Added noWrap table cell property by @kernusr in #2359 +- HTML Reader : Support for `font-variant: small-caps` by @cambraca in #2117 +- Improved TextDirection for styling a cell by @terryzwt in #2429 +### Bug fixes + +- Fixed wrong mimetype for docx files by @gamerlv in #2416 +- Word2007 Reader : Read hyperlingks in headings by @hannesdorn in #2433 +- PclZip : strtr using empty string by @spl1nes in #2432 +- Fixed PHP 8.2 deprecated about Allow access to an undefined property by @DAdq26 in #2440 + +### Miscellaneous + +- Added PHPStan by @PowerKiKi in #2405 +- Bump symfony/process from 4.4.44 to 5.4.26 by @dependabot in #2431 +- Bump phpunit/phpunit from 9.6.8 to 9.6.10 by @dependabot in #2430 + ## [1.1.0](https://github.com/PHPOffice/PHPWord/tree/1.1.0) (2023-05-30) [Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.0.0...1.1.0) From a76b045f4f934bfb0b637b051d6a9ef623c910a0 Mon Sep 17 00:00:00 2001 From: dante Date: Fri, 23 Jun 2023 12:56:24 +0700 Subject: [PATCH 120/246] Fix Dimension Regex --- CHANGELOG.md | 1 + src/PhpWord/TemplateProcessor.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c69542b4ff..7d8a8b5605 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Word2007 Reader : Read hyperlingks in headings by @hannesdorn in #2433 - PclZip : strtr using empty string by @spl1nes in #2432 - Fixed PHP 8.2 deprecated about Allow access to an undefined property by @DAdq26 in #2440 +- Template Processor : Fixed choose dimention for Float Value by @gdevilbat in #2449 ### Miscellaneous diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 6ef22fc538..3433287e19 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -437,7 +437,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) { From 076af66b36e3544c78294f8279407176b64da79a Mon Sep 17 00:00:00 2001 From: Andrew Elliott Date: Fri, 8 Apr 2022 16:56:22 -0700 Subject: [PATCH 121/246] when language code is 'und' default to 'en-EN' --- src/PhpWord/Style/Language.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index 39d5aa1f06..18e7f76e77 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -256,7 +256,9 @@ private function validateLocale($locale) if ($locale !== null && strlen($locale) === 2) { return strtolower($locale) . '-' . strtoupper($locale); } - + if ($locale === 'und') { + return 'en-EN'; + } if ($locale !== null && $locale !== 'zxx' && strstr($locale, '-') === false) { throw new InvalidArgumentException($locale . ' is not a valid language code'); } From eefb2b5c78b48006074ac12562624988dc6005be Mon Sep 17 00:00:00 2001 From: Andrew Elliott Date: Tue, 15 Mar 2022 15:44:19 -0700 Subject: [PATCH 122/246] Added option to disable loading images --- CHANGELOG.md | 1 + src/PhpWord/Reader/AbstractReader.php | 19 +++++++ src/PhpWord/Reader/Word2007.php | 1 + src/PhpWord/Reader/Word2007/AbstractPart.php | 23 +++++++- tests/PhpWordTests/Reader/Word2007Test.php | 58 ++++++++++++++++---- 5 files changed, 90 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d8a8b5605..2439058f6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Word2007 Reader/Writer : Added noWrap table cell property by @kernusr in #2359 - HTML Reader : Support for `font-variant: small-caps` by @cambraca in #2117 - Improved TextDirection for styling a cell by @terryzwt in #2429 +- Word2007 Reader : Added option to disable loading images by @aelliott1485 in #2450 ### Bug fixes - Fixed wrong mimetype for docx files by @gamerlv in #2416 diff --git a/src/PhpWord/Reader/AbstractReader.php b/src/PhpWord/Reader/AbstractReader.php index ff768e3306..da5e6f6e19 100644 --- a/src/PhpWord/Reader/AbstractReader.php +++ b/src/PhpWord/Reader/AbstractReader.php @@ -42,6 +42,13 @@ abstract class AbstractReader implements ReaderInterface */ protected $fileHandle; + /** + * Load images. + * + * @var bool + */ + protected $imageLoading = true; + /** * Read data only? * @@ -67,6 +74,18 @@ public function setReadDataOnly($value = true) return $this; } + public function hasImageLoading(): bool + { + return $this->imageLoading; + } + + public function setImageLoading(bool $value): self + { + $this->imageLoading = $value; + + return $this; + } + /** * Open file for reading. * diff --git a/src/PhpWord/Reader/Word2007.php b/src/PhpWord/Reader/Word2007.php index 5f2a69c721..1febe0ff0a 100644 --- a/src/PhpWord/Reader/Word2007.php +++ b/src/PhpWord/Reader/Word2007.php @@ -94,6 +94,7 @@ private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile, if (class_exists($partClass)) { /** @var \PhpOffice\PhpWord\Reader\Word2007\AbstractPart $part Type hint */ $part = new $partClass($docFile, $xmlFile); + $part->setImageLoading($this->hasImageLoading()); $part->setRels($relationships); $part->read($phpWord); } diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index b1afccaafb..418661d6f0 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -67,6 +67,13 @@ abstract class AbstractPart */ protected $rels = []; + /** + * Image Loading. + * + * @var bool + */ + protected $imageLoading = true; + /** * Read part. */ @@ -94,6 +101,18 @@ public function setRels($value): void $this->rels = $value; } + public function setImageLoading(bool $value): self + { + $this->imageLoading = $value; + + return $this; + } + + public function hasImageLoading(): bool + { + return $this->imageLoading; + } + /** * Read w:p. * @@ -249,7 +268,7 @@ protected function readRunChild(XMLReader $xmlReader, DOMElement $node, Abstract // Image $rId = $xmlReader->getAttribute('r:id', $node, 'v:shape/v:imagedata'); $target = $this->getMediaTarget($docPart, $rId); - if (null !== $target) { + if ($this->hasImageLoading() && null !== $target) { if ('External' == $this->getTargetMode($docPart, $rId)) { $imageSource = $target; } else { @@ -271,7 +290,7 @@ protected function readRunChild(XMLReader $xmlReader, DOMElement $node, Abstract $embedId = $xmlReader->getAttribute('r:embed', $node, 'wp:anchor/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip'); } $target = $this->getMediaTarget($docPart, $embedId); - if (null !== $target) { + if ($this->hasImageLoading() && null !== $target) { $imageSource = "zip://{$this->docFile}#{$target}"; $parent->addImage($imageSource, null, false, $name); } diff --git a/tests/PhpWordTests/Reader/Word2007Test.php b/tests/PhpWordTests/Reader/Word2007Test.php index 999eaf853a..883dc84d53 100644 --- a/tests/PhpWordTests/Reader/Word2007Test.php +++ b/tests/PhpWordTests/Reader/Word2007Test.php @@ -17,7 +17,10 @@ namespace PhpOffice\PhpWordTests\Reader; +use PhpOffice\PhpWord\Element\Image; +use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\IOFactory; +use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Reader\Word2007; use PhpOffice\PhpWordTests\TestHelperDOCX; @@ -36,8 +39,7 @@ class Word2007Test extends \PHPUnit\Framework\TestCase public function testCanRead(): void { $object = new Word2007(); - $filename = __DIR__ . '/../_files/documents/reader.docx'; - self::assertTrue($object->canRead($filename)); + self::assertTrue($object->canRead(dirname(__DIR__, 1) . '/_files/documents/reader.docx')); } /** @@ -46,8 +48,7 @@ public function testCanRead(): void public function testCanReadFailed(): void { $object = new Word2007(); - $filename = __DIR__ . '/../_files/documents/foo.docx'; - self::assertFalse($object->canRead($filename)); + self::assertFalse($object->canRead(dirname(__DIR__, 1) . '/_files/documents/foo.docx')); } /** @@ -55,10 +56,9 @@ public function testCanReadFailed(): void */ public function testLoad(): void { - $filename = __DIR__ . '/../_files/documents/reader.docx'; - $phpWord = IOFactory::load($filename); + $phpWord = IOFactory::load(dirname(__DIR__, 1) . '/_files/documents/reader.docx', 'Word2007'); - self::assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); + self::assertInstanceOf(PhpWord::class, $phpWord); self::assertTrue($phpWord->getSettings()->hasDoNotTrackMoves()); self::assertFalse($phpWord->getSettings()->hasDoNotTrackFormatting()); self::assertEquals(100, $phpWord->getSettings()->getZoom()); @@ -72,12 +72,50 @@ public function testLoad(): void */ public function testLoadWord2011(): void { - $filename = __DIR__ . '/../_files/documents/reader-2011.docx'; - $phpWord = IOFactory::load($filename); + $reader = new Word2007(); + $phpWord = $reader->load(dirname(__DIR__, 1) . '/_files/documents/reader-2011.docx'); - self::assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); + self::assertInstanceOf(PhpWord::class, $phpWord); $doc = TestHelperDOCX::getDocument($phpWord); self::assertTrue($doc->elementExists('/w:document/w:body/w:p[3]/w:r/w:pict/v:shape/v:imagedata')); } + + /** + * Load a Word without/withoutImages. + * + * @dataProvider providerSettingsImageLoading + */ + public function testLoadWord2011SettingsImageLoading(bool $hasImageLoading): void + { + $reader = new Word2007(); + $reader->setImageLoading($hasImageLoading); + $phpWord = $reader->load(dirname(__DIR__, 1) . '/_files/documents/reader-2011.docx'); + + self::assertInstanceOf(PhpWord::class, $phpWord); + + $sections = $phpWord->getSections(); + self::assertCount(1, $sections); + $section = $sections[0]; + $elements = $section->getElements(); + self::assertCount(3, $elements); + $element = $elements[2]; + self::assertInstanceOf(TextRun::class, $element); + $subElements = $element->getElements(); + if ($hasImageLoading) { + self::assertCount(1, $subElements); + $subElement = $subElements[0]; + self::assertInstanceOf(Image::class, $subElement); + } else { + self::assertCount(0, $subElements); + } + } + + public function providerSettingsImageLoading(): iterable + { + return [ + [true], + [false], + ]; + } } From 5a8ecf5f8936e59160c13bc47a31148b4b54f59e Mon Sep 17 00:00:00 2001 From: Artem Vasilev Date: Tue, 22 Nov 2022 13:19:56 +0300 Subject: [PATCH 123/246] add border-spacing to default styles --- src/PhpWord/Writer/HTML/Part/Head.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PhpWord/Writer/HTML/Part/Head.php b/src/PhpWord/Writer/HTML/Part/Head.php index a2541aa4b0..96e73e2eb5 100644 --- a/src/PhpWord/Writer/HTML/Part/Head.php +++ b/src/PhpWord/Writer/HTML/Part/Head.php @@ -101,6 +101,7 @@ private function writeStyles() 'table' => [ 'border' => '1px solid black', 'border-spacing' => '0px', + 'border-collapse' => 'collapse', 'width ' => '100%', ], 'td' => [ From 6203febccaae319ba9edf8beca5bfe6454fd4cc1 Mon Sep 17 00:00:00 2001 From: Artem Vasilev Date: Tue, 22 Nov 2022 13:23:38 +0300 Subject: [PATCH 124/246] replace tab to space --- src/PhpWord/Writer/HTML/Part/Head.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Writer/HTML/Part/Head.php b/src/PhpWord/Writer/HTML/Part/Head.php index 96e73e2eb5..6117f736e3 100644 --- a/src/PhpWord/Writer/HTML/Part/Head.php +++ b/src/PhpWord/Writer/HTML/Part/Head.php @@ -101,7 +101,7 @@ private function writeStyles() 'table' => [ 'border' => '1px solid black', 'border-spacing' => '0px', - 'border-collapse' => 'collapse', + 'border-collapse' => 'collapse', 'width ' => '100%', ], 'td' => [ From 36b9af6cc273e5b1479b07c8cd13b80302581b36 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 30 Aug 2023 20:51:08 +0200 Subject: [PATCH 125/246] Updated Changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2439058f6f..39f71ddcea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). - HTML Reader : Support for `font-variant: small-caps` by @cambraca in #2117 - Improved TextDirection for styling a cell by @terryzwt in #2429 - Word2007 Reader : Added option to disable loading images by @aelliott1485 in #2450 +- HTML Writer : Added border-spacing to default styles for table by @kernusr in #2451 + ### Bug fixes - Fixed wrong mimetype for docx files by @gamerlv in #2416 From 725d7160b70e4af346cc5f310c9a0279d98662b7 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 30 Aug 2023 21:05:12 +0200 Subject: [PATCH 126/246] Added coveralls.io --- .github/workflows/ci.yml | 17 +++++++++++------ CHANGELOG.md | 1 + README.md | 5 ++--- phpunit.xml.dist | 4 ++++ 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index adc97146fa..52fc2a425f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,9 +131,9 @@ jobs: - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 with: - php-version: 8.0 + php-version: 8.1 extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: pcov + coverage: xdebug - name: Get composer cache directory id: composer-cache @@ -149,8 +149,13 @@ jobs: - name: Install dependencies run: composer install --no-progress --prefer-dist --optimize-autoloader - - name: Coverage + - name: Run phpunit + run: ./vendor/bin/phpunit -c phpunit.xml.dist --coverage-clover build/clover.xml + + - name: Upload coverage results to Coveralls + env: + COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - ./vendor/bin/phpunit --coverage-clover coverage-clover.xml - composer global require scrutinizer/ocular - ~/.composer/vendor/bin/ocular code-coverage:upload --format=php-clover coverage-clover.xml + wget https://github.com/php-coveralls/php-coveralls/releases/download/v2.4.3/php-coveralls.phar + chmod +x php-coveralls.phar + php php-coveralls.phar --coverage_clover=build/clover.xml --json_path=build/coveralls-upload.json -vvv diff --git a/CHANGELOG.md b/CHANGELOG.md index 39f71ddcea..027da5b0ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Added PHPStan by @PowerKiKi in #2405 - Bump symfony/process from 4.4.44 to 5.4.26 by @dependabot in #2431 - Bump phpunit/phpunit from 9.6.8 to 9.6.10 by @dependabot in #2430 +- Added Changelog by @Progi1984 in #2452 ## [1.1.0](https://github.com/PHPOffice/PHPWord/tree/1.1.0) (2023-05-30) diff --git a/README.md b/README.md index 21e0dd4fb3..ceb8451a4c 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,10 @@ # ![PHPWord](https://rawgit.com/PHPOffice/PHPWord/develop/docs/images/phpword.svg "PHPWord") [![Latest Stable Version](https://poser.pugx.org/phpoffice/phpword/v/stable.png)](https://packagist.org/packages/phpoffice/phpword) -[![CI](https://github.com/PHPOffice/PHPWord/actions/workflows/ci.yml/badge.svg)](https://github.com/PHPOffice/PHPWord/actions/workflows/ci.yml) -[![Code Quality](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/) -[![Code Coverage](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/) +[![Coverage Status](https://coveralls.io/repos/github/PHPOffice/PHPWord/badge.svg?branch=master)](https://coveralls.io/github/PHPOffice/PHPWord?branch=master) [![Total Downloads](https://poser.pugx.org/phpoffice/phpword/downloads.png)](https://packagist.org/packages/phpoffice/phpword) [![License](https://poser.pugx.org/phpoffice/phpword/license.png)](https://packagist.org/packages/phpoffice/phpword) +[![CI](https://github.com/PHPOffice/PHPWord/actions/workflows/ci.yml/badge.svg)](https://github.com/PHPOffice/PHPWord/actions/workflows/ci.yml) [![Join the chat at https://gitter.im/PHPOffice/PHPWord](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/PHPOffice/PHPWord) PHPWord is a library written in pure PHP that provides a set of classes to write to and read from different document file formats. The current version of PHPWord supports Microsoft [Office Open XML](http://en.wikipedia.org/wiki/Office_Open_XML) (OOXML or OpenXML), OASIS [Open Document Format for Office Applications](http://en.wikipedia.org/wiki/OpenDocument) (OpenDocument or ODF), [Rich Text Format](http://en.wikipedia.org/wiki/Rich_Text_Format) (RTF), HTML, and PDF. diff --git a/phpunit.xml.dist b/phpunit.xml.dist index e3f02121bb..a81487036d 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -20,4 +20,8 @@ + + + + From d59e1d941f0afa8b17fb2c577274eb1a78e4a37b Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 30 Aug 2023 21:30:27 +0200 Subject: [PATCH 127/246] Added support for PHP 8.2 & 8.3 --- .github/workflows/ci.yml | 2 ++ CHANGELOG.md | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 52fc2a425f..46c539dcc3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,8 @@ jobs: - "7.4" - "8.0" - "8.1" + - "8.2" + - "8.3" name: PHP ${{ matrix.php-version }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 027da5b0ff..f93b7ac0f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Added PHPStan by @PowerKiKi in #2405 - Bump symfony/process from 4.4.44 to 5.4.26 by @dependabot in #2431 - Bump phpunit/phpunit from 9.6.8 to 9.6.10 by @dependabot in #2430 -- Added Changelog by @Progi1984 in #2452 +- Added Coveralls.io by @Progi1984 in #2452 +- Added support for PHP 8.2 & PHP 8.3 by @Progi1984 in #2453 ## [1.1.0](https://github.com/PHPOffice/PHPWord/tree/1.1.0) (2023-05-30) From 03246d7cf12275db5589f476f8a82b7a44a5c2f0 Mon Sep 17 00:00:00 2001 From: Jokubas Ramanauskas Date: Wed, 26 Jul 2023 10:58:44 +0300 Subject: [PATCH 128/246] Fix Html::parseImage when image has no extension --- CHANGELOG.md | 1 + src/PhpWord/Shared/Html.php | 5 ++++- .../AbstractWebServerEmbeddedTest.php | 9 +++++++++ tests/PhpWordTests/Shared/HtmlTest.php | 18 ++++++++++++++++++ tests/PhpWordTests/_files/images/new-php-logo | Bin 0 -> 10298 bytes 5 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 tests/PhpWordTests/_files/images/new-php-logo diff --git a/CHANGELOG.md b/CHANGELOG.md index f93b7ac0f3..a2c5be13c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - PclZip : strtr using empty string by @spl1nes in #2432 - Fixed PHP 8.2 deprecated about Allow access to an undefined property by @DAdq26 in #2440 - Template Processor : Fixed choose dimention for Float Value by @gdevilbat in #2449 +- HTML Parser : Fix image parsing from url without extension by @JokubasR in #2459 ### Miscellaneous diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 15c5246a0c..7f93b2ebff 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -965,7 +965,10 @@ protected static function parseImage($node, $element) $tmpDir = Settings::getTempDir() . '/'; $match = []; preg_match('/.+\.(\w+)$/', $src, $match); - $src = $tmpDir . uniqid() . '.' . $match[1]; + $src = $tmpDir . uniqid(); + if (isset($match[1])) { + $src .= '.' . $match[1]; + } $ifp = fopen($src, 'wb'); diff --git a/tests/PhpWordTests/AbstractWebServerEmbeddedTest.php b/tests/PhpWordTests/AbstractWebServerEmbeddedTest.php index f291f79b8a..38420b4462 100644 --- a/tests/PhpWordTests/AbstractWebServerEmbeddedTest.php +++ b/tests/PhpWordTests/AbstractWebServerEmbeddedTest.php @@ -53,6 +53,15 @@ protected static function getRemoteImageUrl() return 'http://php.net/images/logos/new-php-logo.png'; } + protected static function getRemoteImageUrlWithoutExtension(): string + { + if (self::$httpServer) { + return self::getBaseUrl() . '/images/new-php-logo'; + } + + return 'http://placekitten.com/200/300'; + } + protected static function getRemoteGifImageUrl() { if (self::$httpServer) { diff --git a/tests/PhpWordTests/Shared/HtmlTest.php b/tests/PhpWordTests/Shared/HtmlTest.php index 6887c61829..d65066d54c 100644 --- a/tests/PhpWordTests/Shared/HtmlTest.php +++ b/tests/PhpWordTests/Shared/HtmlTest.php @@ -816,6 +816,24 @@ public function testParseRemoteImage(): void self::assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); } + /** + * Test parsing of remote img without extension. + */ + public function testParseRemoteImageWithoutExtension(): void + { + $src = self::getRemoteImageUrlWithoutExtension(); + + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $html = '

    '; + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $baseXpath = '/w:document/w:body/w:p/w:r'; + self::assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); + } + /** * Test parsing embedded image. */ diff --git a/tests/PhpWordTests/_files/images/new-php-logo b/tests/PhpWordTests/_files/images/new-php-logo new file mode 100644 index 0000000000000000000000000000000000000000..6649079930716c425de2d675a0feebbe7d0a0d70 GIT binary patch literal 10298 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 M07*qoM6N<$f)aut$N&HU literal 0 HcmV?d00001 From d1137c7cb04434b37824ab73739851996e95f32e Mon Sep 17 00:00:00 2001 From: Artem Vasilev Date: Tue, 6 Dec 2022 19:04:18 +0300 Subject: [PATCH 129/246] Word2007 Reader : Support for table cell borders and margins --- CHANGELOG.md | 1 + src/PhpWord/Reader/Word2007/AbstractPart.php | 25 +++- src/PhpWord/Style/Border.php | 126 +++++++++++++++++ src/PhpWord/Style/Section.php | 125 ----------------- .../Reader/Word2007/StyleTest.php | 128 ++++++++++++------ 5 files changed, 232 insertions(+), 173 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f93b7ac0f3..5235895506 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Improved TextDirection for styling a cell by @terryzwt in #2429 - Word2007 Reader : Added option to disable loading images by @aelliott1485 in #2450 - HTML Writer : Added border-spacing to default styles for table by @kernusr in #2451 +- Word2007 Reader : Support for table cell borders and margins by @kernusr in #2454 ### Bug fixes diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 418661d6f0..3ab8995f9e 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -385,9 +385,8 @@ protected function readTable(XMLReader $xmlReader, DOMElement $domNode, $parent, } elseif ('w:tc' == $rowNode->nodeName) { // Cell $cellWidth = $xmlReader->getAttribute('w:w', $rowNode, 'w:tcPr/w:tcW'); $cellStyle = null; - $cellStyleNode = $xmlReader->getElement('w:tcPr', $rowNode); - if (null !== $cellStyleNode) { - $cellStyle = $this->readCellStyle($xmlReader, $cellStyleNode); + if ($xmlReader->elementExists('w:tcPr', $rowNode)) { + $cellStyle = $this->readCellStyle($xmlReader, $rowNode); } $cell = $row->addCell($cellWidth, $cellStyle); @@ -573,7 +572,7 @@ private function readTableIndent(XMLReader $xmlReader, DOMElement $domNode) /** * Read w:tcPr. * - * @return array + * @return null|array */ private function readCellStyle(XMLReader $xmlReader, DOMElement $domNode) { @@ -585,8 +584,24 @@ private function readCellStyle(XMLReader $xmlReader, DOMElement $domNode) 'bgColor' => [self::READ_VALUE, 'w:shd', 'w:fill'], 'noWrap' => [self::READ_VALUE, 'w:noWrap', null, null, true], ]; + $style = null; - return $this->readStyleDefs($xmlReader, $domNode, $styleDefs); + if ($xmlReader->elementExists('w:tcPr', $domNode)) { + $styleNode = $xmlReader->getElement('w:tcPr', $domNode); + + $borders = ['top', 'left', 'bottom', 'right']; + foreach ($borders as $side) { + $ucfSide = ucfirst($side); + + $styleDefs['border' . $ucfSide . 'Size'] = [self::READ_VALUE, 'w:tcBorders/w:' . $side, 'w:sz']; + $styleDefs['border' . $ucfSide . 'Color'] = [self::READ_VALUE, 'w:tcBorders/w:' . $side, 'w:color']; + $styleDefs['border' . $ucfSide . 'Style'] = [self::READ_VALUE, 'w:tcBorders/w:' . $side, 'w:val']; + } + + $style = $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); + } + + return $style; } /** diff --git a/src/PhpWord/Style/Border.php b/src/PhpWord/Style/Border.php index 2ee69be56f..28e340c040 100644 --- a/src/PhpWord/Style/Border.php +++ b/src/PhpWord/Style/Border.php @@ -22,6 +22,8 @@ */ class Border extends AbstractStyle { + const DEFAULT_MARGIN = 1440; // In twips. + /** * Border Top Size. * @@ -106,6 +108,34 @@ class Border extends AbstractStyle */ protected $borderBottomStyle; + /** + * Top margin spacing. + * + * @var float|int + */ + protected $marginTop = self::DEFAULT_MARGIN; + + /** + * Left margin spacing. + * + * @var float|int + */ + protected $marginLeft = self::DEFAULT_MARGIN; + + /** + * Right margin spacing. + * + * @var float|int + */ + protected $marginRight = self::DEFAULT_MARGIN; + + /** + * Bottom margin spacing. + * + * @var float|int + */ + protected $marginBottom = self::DEFAULT_MARGIN; + /** * Get border size. * @@ -501,4 +531,100 @@ public function hasBorder() return $borders !== array_filter($borders, 'is_null'); } + + /** + * Get Margin Top. + * + * @return float|int + */ + public function getMarginTop() + { + return $this->marginTop; + } + + /** + * Set Margin Top. + * + * @param float|int $value + * + * @return self + */ + public function setMarginTop($value = null) + { + $this->marginTop = $this->setNumericVal($value, self::DEFAULT_MARGIN); + + return $this; + } + + /** + * Get Margin Left. + * + * @return float|int + */ + public function getMarginLeft() + { + return $this->marginLeft; + } + + /** + * Set Margin Left. + * + * @param float|int $value + * + * @return self + */ + public function setMarginLeft($value = null) + { + $this->marginLeft = $this->setNumericVal($value, self::DEFAULT_MARGIN); + + return $this; + } + + /** + * Get Margin Right. + * + * @return float|int + */ + public function getMarginRight() + { + return $this->marginRight; + } + + /** + * Set Margin Right. + * + * @param float|int $value + * + * @return self + */ + public function setMarginRight($value = null) + { + $this->marginRight = $this->setNumericVal($value, self::DEFAULT_MARGIN); + + return $this; + } + + /** + * Get Margin Bottom. + * + * @return float|int + */ + public function getMarginBottom() + { + return $this->marginBottom; + } + + /** + * Set Margin Bottom. + * + * @param float|int $value + * + * @return self + */ + public function setMarginBottom($value = null) + { + $this->marginBottom = $this->setNumericVal($value, self::DEFAULT_MARGIN); + + return $this; + } } diff --git a/src/PhpWord/Style/Section.php b/src/PhpWord/Style/Section.php index d4ede285e7..3b08aa5f38 100644 --- a/src/PhpWord/Style/Section.php +++ b/src/PhpWord/Style/Section.php @@ -40,7 +40,6 @@ class Section extends Border */ const DEFAULT_WIDTH = 11905.511811024; // In twips. const DEFAULT_HEIGHT = 16837.79527559; // In twips. - const DEFAULT_MARGIN = 1440; // In twips. const DEFAULT_GUTTER = 0; // In twips. const DEFAULT_HEADER_HEIGHT = 720; // In twips. const DEFAULT_FOOTER_HEIGHT = 720; // In twips. @@ -77,34 +76,6 @@ class Section extends Border */ private $pageSizeH = self::DEFAULT_HEIGHT; - /** - * Top margin spacing. - * - * @var float|int - */ - private $marginTop = self::DEFAULT_MARGIN; - - /** - * Left margin spacing. - * - * @var float|int - */ - private $marginLeft = self::DEFAULT_MARGIN; - - /** - * Right margin spacing. - * - * @var float|int - */ - private $marginRight = self::DEFAULT_MARGIN; - - /** - * Bottom margin spacing. - * - * @var float|int - */ - private $marginBottom = self::DEFAULT_MARGIN; - /** * Page gutter spacing. * @@ -344,102 +315,6 @@ public function setPageSizeH($value = null) return $this; } - /** - * Get Margin Top. - * - * @return float|int - */ - public function getMarginTop() - { - return $this->marginTop; - } - - /** - * Set Margin Top. - * - * @param float|int $value - * - * @return self - */ - public function setMarginTop($value = null) - { - $this->marginTop = $this->setNumericVal($value, self::DEFAULT_MARGIN); - - return $this; - } - - /** - * Get Margin Left. - * - * @return float|int - */ - public function getMarginLeft() - { - return $this->marginLeft; - } - - /** - * Set Margin Left. - * - * @param float|int $value - * - * @return self - */ - public function setMarginLeft($value = null) - { - $this->marginLeft = $this->setNumericVal($value, self::DEFAULT_MARGIN); - - return $this; - } - - /** - * Get Margin Right. - * - * @return float|int - */ - public function getMarginRight() - { - return $this->marginRight; - } - - /** - * Set Margin Right. - * - * @param float|int $value - * - * @return self - */ - public function setMarginRight($value = null) - { - $this->marginRight = $this->setNumericVal($value, self::DEFAULT_MARGIN); - - return $this; - } - - /** - * Get Margin Bottom. - * - * @return float|int - */ - public function getMarginBottom() - { - return $this->marginBottom; - } - - /** - * Set Margin Bottom. - * - * @param float|int $value - * - * @return self - */ - public function setMarginBottom($value = null) - { - $this->marginBottom = $this->setNumericVal($value, self::DEFAULT_MARGIN); - - return $this; - } - /** * Get gutter. * diff --git a/tests/PhpWordTests/Reader/Word2007/StyleTest.php b/tests/PhpWordTests/Reader/Word2007/StyleTest.php index be80dc513e..015a3cfcb7 100644 --- a/tests/PhpWordTests/Reader/Word2007/StyleTest.php +++ b/tests/PhpWordTests/Reader/Word2007/StyleTest.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWordTests\Reader\Word2007; +use PhpOffice\PhpWord\SimpleType\Border; use PhpOffice\PhpWord\SimpleType\TblWidth; use PhpOffice\PhpWord\SimpleType\VerticalJc; use PhpOffice\PhpWord\Style; @@ -48,28 +49,6 @@ public function testReadTableLayout(): void self::assertEquals(Table::LAYOUT_FIXED, $elements[0]->getStyle()->getLayout()); } - /** - * Test reading of cell spacing. - */ - public function testReadCellSpacing(): void - { - $documentXml = ' - - - - '; - - $phpWord = $this->getDocumentFromString(['document' => $documentXml]); - - $elements = $phpWord->getSection(0)->getElements(); - self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); - self::assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); - /** @var \PhpOffice\PhpWord\Style\Table $tableStyle */ - $tableStyle = $elements[0]->getStyle(); - self::assertEquals(TblWidth::AUTO, $tableStyle->getUnit()); - self::assertEquals(10.5, $tableStyle->getCellSpacing()); - } - /** * Test reading of table position. */ @@ -102,6 +81,90 @@ public function testReadTablePosition(): void self::assertEquals(60, $tableStyle->getTblpY()); } + public function testReadTableCellNoWrap(): void + { + $documentXml = ' + + + + + + + + '; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $elements = $phpWord->getSection(0)->getElements(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); + $rows = $elements[0]->getRows(); + $cells = $rows[0]->getCells(); + self::assertTrue($cells[0]->getStyle()->getNoWrap()); + } + + /** + * Test reading of cell spacing. + */ + public function testReadTableCellSpacing(): void + { + $documentXml = ' + + + + '; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $elements = $phpWord->getSection(0)->getElements(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); + self::assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); + /** @var \PhpOffice\PhpWord\Style\Table $tableStyle */ + $tableStyle = $elements[0]->getStyle(); + self::assertEquals(TblWidth::AUTO, $tableStyle->getUnit()); + self::assertEquals(10.5, $tableStyle->getCellSpacing()); + } + + public function testReadTableCellStyle(): void + { + $documentXml = ' + + + + + + + + + + + + + + + + + '; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $elements = $phpWord->getSection(0)->getElements(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); + $rows = $elements[0]->getRows(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\Row', $rows[0]); + $cells = $rows[0]->getCells(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\Cell', $cells[0]); + $styleCell = $cells[0]->getStyle(); + self::assertInstanceOf('PhpOffice\PhpWord\Style\Cell', $styleCell); + + self::assertEquals(4, $styleCell->getBorderTopSize()); + self::assertEquals(Border::SINGLE, $styleCell->getBorderTopStyle()); + self::assertEquals('auto', $styleCell->getBorderTopColor()); + + self::assertEquals(4, $styleCell->getBorderBottomSize()); + self::assertEquals(Border::DOUBLE, $styleCell->getBorderBottomStyle()); + self::assertEquals('auto', $styleCell->getBorderBottomColor()); + } + /** * Test reading of position. */ @@ -190,27 +253,6 @@ public function testReadHidden(): void self::assertTrue($fontStyle->isHidden()); } - public function testReadTableCellNoWrap(): void - { - $documentXml = ' - - - - - - - - '; - - $phpWord = $this->getDocumentFromString(['document' => $documentXml]); - - $elements = $phpWord->getSection(0)->getElements(); - self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); - $rows = $elements[0]->getRows(); - $cells = $rows[0]->getCells(); - self::assertTrue($cells[0]->getStyle()->getNoWrap()); - } - public function testReadHeading(): void { Style::resetStyles(); From f1f2c4f92b0e46909196e39f27e62e47371447fe Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Fri, 8 Sep 2023 13:04:10 +0200 Subject: [PATCH 130/246] Moved documention from ReadTheDocs to MkDocs & Github Pages --- .github/workflows/deploy.yml | 51 ++ .github/workflows/github-pages.yml | 29 - .github/workflows/{ci.yml => php.yml} | 0 .gitignore | 1 + .scrutinizer.yml | 35 - CHANGELOG.md | 796 ------------------- README.md | 8 +- composer.json | 2 +- docs/Makefile | 153 ---- docs/changes/0.x/0.10.0.md | 84 ++ docs/changes/0.x/0.10.1.md | 9 + docs/changes/0.x/0.11.0.md | 62 ++ docs/changes/0.x/0.11.1.md | 5 + docs/changes/0.x/0.12.0.md | 60 ++ docs/changes/0.x/0.12.1.md | 11 + docs/changes/0.x/0.13.0.md | 47 ++ docs/changes/0.x/0.14.0.md | 47 ++ docs/changes/0.x/0.15.0.md | 45 ++ docs/changes/0.x/0.16.0.md | 27 + docs/changes/0.x/0.17.0.md | 27 + docs/changes/0.x/0.18.0.md | 47 ++ docs/changes/0.x/0.18.1.md | 7 + docs/changes/0.x/0.18.2.md | 14 + docs/changes/0.x/0.18.3.md | 6 + docs/changes/0.x/0.7.0.md | 26 + docs/changes/0.x/0.8.0.md | 45 ++ docs/changes/0.x/0.8.1.md | 9 + docs/changes/0.x/0.9.0.md | 19 + docs/changes/0.x/0.9.1.md | 8 + docs/changes/1.x/1.0.0.md | 110 +++ docs/changes/1.x/1.1.0.md | 24 + docs/changes/1.x/1.2.0.md | 30 + docs/conf.py | 290 ------- docs/credits.md | 40 + docs/credits.rst | 4 - docs/elements.rst | 512 ------------ docs/faq.md | 5 + docs/faq.rst | 8 - docs/general.rst | 344 -------- docs/howto.md | 101 +++ docs/index.md | 115 +++ docs/index.rst | 40 - docs/install.md | 52 ++ docs/installing.rst | 48 -- docs/intro.rst | 196 ----- docs/recipes.rst | 97 --- docs/references.rst | 28 - docs/styles.rst | 213 ----- docs/templates-processing.rst | 303 ------- docs/{containers.rst => usage/containers.md} | 119 +-- docs/usage/elements/chart.md | 15 + docs/usage/elements/checkbox.md | 14 + docs/usage/elements/comment.md | 23 + docs/usage/elements/field.md | 39 + docs/usage/elements/image.md | 36 + docs/usage/elements/index.md | 34 + docs/usage/elements/line.md | 21 + docs/usage/elements/link.md | 14 + docs/usage/elements/list.md | 48 ++ docs/usage/elements/note.md | 54 ++ docs/usage/elements/oleobject.md | 9 + docs/usage/elements/pagebreak.md | 9 + docs/usage/elements/preservetext.md | 9 + docs/usage/elements/table.md | 41 + docs/usage/elements/text.md | 26 + docs/usage/elements/textbox.md | 3 + docs/usage/elements/textbreak.md | 13 + docs/usage/elements/title.md | 19 + docs/usage/elements/toc.md | 21 + docs/usage/elements/trackchanges.md | 25 + docs/usage/elements/watermark.md | 13 + docs/usage/introduction.md | 356 +++++++++ docs/usage/readers.md | 51 ++ docs/usage/styles/chart.md | 19 + docs/usage/styles/font.md | 26 + docs/usage/styles/image.md | 14 + docs/usage/styles/numberinglevel.md | 16 + docs/usage/styles/paragraph.md | 29 + docs/usage/styles/section.md | 28 + docs/usage/styles/table.md | 49 ++ docs/usage/template.md | 347 ++++++++ docs/usage/writers.md | 65 ++ docs/writersreaders.rst | 110 --- mkdocs.yml | 116 +++ samples/Sample_26_Html.php | 2 +- samples/Sample_Header.php | 4 +- samples/index.php | 2 +- samples/resources/Sample_30_ReadHTML.html | 2 +- sonar-project.properties | 17 - src/PhpWord/Reader/MsDoc.php | 10 +- src/PhpWord/Writer/Word2007.php | 2 +- tests/PhpWordTests/Shared/HtmlTest.php | 2 +- 92 files changed, 2813 insertions(+), 3299 deletions(-) create mode 100644 .github/workflows/deploy.yml delete mode 100644 .github/workflows/github-pages.yml rename .github/workflows/{ci.yml => php.yml} (100%) delete mode 100644 .scrutinizer.yml delete mode 100644 CHANGELOG.md delete mode 100644 docs/Makefile create mode 100644 docs/changes/0.x/0.10.0.md create mode 100644 docs/changes/0.x/0.10.1.md create mode 100644 docs/changes/0.x/0.11.0.md create mode 100644 docs/changes/0.x/0.11.1.md create mode 100644 docs/changes/0.x/0.12.0.md create mode 100644 docs/changes/0.x/0.12.1.md create mode 100644 docs/changes/0.x/0.13.0.md create mode 100644 docs/changes/0.x/0.14.0.md create mode 100644 docs/changes/0.x/0.15.0.md create mode 100644 docs/changes/0.x/0.16.0.md create mode 100644 docs/changes/0.x/0.17.0.md create mode 100644 docs/changes/0.x/0.18.0.md create mode 100644 docs/changes/0.x/0.18.1.md create mode 100644 docs/changes/0.x/0.18.2.md create mode 100644 docs/changes/0.x/0.18.3.md create mode 100644 docs/changes/0.x/0.7.0.md create mode 100644 docs/changes/0.x/0.8.0.md create mode 100644 docs/changes/0.x/0.8.1.md create mode 100644 docs/changes/0.x/0.9.0.md create mode 100644 docs/changes/0.x/0.9.1.md create mode 100644 docs/changes/1.x/1.0.0.md create mode 100644 docs/changes/1.x/1.1.0.md create mode 100644 docs/changes/1.x/1.2.0.md delete mode 100644 docs/conf.py create mode 100644 docs/credits.md delete mode 100644 docs/credits.rst delete mode 100644 docs/elements.rst create mode 100644 docs/faq.md delete mode 100644 docs/faq.rst delete mode 100644 docs/general.rst create mode 100644 docs/howto.md create mode 100644 docs/index.md delete mode 100644 docs/index.rst create mode 100644 docs/install.md delete mode 100644 docs/installing.rst delete mode 100644 docs/intro.rst delete mode 100644 docs/recipes.rst delete mode 100644 docs/references.rst delete mode 100644 docs/styles.rst delete mode 100644 docs/templates-processing.rst rename docs/{containers.rst => usage/containers.md} (59%) create mode 100644 docs/usage/elements/chart.md create mode 100644 docs/usage/elements/checkbox.md create mode 100644 docs/usage/elements/comment.md create mode 100644 docs/usage/elements/field.md create mode 100644 docs/usage/elements/image.md create mode 100644 docs/usage/elements/index.md create mode 100644 docs/usage/elements/line.md create mode 100644 docs/usage/elements/link.md create mode 100644 docs/usage/elements/list.md create mode 100644 docs/usage/elements/note.md create mode 100644 docs/usage/elements/oleobject.md create mode 100644 docs/usage/elements/pagebreak.md create mode 100644 docs/usage/elements/preservetext.md create mode 100644 docs/usage/elements/table.md create mode 100644 docs/usage/elements/text.md create mode 100644 docs/usage/elements/textbox.md create mode 100644 docs/usage/elements/textbreak.md create mode 100644 docs/usage/elements/title.md create mode 100644 docs/usage/elements/toc.md create mode 100644 docs/usage/elements/trackchanges.md create mode 100644 docs/usage/elements/watermark.md create mode 100644 docs/usage/introduction.md create mode 100644 docs/usage/readers.md create mode 100644 docs/usage/styles/chart.md create mode 100644 docs/usage/styles/font.md create mode 100644 docs/usage/styles/image.md create mode 100644 docs/usage/styles/numberinglevel.md create mode 100644 docs/usage/styles/paragraph.md create mode 100644 docs/usage/styles/section.md create mode 100644 docs/usage/styles/table.md create mode 100644 docs/usage/template.md create mode 100644 docs/usage/writers.md delete mode 100644 docs/writersreaders.rst create mode 100644 mkdocs.yml delete mode 100644 sonar-project.properties diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000000..433a62077a --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,51 @@ +name: Deploy + +on: + push: + branches: + - develop + pull_request: + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + ### MkDocs + - name: Setup Python + uses: actions/setup-python@v2 + with: + python-version: 3.x + - name: Install Python Dependencies + run: pip install mkdocs-material autolink-references-mkdocs-plugin + - name: Build documentation + run: mkdocs build --site-dir public + ### PHPUnit + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.1 + extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib + coverage: xdebug + - name: Create directory public/coverage + run: mkdir ./public/coverage + - name: Install PHP Dependencies + run: composer install --ansi --prefer-dist --no-interaction --no-progress + - name: Build Coverage Report + run: XDEBUG_MODE=coverage ./vendor/bin/phpunit -c ./ --coverage-text --coverage-html ./public/coverage + ### PHPDoc + - name: Create directory public/docs + run: mkdir ./public/docs + - name: Install PhpDocumentor + run: wget https://phpdoc.org/phpDocumentor.phar && chmod +x phpDocumentor.phar + - name: Build Documentation + run: ./phpDocumentor.phar run -d ./src -t ./public/docs + + ### Deploy + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + if: github.ref == 'refs/heads/develop' + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./public diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml deleted file mode 100644 index aa35f57f87..0000000000 --- a/.github/workflows/github-pages.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: GithHub Pages -on: - push: - tags: - - '*' - -jobs: - github-pages: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: 7.4 - coverage: none # remove xdebug - - - name: Build API documentation - run: | - curl -LO https://github.com/phpDocumentor/phpDocumentor/releases/download/v3.0.0/phpDocumentor.phar - php phpDocumentor.phar --directory src/ --target docs/api - - - name: Deploy to GithHub Pages - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs/api diff --git a/.github/workflows/ci.yml b/.github/workflows/php.yml similarity index 100% rename from .github/workflows/ci.yml rename to .github/workflows/php.yml diff --git a/.gitignore b/.gitignore index 7e80be0d15..3695438057 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ phpword.ini /nbproject /.php_cs.cache /.phpunit.result.cache +/public \ No newline at end of file diff --git a/.scrutinizer.yml b/.scrutinizer.yml deleted file mode 100644 index d1fe59618d..0000000000 --- a/.scrutinizer.yml +++ /dev/null @@ -1,35 +0,0 @@ -build: - nodes: - analysis: - tests: - override: [php-scrutinizer-run] - environment: - php: - version: '7.4' - pecl_extensions: - - zip - -filter: - excluded_paths: [ 'vendor/*', 'tests/*', 'samples/*', 'src/PhpWord/Shared/PCLZip/*' ] - -before_commands: - - "composer install --prefer-source --dev" - -tools: - php_code_sniffer: - enabled: true - config: - standard: PSR2 - php_mess_detector: - enabled: true - config: - ruleset: phpmd.xml.dist - external_code_coverage: - enabled: false - timeout: 1200 - 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 deleted file mode 100644 index 1abf460f68..0000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,796 +0,0 @@ -# Changelog -All notable changes to this project will be documented in this file. -This project adheres to [Semantic Versioning](http://semver.org/). - -## [1.2.0](https://github.com/PHPOffice/PHPWord/tree/1.2.0) (WIP) - -[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.1.0...1.2.0) - -## Enhancements - -- Word2007 Reader/Writer : Added noWrap table cell property by @kernusr in #2359 -- HTML Reader : Support for `font-variant: small-caps` by @cambraca in #2117 -- Improved TextDirection for styling a cell by @terryzwt in #2429 -- Word2007 Reader : Added option to disable loading images by @aelliott1485 in #2450 -- HTML Writer : Added border-spacing to default styles for table by @kernusr in #2451 -- Word2007 Reader : Support for table cell borders and margins by @kernusr in #2454 - -### Bug fixes - -- Fixed wrong mimetype for docx files by @gamerlv in #2416 -- Word2007 Reader : Read hyperlingks in headings by @hannesdorn in #2433 -- PclZip : strtr using empty string by @spl1nes in #2432 -- Fixed PHP 8.2 deprecated about Allow access to an undefined property by @DAdq26 in #2440 -- Template Processor : Fixed choose dimention for Float Value by @gdevilbat in #2449 -- HTML Parser : Fix image parsing from url without extension by @JokubasR in #2459 - -### Miscellaneous - -- Added PHPStan by @PowerKiKi in #2405 -- Bump symfony/process from 4.4.44 to 5.4.26 by @dependabot in #2431 -- Bump phpunit/phpunit from 9.6.8 to 9.6.10 by @dependabot in #2430 -- Added Coveralls.io by @Progi1984 in #2452 -- Added support for PHP 8.2 & PHP 8.3 by @Progi1984 in #2453 - -## [1.1.0](https://github.com/PHPOffice/PHPWord/tree/1.1.0) (2023-05-30) - -[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.0.0...1.1.0) - -### Enhancements - -- Introduce deleteRow() method for TemplateProcessor -- HTML Reader: Add basic support for CSS Style Tag -- Allow customizing macro syntax in TemplateProcessor -- Add background color support for textboxes -- Add softhyphen support to word reader -- Add support table row height when importing HTML -- Add support for fractional font sizes -- Added image quality support, with the maximum quality as default -- Support for reading nested tables - -### Bug fixes - -- DOCX reader: Read empty vmerge -- Fixed setting width of Cell Style - -### Miscellaneous - -- `master` is the new default branch - -## [1.0.0](https://github.com/PHPOffice/PHPWord/tree/1.0.0) (2022-11-15) - -[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.18.3...1.0.0) - -### BREAKING CHANGE - -Most deprecated things were dropped. See details in -https://github.com/PHPOffice/PHPWord/commit/b9f1151bc6f90c276153c3c9dca10a5fc7f355fb. - -#### Dropped classes: - -- `PhpOffice\PhpWord\Template` - -#### Dropped constants: - -- `PhpOffice\PhpWord\Style\Font::UNDERLINE_DOTHASH` -- `PhpOffice\PhpWord\Style\Font::UNDERLINE_DOTHASHHEAVY` -- `PhpOffice\PhpWord\Style\Cell::VALIGN_TOP` -- `PhpOffice\PhpWord\Style\Cell::VALIGN_CENTER` -- `PhpOffice\PhpWord\Style\Cell::VALIGN_BOTTOM` -- `PhpOffice\PhpWord\Style\Cell::VALIGN_BOTH` -- `PhpOffice\PhpWord\Style\TOC::TABLEADER_DOT` -- `PhpOffice\PhpWord\Style\TOC::TABLEADER_UNDERSCORE` -- `PhpOffice\PhpWord\Style\TOC::TABLEADER_LINE` -- `PhpOffice\PhpWord\Style\TOC::TABLEADER_NONE` -- `PhpOffice\PhpWord\Style\Table::WIDTH_AUTO` -- `PhpOffice\PhpWord\Style\Table::WIDTH_PERCENT` -- `PhpOffice\PhpWord\Style\Table::WIDTH_TWIP` -- `PhpOffice\PhpWord\PhpWord::DEFAULT_FONT_NAME` -- `PhpOffice\PhpWord\PhpWord::DEFAULT_FONT_SIZE` -- `PhpOffice\PhpWord\PhpWord::DEFAULT_FONT_COLOR` -- `PhpOffice\PhpWord\PhpWord::DEFAULT_FONT_CONTENT_TYPE` -- -#### Dropped methods: - -- `PhpOffice\PhpWord\Ekement\AbstractContainer::createTextRun()` -- `PhpOffice\PhpWord\Ekement\AbstractContainer::createFootnote()` -- `PhpOffice\PhpWord\Ekement\Footnote::getReferenceId()` -- `PhpOffice\PhpWord\Ekement\Footnote::setReferenceId()` -- `PhpOffice\PhpWord\Ekement\Image::getIsWatermark()` -- `PhpOffice\PhpWord\Ekement\Image::getIsMemImage()` -- `PhpOffice\PhpWord\Ekement\Link::getTarget()` -- `PhpOffice\PhpWord\Ekement\Link::getLinkSrc()` -- `PhpOffice\PhpWord\Ekement\Link::getLinkName()` -- `PhpOffice\PhpWord\Ekement\OLEObject::getObjectId()` -- `PhpOffice\PhpWord\Ekement\OLEObject::setObjectId()` -- `PhpOffice\PhpWord\Ekement\Section::getFootnotePropoperties()` -- `PhpOffice\PhpWord\Ekement\Section::setSettings()` -- `PhpOffice\PhpWord\Ekement\Section::getSettings()` -- `PhpOffice\PhpWord\Ekement\Section::createHeader()` -- `PhpOffice\PhpWord\Ekement\Section::createFooter()` -- `PhpOffice\PhpWord\Ekement\Section::getFooter()` -- `PhpOffice\PhpWord\Media::addSectionMediaElement()` -- `PhpOffice\PhpWord\Media::addSectionLinkElement()` -- `PhpOffice\PhpWord\Media::getSectionMediaElements()` -- `PhpOffice\PhpWord\Media::countSectionMediaElements()` -- `PhpOffice\PhpWord\Media::addHeaderMediaElement()` -- `PhpOffice\PhpWord\Media::countHeaderMediaElements()` -- `PhpOffice\PhpWord\Media::getHeaderMediaElements()` -- `PhpOffice\PhpWord\Media::addFooterMediaElement()` -- `PhpOffice\PhpWord\Media::countFooterMediaElements()` -- `PhpOffice\PhpWord\Media::getFooterMediaElements()` -- `PhpOffice\PhpWord\PhpWord::getProtection()` -- `PhpOffice\PhpWord\PhpWord::loadTemplate()` -- `PhpOffice\PhpWord\PhpWord::createSection()` -- `PhpOffice\PhpWord\PhpWord::getDocumentProperties()` -- `PhpOffice\PhpWord\PhpWord::setDocumentProperties()` -- `PhpOffice\PhpWord\Reader\AbstractReader::getReadDataOnly()` -- `PhpOffice\PhpWord\Settings::getCompatibility()` -- `PhpOffice\PhpWord\Style\AbstractStyle::setArrayStyle()` -- `PhpOffice\PhpWord\Style\Cell::getDefaultBorderColor()` -- `PhpOffice\PhpWord\Style\Font::getBold()` -- `PhpOffice\PhpWord\Style\Font::getItalic()` -- `PhpOffice\PhpWord\Style\Font::getSuperScript()` -- `PhpOffice\PhpWord\Style\Font::getSubScript()` -- `PhpOffice\PhpWord\Style\Font::getStrikethrough()` -- `PhpOffice\PhpWord\Style\Font::getParagraphStyle()` -- `PhpOffice\PhpWord\Style\Frame::getAlign()` -- `PhpOffice\PhpWord\Style\Frame::setAlign()` -- `PhpOffice\PhpWord\Style\NumberingLevel::getAlign()` -- `PhpOffice\PhpWord\Style\NumberingLevel::setAlign()` -- `PhpOffice\PhpWord\Style\Paragraph::getAlign()` -- `PhpOffice\PhpWord\Style\Paragraph::setAlign()` -- `PhpOffice\PhpWord\Style\Paragraph::getWidowControl()` -- `PhpOffice\PhpWord\Style\Paragraph::getKeepNext()` -- `PhpOffice\PhpWord\Style\Paragraph::getKeepLines()` -- `PhpOffice\PhpWord\Style\Paragraph::getPageBreakBefore()` -- `PhpOffice\PhpWord\Style\Row::getTblHeader()` -- `PhpOffice\PhpWord\Style\Row::isTblHeader()` -- `PhpOffice\PhpWord\Style\Row::getCantSplit()` -- `PhpOffice\PhpWord\Style\Row::getExactHeight()` -- `PhpOffice\PhpWord\Style\Spacing::getRule()` -- `PhpOffice\PhpWord\Style\Spacing::setRule()` -- `PhpOffice\PhpWord\Style\Table::getAlign()` -- `PhpOffice\PhpWord\Style\Table::setAlign()` -- `PhpOffice\PhpWord\Writer\AbstractWriter::getUseDiskCaching()` -- `PhpOffice\PhpWord\Writer\HTML::writeDocument()` - -### Bug fixes - -- Multiple PHP 8.1 fixes -- `loadConfig` returns config that was actually applied -- HTML Reader : Override inline style on HTML attribute for table -- HTML Reader : Use `border` attribute for tables -- HTML Reader : Style page-break-after in paragraph -- HTML Reader : Heading in Text Run is not allowed -- -### Miscellaneous - -- Drop support for PHP 7.0 and older - -## [0.18.3](https://github.com/PHPOffice/PHPWord/tree/0.18.3) (2022-02-17) - -[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.18.2...0.18.3) - -### Bug fixes -- PHP 8.1 compatibility - -## [0.18.2](https://github.com/PHPOffice/PHPWord/tree/0.18.2) (2021-06-04) - -[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.18.1...0.18.2) - -### Bug fixes -- when adding image to relationship first check that the generated RID is actually unique [\#2063](https://github.com/PHPOffice/PHPWord/pull/2063) ([tpv-ebben](https://github.com/tpv-ebben)) -- Update chart, don't write 'c:overlap' if grouping is 'clustered' [\#2052](https://github.com/PHPOffice/PHPWord/pull/2052) ([dfsd534](https://github.com/dfsd534)) -- Update Html parser to accept line-height:normal [\#2041](https://github.com/PHPOffice/PHPWord/pull/2041) ([joelgo](https://github.com/joelgo)) -- Fix image border in Word2007 Writer for LibreOffice 7 [\#2021](https://github.com/PHPOffice/PHPWord/pull/2021) ([kamilmmach](https://github.com/kamilmmach)) - -### Miscellaneous -- Corrected namespace for Language class in docs. [\#2087](https://github.com/PHPOffice/PHPWord/pull/2087) ([MegaChriz](https://github.com/MegaChriz)) -- Added support for Garamond font [\#2078](https://github.com/PHPOffice/PHPWord/pull/2078) ([artemkolotilkin](https://github.com/artemkolotilkin)) -- Add BorderStyle for Cell Style to documentation [\#2090](https://github.com/PHPOffice/PHPWord/pull/2090) ([DShkrabak](https://github.com/DShkrabak)) - -## [0.18.1](https://github.com/PHPOffice/PHPWord/tree/0.18.1) (2021-03-08) - -[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.18.0...0.18.1) - -### Bug fixes -- Fix BC break in #1946. This package does not replace laminas/laminas-zendframework-bridge [\#2032](https://github.com/PHPOffice/PHPWord/pull/2032) ([mussbach](https://github.com/mussbach)) - -## [0.18.0](https://github.com/PHPOffice/PHPWord/tree/0.18.0) (2021-02-12) - -[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.17.0...0.18.0) - -### Enhancements -- Add support for charts in template processor [\#2012](https://github.com/PHPOffice/PHPWord/pull/2012) ([dbarzin](https://github.com/dbarzin)) -- add/setting page element border style. [\#1986](https://github.com/PHPOffice/PHPWord/pull/1986) ([emnabs](https://github.com/emnabs)) -- allow to use customized pdf library [\#1983](https://github.com/PHPOffice/PHPWord/pull/1983) ([SailorMax](https://github.com/SailorMax)) -- feat: Update addHtml to handle style inheritance [\#1965](https://github.com/PHPOffice/PHPWord/pull/1965) ([Julien1138](https://github.com/Julien1138)) -- Add parsing of Shape node values [\#1924](https://github.com/PHPOffice/PHPWord/pull/1924) ([sven-ahrens](https://github.com/sven-ahrens)) -- Allow to redefine TCPDF object [\#1907](https://github.com/PHPOffice/PHPWord/pull/1907) ([SailorMax](https://github.com/SailorMax)) -- Enhancements to addHTML parser [\#1902](https://github.com/PHPOffice/PHPWord/pull/1902) ([lubosdz](https://github.com/lubosdz)) -- Make Default Paper Configurable [\#1851](https://github.com/PHPOffice/PHPWord/pull/1851) ([oleibman](https://github.com/oleibman)) -- Implement various missing features for the ODT writer [\#1796](https://github.com/PHPOffice/PHPWord/pull/1796) ([oleibman](https://github.com/oleibman)) -- Added support for "cloudConvert" images [\#1794](https://github.com/PHPOffice/PHPWord/pull/1794) ([ErnestStaug](https://github.com/ErnestStaug)) -- Add support for several features for the RTF writer [\#1775](https://github.com/PHPOffice/PHPWord/pull/1775) ([oleibman](https://github.com/oleibman)) -- Add font style for Field elements [\#1774](https://github.com/PHPOffice/PHPWord/pull/1774) ([oleibman](https://github.com/oleibman)) -- Add support for ListItemRun in HTML writer [\#1766](https://github.com/PHPOffice/PHPWord/pull/1766) ([stefan-91](https://github.com/stefan-91)) -- Improvements in RTF writer [\#1755](https://github.com/PHPOffice/PHPWord/pull/1755) ([oleibman](https://github.com/oleibman)) -- Allow a closure to be passed with image replacement tags [\#1716](https://github.com/PHPOffice/PHPWord/pull/1716) ([mbardelmeijer](https://github.com/mbardelmeijer)) -- Add Option for Dynamic Chart Legend Position [\#1699](https://github.com/PHPOffice/PHPWord/pull/1699) ([Stephan212](https://github.com/Stephan212)) -- Add parsing of HTML checkbox input field [\#1832](https://github.com/PHPOffice/PHPWord/pull/1832) ([Matze2010](https://github.com/Matze2010)) - -### Bug fixes -- Fix image stroke in libreoffice 7.x [\#1992](https://github.com/PHPOffice/PHPWord/pull/1992) ([Adizbek](https://github.com/Adizbek)) -- Fix deprecated warning for non-hexadecimal number [\#1988](https://github.com/PHPOffice/PHPWord/pull/1988) ([Ciki](https://github.com/Ciki)) -- Fix limit not taken into account when adding image in template [\#1967](https://github.com/PHPOffice/PHPWord/pull/1967) ([jsochor](https://github.com/jsochor)) -- Add null check when setComplexValue is not found [\#1936](https://github.com/PHPOffice/PHPWord/pull/1936) ([YannikFirre](https://github.com/YannikFirre)) -- Some document have non-standard locale code [\#1824](https://github.com/PHPOffice/PHPWord/pull/1824) ([ErnestStaug](https://github.com/ErnestStaug)) -- Fixes PHPDoc @param and @return types for several Converter methods [\#1818](https://github.com/PHPOffice/PHPWord/pull/1818) ([caugner](https://github.com/caugner)) -- Update the regexp to avoid catastrophic backtracking [\#1809](https://github.com/PHPOffice/PHPWord/pull/1809) ([juzser](https://github.com/juzser)) -- Fix PHPUnit tests on develop branch [\#1771](https://github.com/PHPOffice/PHPWord/pull/1771) ([mdupont](https://github.com/mdupont)) -- TemplateProcessor cloneBlock wrongly clones images [\#1763](https://github.com/PHPOffice/PHPWord/pull/1763) ([alarai](https://github.com/alarai)) - -### Miscellaneous -- Compatibility with PHP 7.4, PHP 8.0 and migrate to Laminas Escaper [\#1946](https://github.com/PHPOffice/PHPWord/pull/1946) ([liborm85](https://github.com/liborm85)) -- Remove legacy PHPOffice/Common package, fix PHP 8.0 compatibility [\#1996](https://github.com/PHPOffice/PHPWord/pull/1996) ([liborm85](https://github.com/liborm85)) -- Improve Word2007 Test Coverage [\#1858](https://github.com/PHPOffice/PHPWord/pull/1858) ([oleibman](https://github.com/oleibman)) -- Fix typo in docs. Update templates-processing.rst [\#1952](https://github.com/PHPOffice/PHPWord/pull/1952) ([mnvx](https://github.com/mnvx)) -- Fix documentation and method name for FootnoteProperties [\#1776](https://github.com/PHPOffice/PHPWord/pull/1776) ([mdupont](https://github.com/mdupont)) -- fix: documentation about paragraph indentation [\#1764](https://github.com/PHPOffice/PHPWord/pull/1764) ([mdupont](https://github.com/mdupont)) -- Update templates-processing.rst [\#1745](https://github.com/PHPOffice/PHPWord/pull/1745) ([igronus](https://github.com/igronus)) -- Unused variables $rows, $cols in sample [\#1877](https://github.com/PHPOffice/PHPWord/pull/1877) ([ThanasisMpalatsoukas](https://github.com/ThanasisMpalatsoukas)) -- Add unit test for NumberingStyle [\#1744](https://github.com/PHPOffice/PHPWord/pull/1744) ([Manunchik](https://github.com/Manunchik)) -- Add unit test for PhpWord Settings [\#1743](https://github.com/PHPOffice/PHPWord/pull/1743) ([Manunchik](https://github.com/Manunchik)) -- Add unit test for Media elements [\#1742](https://github.com/PHPOffice/PHPWord/pull/1742) ([Manunchik](https://github.com/Manunchik)) -- Update templates processing docs [\#1729](https://github.com/PHPOffice/PHPWord/pull/1729) ([hcdias](https://github.com/hcdias)) - -v0.17.0 (01 oct 2019) ----------------------- -### Added -- Add methods setValuesFromArray and cloneRowFromArray to the TemplateProcessor @geraldb-nicat #670 -- Set complex type in template @troosan #1565 -- implement support for section vAlign @troosan #1569 -- ParseStyle for border-color @Gllrm0 #1551 -- Html writer auto invert text color @SailorMax #1387 -- Add RightToLeft table presentation. @troosan #1550 -- Add support for page vertical alignment. @troosan #672 #1569 -- Adding setNumId method for ListItem style @eweso #1329 -- Add support for basic fields in RTF writer. @Samuel-BF #1717 - -### Fixed -- Fix HTML border-color parsing. @troosan #1551 #1570 -- Language::validateLocale should pass with locale 'zxx'. @efpapado #1558 -- can't align center vertically with the text @ter987 #672 -- fix parsing of border-color and add test @troosan #1570 -- TrackChange doesn't handle all return types of \DateTime::createFromFormat(...) @superhaggis #1584 -- To support PreserveText inside sub container @bhattnishant #1637 -- No nested w:pPr elements in ListItemRun. @waltertamboer #1628 -- Ensure that entity_loader disable variable is re-set back to the original setting @seamuslee001 #1585 - -### Miscellaneous -- Use embedded http server to test loading of remote images @troosan #1544 -- Change private to protected to be able extending class Html @SpinyMan #1646 -- Fix apt-get crash in Travis CI for PHP 5.3 @mdupont #1707 - -v0.16.0 (30 dec 2018) ----------------------- -### Added -- Add getVariableCount method in TemplateProcessor. @nicoder #1272 -- Add setting Chart Title and Legend visibility @Tom-Magill #1433 -- Add ability to pass a Style object in Section constructor @ndench #1416 -- Add support for hidden text @Alexmg86 #1527 -- Add support for setting images in TemplateProcessor @SailorMax #1170 -- Add "Plain Text" type to SDT (Structured Document Tags) @morrisdj #1541 -- Added possibility to index variables inside cloned block in TemplateProcessor @JPBetley #817 -- Added possibility to replace variables inside cloned block with values in TemplateProcessor @DIDoS #1392 - -### Fixed -- Fix regex in `cloneBlock` function @nicoder #1269 -- HTML Title Writer loses text when Title contains a TextRun instead a string. @begnini #1436 -- Fix regex in fixBrokenMacros, make it less greedy @MuriloSo @brainwood @yurii-sio2 #1502 #1345 -- 240 twips are being added to line spacing, should not happen when using lineRule fixed @troosan #1509 #1505 -- Adding table layout to the generated HTML @aarangara #1441 -- Fix loading of Sharepoint document @Garrcomm #1498 -- RTF writer: Round getPageSizeW and getPageSizeH to avoid decimals @Patrick64 #1493 -- Fix parsing of Office 365 documents @Timanx #1485 -- For RTF writers, sizes should should never have decimals @Samuel-BF #1536 -- Style Name Parsing fails if document generated by a non-english word version @begnini #1434 - -### Miscellaneous -- Get rid of duplicated code in TemplateProcessor @abcdmitry #1161 - -v0.15.0 (14 Jul 2018) ----------------------- -### Added -- Parsing of `align` HTML attribute - @troosan #1231 -- Parse formatting inside HTML lists - @troosan @samimussbach #1239 #945 #1215 #508 -- Parsing of CSS `direction` instruction, HTML `lang` attribute, formatting inside table cell - @troosan #1273 #1252 #1254 -- Add support for Track changes @Cip @troosan #354 #1262 -- Add support for fixed Table Layout @aoloe @ekopach @troosan #841 #1276 -- Add support for Cell Spacing @dox07 @troosan #1040 -- Add parsing of formatting inside lists @atomicalnet @troosan #594 -- Added support for Vertically Raised or Lowered Text (w:position) @anrikun @troosan #640 -- Add support for MACROBUTTON field @phryneas @troosan #1021 -- Add support for Hyphenation @Trainmaster #1282 (Document: `autoHyphenation`, `consecutiveHyphenLimit`, `hyphenationZone`, `doNotHyphenateCaps`, Paragraph: `suppressAutoHyphens`) -- Added support for Floating Table Positioning (tblpPr) @anrikun #639 -- Added support for Image text wrapping distance @troosan #1310 -- Added parsing of CSS line-height and text-indent in HTML reader @troosan #1316 -- Added the ability to enable gridlines and axislabels on charts @FrankMeyer #576 -- Add support for table indent (tblInd) @Trainmaster #1343 -- Added parsing of internal links in HTML reader @lalop #1336 -- Several improvements to charts @JAEK-S #1332 -- Add parsing of html image in base64 format @jgpATs2w #1382 -- Added Support for Indentation & Tabs on RTF Writer. @smaug1985 #1405 -- Allows decimal numbers in HTML line-height style @jgpATs2w #1413 - -### Fixed -- Fix reading of docx default style - @troosan #1238 -- Fix the size unit of when parsing html images - @troosan #1254 -- Fixed HTML parsing of nested lists - @troosan #1265 -- Save PNG alpha information when using remote images. @samsullivan #779 -- Fix parsing of `` tag. @troosan #1274 -- Bookmark are not writton as internal link in html writer @troosan #1263 -- It should be possible to add a Footnote in a ListItemRun @troosan #1287 #1287 -- Fix colspan and rowspan for tables in HTML Writer @mattbolt #1292 -- Fix parsing of Heading and Title formating @troosan @gthomas2 #465 -- Fix Dateformat typo, fix hours casing, add Month-Day-Year formats @ComputerTinker #591 -- Support reading of w:drawing for documents produced by word 2011+ @gthomas2 #464 #1324 -- Fix missing column width in ODText writer @potofcoffee #413 -- Disable entity loader before parsing XML to avoid XXE injection @Tom4t0 #1427 - -### Changed -- Remove zend-stdlib dependency @Trainmaster #1284 -- The default unit for `\PhpOffice\PhpWord\Style\Image` changed from `px` to `pt`. - -### Miscellaneous -- Drop GitHub pages, switch to coveralls for code coverage analysis @czosel #1360 - -v0.14.0 (29 Dec 2017) ----------------------- -This release fixes several bugs and adds some new features. -This version brings compatibility with PHP 7.0 & 7.1 - -### Added -- Possibility to control the footnote numbering - @troosan #1068 -- Image creation from string - @troosan #937 -- Introduced the `\PhpOffice\PhpWord\SimpleType\NumberFormat` simple type. - @troosan -- Support for ContextualSpacing - @postHawk #1088 -- Possiblity to hide spelling and/or grammatical errors - @troosan #542 -- Possiblity to set default document language as well as changing the language for each text element - @troosan #1108 -- Support for Comments - @troosan #1067 -- Support for paragraph textAlignment - @troosan #1165 -- Add support for HTML underline tag in addHtml - @zNightFalLz #1186 -- Add support for HTML
    in addHtml - @anrikun @troosan #659 -- Allow to change cell width unit - guillaume-ro-fr #986 -- Allow to change the line height rule @troosan -- Implement PageBreak for odt writer @cookiekiller #863 #824 -- Allow to force an update of all fields on opening a document - @troosan #951 -- Allow adding a CheckBox in a TextRun - @irond #727 -- Add support for HTML img tag - @srggroup #934 -- Add support for password protection for docx - @mariahaubner #1019 - -### Fixed -- Loosen dependency to Zend -- Images are not being printed when generating PDF - @hubertinio #1074 #431 -- Fixed some PHP 7 warnings - @ likeuntomurphy #927 -- Fixed PHP 7.2 compatibility (renamed `Object` class names to `ObjectElement`) - @SailorMax #1185 -- Fixed Word 97 reader - @alsofronie @Benpxpx @mario-rivera #912 #920 #892 -- Fixed image loading over https - @troosan #988 -- Impossibility to set different even and odd page headers - @troosan #981 -- Fixed Word2007 reader where unnecessary paragraphs were being created - @donghaobo #1043 #620 -- Fixed Word2007 reader where margins were not being read correctly - @slowprog #885 #1008 -- Impossible to add element PreserveText in Section - @rvanlaak #452 -- Added missing options for numbering format - @troosan #1041 -- Fixed impossibility to set a different footer for first page - @ctrlaltca #1116, @aoloe #875 -- Fixed styles not being applied by HTML writer, better pdf output - @sarke #1047 #500 #1139 -- Fixed read docx error when document contains image from remote url - @FBnil #1173 #1176 -- Padded the $args array to remove error - @kaigoh #1150, @reformed #870 -- Fix incorrect image size between windows and mac - @bskrtich #874 -- Fix adding HTML table to document - @mogilvie @arivanbastos #324 -- Fix parsing on/off values (w:val="true|false|1|0|on|off") - @troosan #1221 #1219 -- Fix error on Empty Dropdown Entry - @ComputerTinker #592 - -### Deprecated -- PhpWord->getProtection(), get it from the settings instead PhpWord->getSettings()->getDocumentProtection(); - - - -v0.13.0 (31 July 2016) -------------------- -This release brings several improvements in `TemplateProcessor`, automatic output escaping feature for OOXML, ODF, HTML, and RTF (turned off, by default). -It also introduces constants for horizontal alignment options, and resolves some issues with PHP 7. -Manual installation feature has been dropped since the release. Please, use [Composer](https://getcomposer.org/) to install PHPWord. - -### Added -- Introduced the `\PhpOffice\PhpWord\SimpleType\Jc` simple type. - @RomanSyroeshko -- Introduced the `\PhpOffice\PhpWord\SimpleType\JcTable` simple type. - @RomanSyroeshko -- Introduced writer for the "Paragraph Alignment" element (see `\PhpOffice\PhpWord\Writer\Word2007\Element\ParagraphAlignment`). - @RomanSyroeshko -- Introduced writer for the "Table Alignment" element (see `\PhpOffice\PhpWord\Writer\Word2007\Element\TableAlignment`). - @RomanSyroeshko -- Supported indexed arrays in arguments of `TemplateProcessor::setValue()`. - @RomanSyroeshko #618 -- Introduced automatic output escaping for OOXML, ODF, HTML, and RTF. To turn the feature on use `phpword.ini` or `\PhpOffice\PhpWord\Settings`. - @RomanSyroeshko #483 -- Supported processing of headers and footers in `TemplateProcessor::applyXslStyleSheet()`. - @RomanSyroeshko #335 - -### Changed -- Improved error message for the case when `autoload.php` is not found. - @RomanSyroeshko #371 -- Renamed the `align` option of `NumberingLevel`, `Frame`, `Table`, and `Paragraph` styles into `alignment`. - @RomanSyroeshko -- Improved performance of `TemplateProcessor::setValue()`. - @kazitanvirahsan #614, #617 -- Fixed some HTML tags not rendering any output (p, header & table) - #257, #324 - @twmobius and @garethellis - -### Deprecated -- `getAlign` and `setAlign` methods of `NumberingLevel`, `Frame`, `Table`, and `Paragraph` styles. -Use the correspondent `getAlignment` and `setAlignment` methods instead. - @RomanSyroeshko -- `left`, `right`, and `justify` alignment options for paragraphs (now are mapped to `Jc::START`, `Jc::END`, and `Jc::BOTH`). - @RomanSyroeshko -- `left`, `right`, and `justify` alignment options for tables (now are mapped to `Jc::START`, `Jc::END`, and `Jc::CENTER`). - @RomanSyroeshko -- `TCPDF` due to its limited HTML support. Use `DomPDF` or `MPDF` writer instead. - @RomanSyroeshko #399 - -### Removed -- `\PhpOffice\PhpWord\Style\Alignment`. Style properties, which previously stored instances of this class, now deal with strings. -In each case set of available string values is defined by the correspondent simple type. - @RomanSyroeshko -- Manual installation support. Since the release we have dependencies on third party libraries, -so installation via ZIP-archive download is not an option anymore. To install PHPWord use [Composer](https://getcomposer.org/). - We also removed `\PhpOffice\PhpWord\Autoloader`, because the latter change made it completely useless. - Autoloaders provided by Composer are in use now (see `bootstrap.php`). - @RomanSyroeshko -- `\PhpOffice\PhpWord\Shared\Drawing` replaced by `\PhpOffice\Common\Drawing`. - @Progi1984 #658 -- `\PhpOffice\PhpWord\Shared\Font`. - @Progi1984 #658 -- `\PhpOffice\PhpWord\Shared\String` replaced by `\PhpOffice\Common\Text`. - @Progi1984 @RomanSyroeshko #658 -- `\PhpOffice\PhpWord\Shared\XMLReader` replaced by `\PhpOffice\Common\XMLReader`. - @Progi1984 #658 -- `\PhpOffice\PhpWord\Shared\XMLWriter` replaced by `\PhpOffice\Common\XMLWriter`. - @Progi1984 @RomanSyroeshko #658 -- `AbstractContainer::addMemoryImage()`. Use `AbstractContainer::addImage()` instead. - -### Fixed -- `Undefined property` error while reading MS-DOC documents. - @jaberu #610 -- Corrupted OOXML template issue in case when its names is broken immediately after `$` sign. -That case wasn't taken into account in implementation of `TemplateProcessor::fixBrokenMacros()`. - @RomanSyroeshko @d-damien #548 - - - -v0.12.1 (30 August 2015) ------------------------ -Maintenance release. This release is focused primarily on `TemplateProcessor`. - -### Changes -- Changed visibility of all private properties and methods of `TemplateProcessor` to `protected`. - @RomanSyroeshko #498 -- Improved performance of `TemplateProcessor::setValue()`. - @RomanSyroeshko @nicoSWD #513 - -### Bugfixes -- Fixed issue with "Access denied" message while opening `Sample_07_TemplateCloneRow.docx` and `Sample_23_TemplateBlock.docx` result files on Windows platform. - @RomanSyroeshko @AshSat #532 -- Fixed `PreserveText` element alignment in footer (see `Sample_12_HeaderFooter.php`). - @RomanSyroeshko @SSchwaiger #495 - - - -v0.12.0 (3 January 2015) ------------------------ -This release added form fields (textinput, checkbox, and dropdown), drawing shapes (arc, curve, line, polyline, rect, oval), and basic 2D chart (pie, doughnut, bar, line, area, scatter, radar) elements along with some new styles. Basic MsDoc reader is introduced. - -### Features -- Element: Ability to add drawing shapes (arc, curve, line, polyline, rect, oval) using new `Shape` element - @ivanlanin #123 -- Font: New `scale`, `spacing`, and `kerning` property of font style - @ivanlanin -- Paragraph: Added shading to the paragraph style for full width shading - @lrobert #264 -- RTF Writer: Support for sections, margins, and borders - @ivanlanin #249 -- Section: Ability to set paper size, e.g. A4, A3, and Legal - @ivanlanin #249 -- General: New `PhpWord::save()` method to encapsulate `IOFactory` - @ivanlanin -- General: New `Shared\Converter` static class - @ivanlanin -- Chart: Basic 2D chart (pie, doughnut, bar, line, area, scatter, radar) - @ivanlanin #278 -- Chart: 3D charts and ability to set width and height - @ivanlanin -- FormField: Ability to add textinput, checkbox, and dropdown form elements - @ivanlanin #266 -- Setting: Ability to define document protection (readOnly, comments, trackedChanges, forms) - @ivanlanin -- Setting: Ability to remove [Compatibility Mode] text in the MS Word title bar - @ivanlanin -- SDT: Ability to add structured document tag elements (comboBox, dropDownList, date) - @ivanlanin -- Paragraph: Support for paragraph with borders - @ivanlanin #294 -- Word2007 Writer : Support for RTL - @Progi1984 #331 -- MsDOC Reader: Basic MsDOC Reader - @Progi1984 #23, #287 -- "absolute" horizontal and vertical positioning of Frame - @basjan #302 -- Add new-page function for PDF generation. For multiple PDF-backends - @chc88 #426 -- Report style options enumerated when style unknown - @h6w - -### Bugfixes -- Fix rare PclZip/realpath/PHP version problem - @andrew-kzoo #261 -- `addHTML` encoding and ampersand fixes for PHP 5.3 - @bskrtich #270 -- Page breaks on titles and tables - @ivanlanin #274 -- Table inside vertical border does not rendered properly - @ivanlanin #280 -- `add` of container should be case insensitive, e.g. `addToc` should be accepted, not only `addTOC` - @ivanlanin #294 -- Fix specific borders (and margins) were not written correctly in word2007 writer - @pscheit #327 -- "HTML is not a valid writer" exception while running "Sample_36_RTL.php" - @RomanSyroeshko #340 -- "addShape()" magic method in AbstractContainer is mistakenly named as "addObject()" - @GMTA #356 -- `Element\Section::setPageSizeW()` and `Element\Section::setPageSizeH()` were mentioned in the docs but not implemented. -- Special Characters (ampersand) in Title break docx output - @RomanSyroeshko #401 -- `` tag is closed with `` tag: - @franzholz #438 - -### Deprecated -- `Element\Link::getTarget()` replaced by `Element\Link::getSource()` -- `Element\Section::getSettings()` and `Element\Section::setSettings()` replaced by `Element\Section::getStyle()` and `Element\Section::setStyle()` -- `Shared\Drawing` and `Shared\Font` merged into `Shared\Converter` -- `DocumentProperties` replaced by `Metadata\DocInfo` -- `Template` replaced by `TemplateProcessor` -- `PhpWord->loadTemplate($filename)` - -### Miscellaneous -- Docs: Add known issue on `README` about requirement for temporary folder to be writable and update `samples/index.php` for this requirement check - @ivanlanin #238 -- Docs: Correct elements.rst about Line - @chrissharkman #292 -- PclZip: Remove temporary file after used - @andrew-kzoo #265 -- Autoloader: Add the ability to set the autoloader options - @bskrtich #267 -- Element: Refactor elements to move set relation Id from container to element - @ivanlanin -- Introduced CreateTemporaryFileException, CopyFileException - @RomanSyroeshko -- Settings: added method to set user defined temporary directory - @RomanSyroeshko #310 -- Renamed `Template` into `TemplateProcessor` - @RomanSyroeshko #216 -- Reverted #51. All text escaping must be performed out of the library - @RomanSyroeshko #51 - - - -v0.11.1 (2 June 2014) --------------------- -This is an immediate bugfix release for HTML reader. - -- HTML Reader: `

    ` and header tags puts no output - @canyildiz @ivanlanin #257 - - - -v0.11.0 (1 June 2014) --------------------- -This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3. Four new elements were added: TextBox, ListItemRun, Field, and Line. Relative and absolute positioning for images and textboxes were added. Writer classes were refactored into parts, elements, and styles. ODT and RTF features were enhanced. Ability to add elements to PHPWord object via HTML were implemented. RTF and HTML reader were initiated. - -### Features -- Image: Ability to define relative and absolute positioning - @basjan #217 -- Footer: Conform footer with header by adding firstPage, evenPage and by inheritance - @basjan @ivanlanin #219 -- Element: New `TextBox` element - @basjan @ivanlanin #228, #229, #231 -- HTML: Ability to add elements to PHPWord object via html - @basjan #231 -- Element: New `ListItemRun` element that can add a list item with inline formatting like a textrun - @basjan #235 -- Table: Ability to add table inside a cell (nested table) - @ivanlanin #149 -- RTF Writer: UTF8 support for RTF: Internal UTF8 text is converted to Unicode before writing - @ivanlanin #158 -- Table: Ability to define table width (in percent and twip) and position - @ivanlanin #237 -- RTF Writer: Ability to add links and page breaks in RTF - @ivanlanin #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 #200 -- ODT Writer: Enable inline font style in TextRun - @ivanlanin -- ODT Writer: Enable underline, strike/doublestrike, smallcaps/allcaps, superscript/subscript font style - @ivanlanin -- ODT Writer: Enable section and column - @ivanlanin -- PDF Writer: Add TCPDF and mPDF as optional PDF renderer library - @ivanlanin -- ODT Writer: Enable title element and custom document properties - @ivanlanin -- ODT Reader: Ability to read standard and custom document properties - @ivanlanin -- Word2007 Writer: Enable the missing custom document properties writer - @ivanlanin -- Image: Enable "image float left" - @ivanlanin #244 -- RTF Writer: Ability to write document properties - @ivanlanin -- RTF Writer: Ability to write image - @ivanlanin -- Element: New `Field` element - @basjan #251 -- RTF Reader: Basic RTF reader - @ivanlanin #72, #252 -- Element: New `Line` element - @basjan #253 -- Title: Ability to apply numbering in heading - @ivanlanin #193 -- HTML Reader: Basic HTML reader - @ivanlanin #80, #254 -- RTF Writer: Basic table writing - @ivanlanin #245 - -### Bugfixes -- Header: All images added to the second header were assigned to the first header - @basjan #222 -- Conversion: Fix conversion from cm to pixel, pixel to cm, and pixel to point - @basjan #233, #234 -- PageBreak: Page break adds new line in the beginning of the new page - @ivanlanin #150 -- Image: `marginLeft` and `marginTop` cannot accept float value - @ivanlanin #248 -- Title: Orphan `w:fldChar` caused OpenOffice to crash when opening DOCX - @ivanlanin #236 - -### Deprecated -- Static classes `Footnotes`, `Endnotes`, and `TOC` -- `Writer\Word2007\Part`: `Numbering::writeNumbering()`, `Settings::writeSettings()`, `WebSettings::writeWebSettings()`, `ContentTypes::writeContentTypes()`, `Styles::writeStyles()`, `Document::writeDocument()` all changed into `write()` -- `Writer\Word2007\Part\DocProps`: Split into `Writer\Word2007\Part\DocPropsCore` and `Writer\Word2007\Part\DocPropsApp` -- `Element\Title::getBookmarkId()` replaced by `Element\Title::getRelationId()` -- `Writer\HTML::writeDocument`: Replaced by `Writer\HTML::getContent` - -### Miscellaneous -- License: Change the project license from LGPL 2.1 into LGPL 3.0 - #211 -- Word2007 Writer: New `Style\Image` class - @ivanlanin -- Refactor: Replace static classes `Footnotes`, `Endnotes`, and `TOC` with `Collections` - @ivanlanin #206 -- QA: Reactivate `phpcpd` and `phpmd` on Travis - @ivanlanin -- Refactor: PHPMD recommendation: Change all `get...` method that returns `boolean` into `is...` or `has...` - @ivanlanin -- Docs: Create gh-pages branch for API documentation - @Progi1984 #154 -- QA: Add `.scrutinizer.yml` and include `composer.lock` for preparation to Scrutinizer - @ivanlanin #186 -- Writer: Refactor writer parts using composite pattern - @ivanlanin -- Docs: Show code quality and test code coverage badge on README -- Style: Change behaviour of `set...` function of boolean properties; when none is defined, assumed true - @ivanlanin -- Shared: Unify PHP ZipArchive and PCLZip features into PhpWord ZipArchive - @ivanlanin -- Docs: Create VERSION file - @ivanlanin -- QA: Improve dan update requirement check in `samples` folder - @ivanlanin - - - -v0.10.1 (21 May 2014) --------------------- -This is a bugfix release for `php-zip` requirement in Composer. - -- Change Composer requirements for php-zip from `require` to `suggest` - @bskrtich #246 - - - -v0.10.0 (4 May 2014) -------------------- -This release marked heavy refactorings on internal code structure with the creation of some abstract classes to reduce code duplication. `Element` subnamespace is introduced in this release to replace `Section`. Word2007 reader capability is greatly enhanced. Endnote is introduced. List numbering is now customizable. Basic HTML and PDF writing support is enabled. Basic ODText reader is introduced. - -### Features -- Image: Get image dimensions without EXIF extension - @andrew-kzoo #184 -- Table: Add `tblGrid` element for Libre/Open Office table sizing - @gianis6 #183 -- Footnote: Ability to insert textbreak in footnote `$footnote->addTextBreak()` - @ivanlanin -- Footnote: Ability to style footnote reference mark by using `FootnoteReference` style - @ivanlanin -- Font: Add `bgColor` to font style to define background using HEX color - @jcarignan #168 -- Table: Add `exactHeight` to row style to define whether row height should be exact or atLeast - @jcarignan #168 -- Element: New `CheckBox` element for sections and table cells - @ozilion #156 -- Settings: Ability to use PCLZip as alternative to ZipArchive - @bskrtich @ivanlanin #106, #140, #185 -- Template: Ability to find & replace variables in headers & footers - @dgudgeon #190 -- Template: Ability to clone & delete block of text using `cloneBlock` and `deleteBlock` - @diego-vieira #191 -- TOC: Ability to have two or more TOC in one document and to set min and max depth for TOC - @Pyreweb #189 -- Table: Ability to add footnote in table cell - @ivanlanin #187 -- Footnote: Ability to add image in footnote - @ivanlanin #187 -- ListItem: Ability to add list item in header/footer - @ivanlanin #187 -- CheckBox: Ability to add checkbox in header/footer - @ivanlanin #187 -- Link: Ability to add link in header/footer - @ivanlanin #187 -- Object: Ability to add object in header, footer, textrun, and footnote - @ivanlanin #187 -- Media: Add `Media::resetElements()` to reset all media data - @juzi #19 -- General: Add `Style::resetStyles()` - @ivanlanin #187 -- DOCX Reader: Ability to read header, footer, footnotes, link, preservetext, textbreak, pagebreak, table, list, image, and title - @ivanlanin -- Endnote: Ability to add endnotes - @ivanlanin -- ListItem: Ability to create custom list and reset list number - @ivanlanin #10, #198 -- ODT Writer: Basic table writing support - @ivanlanin -- Image: Keep image aspect ratio if only 1 dimension styled - @japonicus #194 -- HTML Writer: Basic HTML writer: text, textrun, link, title, textbreak, table, image (as Base64), footnote, endnote - @ivanlanin #203, #67, #147 -- PDF Writer: Basic PDF writer using DomPDF: All HTML element except image - @ivanlanin #68 -- DOCX Writer: Change `docProps/app.xml` `Application` to `PHPWord` - @ivanlanin -- DOCX Writer: Create `word/settings.xml` and `word/webSettings.xml` dynamically - @ivanlanin -- ODT Writer: Basic image writing - @ivanlanin -- ODT Writer: Link writing - @ivanlanin -- ODT Reader: Basic ODText Reader - @ivanlanin #71 -- Section: Ability to define gutter and line numbering - @ivanlanin -- Font: Small caps, all caps, and double strikethrough - @ivanlanin #151 -- Settings: Ability to use measurement unit other than twips with `setMeasurementUnit` - @ivanlanin #199 -- Style: Remove `bgColor` from `Font`, `Table`, and `Cell` and put it into the new `Shading` style - @ivanlanin -- Style: New `Indentation` and `Spacing` style - @ivanlanin -- Paragraph: Ability to define first line and right indentation - @ivanlanin - -### Bugfixes -- Footnote: Footnote content doesn't show footnote reference number - @ivanlanin #170 -- Documentation: Error in a function - @theBeerNut #195 - -### Deprecated -- `createTextRun` replaced by `addTextRun` -- `createFootnote` replaced by `addFootnote` -- `createHeader` replaced by `addHeader` -- `createFooter` replaced by `addFooter` -- `createSection` replaced by `addSection` -- `Element\Footnote::getReferenceId` replaced by `Element\AbstractElement::getRelationId` -- `Element\Footnote::setReferenceId` replaced by `Element\AbstractElement::setRelationId` -- `Footnote::addFootnoteLinkElement` replaced by `Media::addElement` -- `Footnote::getFootnoteLinkElements` replaced by `Media::getElements` -- All current methods on `Media` -- `Element\Link::getLinkSrc` replaced by `Element\Link::getTarget` -- `Element\Link::getLinkName` replaced by `Element\Link::getText` -- `Style\Cell::getDefaultBorderColor` - -### Miscellaneous -- Documentation: Simplify page level docblock - @ivanlanin #179 -- Writer: Refactor writer classes and create a new `Write\AbstractWriter` abstract class - @ivanlanin #160 -- General: Refactor folders: `Element` and `Exception` - @ivanlanin #187 -- General: Remove legacy `HashTable` and `Shared\ZipStreamWrapper` and all related properties/methods - @ivanlanin #187 -- Element: New `AbstractElement` abstract class - @ivanlanin #187 -- Media: Refactor media class to use one method for all docPart (section, header, footer, footnote) - @ivanlanin #187 -- General: Remove underscore prefix from all private properties name - @ivanlanin #187 -- General: Move Section `Settings` to `Style\Section` - @ivanlanin #187 -- General: Give `Abstract` prefix and `Interface` suffix for all abstract classes and interfaces as per [PHP-FIG recommendation](https://github.com/php-fig/fig-standards/blob/master/bylaws/002-psr-naming-conventions.md) - @ivanlanin #187 -- Style: New `Style\AbstractStyle` abstract class - @ivanlanin #187 -- Writer: New 'ODText\Base` class - @ivanlanin #187 -- General: Rename `Footnote` to `Footnotes` to reflect the nature of collection - @ivanlanin -- General: Add some unit tests for Shared & Element (100%!) - @Progi1984 -- Test: Add some samples and tests for image wrapping style - @brunocasado #59 -- Refactor: Remove Style\Tabs - @ivanlanin -- Refactor: Apply composite pattern for writers - @ivanlanin -- Refactor: Split `AbstractContainer` from `AbstractElement` - @ivanlanin -- Refactor: Apply composite pattern for Word2007 reader - @ivanlanin - - - -v0.9.1 (27 Mar 2014) -------------------- -This is a bugfix release for PSR-4 compatibility. - -- Fixed PSR-4 composer autoloader - @AntonTyutin - - - -v0.9.0 (26 Mar 2014) -------------------- -This release marked the transformation to namespaces (PHP 5.3+). - -### Features -- Image: Ability to use remote or GD images using `addImage()` on sections, headers, footer, cells, and textruns - @ivanlanin -- Header: Ability to use remote or GD images using `addWatermark()` - @ivanlanin - -### Bugfixes -- Preserve text doesn't render correctly when the text is not the first word, e.g. 'Page {PAGE}' - @ivanlanin - -### Miscellaneous -- Move documentation to [Read The Docs](http://phpword.readthedocs.org/en/develop/) - @Progi1984 @ivanlanin #82 -- Reorganize and redesign samples folder - @ivanlanin #137 -- Use `PhpOffice\PhpWord` namespace for PSR compliance - @RomanSyroeshko @gabrielbull #159, #58 -- Restructure folders and change folder name `Classes` to `src` and `Tests` to `test` for PSR compliance - @RomanSyroeshko @gabrielbull -- Compliance to phpDocumentor - @ivanlanin -- Merge Style\TableFull into Style\Table. Style\TableFull is deprecated - @ivanlanin #160 -- Merge Section\MemoryImage into Section\Image. Section\Image is deprecated - @ivanlanin #160 - - - -v0.8.1 (17 Mar 2014) -------------------- -This is a bugfix release for image detection functionality. - -- Added fallback for computers that do not have exif_imagetype - @bskrtich, @gabrielbull - - - -v0.8.0 (15 Mar 2014) -------------------- -This release merged a lot of improvements from the community. Unit tests introduced in this release and has reached 90% code coverage. - -### Features -- Template: Permit to save a template generated as a file (PHPWord_Template::saveAs()) - @RomanSyroeshko #56, #57 -- Word2007: Support sections page numbering - @gabrielbull -- Word2007: Added line height methods to mirror the line height settings in Word in the paragraph styling - @gabrielbull -- Word2007: Added support for page header & page footer height - @JillElaine #5 -- General: Add ability to manage line breaks after image insertion - @bskrtich #6, #66, #84 -- Template: Ability to limit number of replacements performed by setValue() method of Template class - @RomanSyroeshko #52, #53, #85 -- Table row: Repeat as header row & allow row to break across pages - @ivanlanin #48, #86 -- Table: Table width in percentage - @ivanlanin #48, #86 -- Font: Superscript and subscript - @ivanlanin #48, #86 -- Paragraph: Hanging paragraph - @ivanlanin #48, #86 -- Section: Multicolumn and section break - @ivanlanin #48, #86 -- Template: Ability to apply XSL style sheet to Template - @RomanSyroeshko #46, #47, #83 -- General: PHPWord_Shared_Font::pointSizeToTwips() converter - @ivanlanin #87 -- Paragraph: Ability to define normal paragraph style with PHPWord::setNormalStyle() - @ivanlanin #87 -- Paragraph: Ability to define parent style (basedOn) and style for following paragraph (next) - @ivanlanin #87 -- Clone table rows on the fly when using a template document - @jeroenmoors #44, #88 -- Initial addition of basic footnote support - @deds #16 -- Paragraph: Ability to define paragraph pagination: widow control, keep next, keep lines, and page break before - @ivanlanin #92 -- General: PHPWord_Style_Font refactoring - @ivanlanin #93 -- Font: Use points instead of halfpoints internally. Conversion to halfpoints done during XML Writing. - @ivanlanin #93 -- Paragraph: setTabs() function - @ivanlanin #92 -- General: Basic support for TextRun on ODT and RTF - @ivanlanin #99 -- Reader: Basic Reader for Word2007 - @ivanlanin #104 -- TextRun: Allow Text Break in Text Run - @bskrtich #109 -- General: Support for East Asian fontstyle - @jhfangying #111, #118 -- Image: Use exif_imagetype to check image format instead of extension name - @gabrielbull #114 -- General: Setting for XMLWriter Compatibility option - @bskrtich #103 -- MemoryImage: Allow remote image when allow_url_open = on - @ivanlanin #122 -- TextBreak: Allow font and paragraph style for text break - @ivanlanin #18 - -### Bugfixes -- Fixed bug with cell styling - @gabrielbull -- Fixed bug list items inside of cells - @gabrielbull -- Adding a value that contains "&" in a template breaks it - @SiebelsTim #51 -- Example in README.md is broken - @Progi1984 #89 -- General: PHPWord_Shared_Drawing::centimetersToPixels() conversion - @ivanlanin #94 -- Footnote: Corrupt DOCX reported by MS Word when sections > 1 and not every sections have footnote - @ivanlanin #125 - -### Miscellaneous -- UnitTests - @Progi1984 - - - -v0.7.0 (28 Jan 2014) -------------------- -This is the first release after a long development hiatus in [CodePlex](https://phpword.codeplex.com/). This release initialized ODT and RTF Writer, along with some other new features for the existing Word2007 Writer, e.g. tab, multiple header, rowspan and colspan. [Composer](https://packagist.org/packages/phpoffice/phpword) and [Travis](https://travis-ci.org/PHPOffice/PHPWord) were added. - -### Features -- Implement RTF Writer - @Progi1984 #1 -- Implement ODT Writer - @Progi1984 #2 -- Word2007: Add rowspan and colspan to cells - @kaystrobach -- Word2007: Support for tab stops - @RLovelett -- Word2007: Support Multiple headers - @RLovelett -- Word2007: Wrapping Styles to Images - @gabrielbull -- Added support for image wrapping style - @gabrielbull - -### Bugfixes -- "Warning: Invalid error type specified in ...\PHPWord.php on line 226" is thrown when the specified template file is not found - @RomanSyroeshko #32 -- PHPWord_Shared_String.IsUTF8 returns FALSE for Cyrillic UTF-8 input - @RomanSyroeshko #34 -- Temporary files naming logic in PHPWord_Template can lead to a collision - @RomanSyroeshko #38 - -### Miscellaneous -- Add superscript/subscript styling in Excel2007 Writer - @MarkBaker -- add indentation support to paragraphs - @deds -- Support for Composer - @Progi1984 #27 -- Basic CI with Travis - @Progi1984 -- Added PHPWord_Exception and exception when could not copy the template - @Progi1984 -- IMPROVED: Moved examples out of Classes directory - @Progi1984 -- IMPROVED: Advanced string replace in setValue for Template - @Esmeraldo [#49](http://phpword.codeplex.com/workitem/49) diff --git a/README.md b/README.md index ceb8451a4c..11bcd1525c 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ PHPWord is a library written in pure PHP that provides a set of classes to write to and read from different document file formats. The current version of PHPWord supports Microsoft [Office Open XML](http://en.wikipedia.org/wiki/Office_Open_XML) (OOXML or OpenXML), OASIS [Open Document Format for Office Applications](http://en.wikipedia.org/wiki/OpenDocument) (OpenDocument or ODF), [Rich Text Format](http://en.wikipedia.org/wiki/Rich_Text_Format) (RTF), HTML, and PDF. -PHPWord is an open source project licensed under the terms of [LGPL version 3](COPYING.LESSER). PHPWord is aimed to be a high quality software product by incorporating [continuous integration](https://github.com/PHPOffice/PHPWord/actions) and unit testing. You can learn more about PHPWord by reading the [Developers' Documentation](http://phpword.readthedocs.org/). +PHPWord is an open source project licensed under the terms of [LGPL version 3](COPYING.LESSER). PHPWord is aimed to be a high quality software product by incorporating [continuous integration](https://github.com/PHPOffice/PHPWord/actions) and unit testing. You can learn more about PHPWord by reading the [Developers' Documentation](https://phpoffice.github.io/PHPWord/). If you have any questions, please ask on [StackOverFlow](https://stackoverflow.com/questions/tagged/phpword) @@ -20,7 +20,7 @@ Read more about PHPWord: - [Installation](#installation) - [Getting started](#getting-started) - [Contributing](#contributing) -- [Developers' Documentation](http://phpword.readthedocs.org/) +- [Developers' Documentation](https://phpoffice.github.io/PHPWord/) ## Features @@ -150,7 +150,7 @@ $objWriter->save('helloWorld.html'); ``` More examples are provided in the [samples folder](samples/). For an easy access to those samples launch `php -S localhost:8000` in the samples directory then browse to [http://localhost:8000](http://localhost:8000) to view the samples. -You can also read the [Developers' Documentation](http://phpword.readthedocs.org/) for more detail. +You can also read the [Developers' Documentation](https://phpoffice.github.io/PHPWord/) for more detail. ## Contributing @@ -159,4 +159,4 @@ We welcome everyone to contribute to PHPWord. Below are some of the things that - Read [our contributing guide](CONTRIBUTING.md). - [Fork us](https://github.com/PHPOffice/PHPWord/fork) and [request a pull](https://github.com/PHPOffice/PHPWord/pulls) to the [master](https://github.com/PHPOffice/PHPWord/tree/master) branch. - Submit [bug reports or feature requests](https://github.com/PHPOffice/PHPWord/issues) to GitHub. -- Follow [@PHPWord](https://twitter.com/PHPWord) and [@PHPOffice](https://twitter.com/PHPOffice) on Twitter. +- Follow [@PHPOffice](https://twitter.com/PHPOffice) on Twitter. diff --git a/composer.json b/composer.json index 445b372f5f..6890bf6d9f 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "docx", "OOXML", "OpenXML", "Office Open XML", "ISO IEC 29500", "WordprocessingML", "RTF", "Rich Text Format", "doc", "odt", "ODF", "OpenDocument", "PDF", "HTML" ], - "homepage": "https://phpword.readthedocs.io/", + "homepage": "https://phpoffice.github.io/PHPWord/", "type": "library", "license": "LGPL-3.0", "authors": [ diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index bd38cd5d9d..0000000000 --- a/docs/Makefile +++ /dev/null @@ -1,153 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PHPWord.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PHPWord.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/PHPWord" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PHPWord" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/docs/changes/0.x/0.10.0.md b/docs/changes/0.x/0.10.0.md new file mode 100644 index 0000000000..3c31d772c2 --- /dev/null +++ b/docs/changes/0.x/0.10.0.md @@ -0,0 +1,84 @@ + +# 0.10.0 (4 May 2014) + +This release marked heavy refactorings on internal code structure with the creation of some abstract classes to reduce code duplication. `Element` subnamespace is introduced in this release to replace `Section`. Word2007 reader capability is greatly enhanced. Endnote is introduced. List numbering is now customizable. Basic HTML and PDF writing support is enabled. Basic ODText reader is introduced. + +### Features +- Image: Get image dimensions without EXIF extension - @andrew-kzoo #184 +- Table: Add `tblGrid` element for Libre/Open Office table sizing - @gianis6 #183 +- Footnote: Ability to insert textbreak in footnote `$footnote->addTextBreak()` - @ivanlanin +- Footnote: Ability to style footnote reference mark by using `FootnoteReference` style - @ivanlanin +- Font: Add `bgColor` to font style to define background using HEX color - @jcarignan #168 +- Table: Add `exactHeight` to row style to define whether row height should be exact or atLeast - @jcarignan #168 +- Element: New `CheckBox` element for sections and table cells - @ozilion #156 +- Settings: Ability to use PCLZip as alternative to ZipArchive - @bskrtich @ivanlanin #106, #140, #185 +- Template: Ability to find & replace variables in headers & footers - @dgudgeon #190 +- Template: Ability to clone & delete block of text using `cloneBlock` and `deleteBlock` - @diego-vieira #191 +- TOC: Ability to have two or more TOC in one document and to set min and max depth for TOC - @Pyreweb #189 +- Table: Ability to add footnote in table cell - @ivanlanin #187 +- Footnote: Ability to add image in footnote - @ivanlanin #187 +- ListItem: Ability to add list item in header/footer - @ivanlanin #187 +- CheckBox: Ability to add checkbox in header/footer - @ivanlanin #187 +- Link: Ability to add link in header/footer - @ivanlanin #187 +- Object: Ability to add object in header, footer, textrun, and footnote - @ivanlanin #187 +- Media: Add `Media::resetElements()` to reset all media data - @juzi #19 +- General: Add `Style::resetStyles()` - @ivanlanin #187 +- DOCX Reader: Ability to read header, footer, footnotes, link, preservetext, textbreak, pagebreak, table, list, image, and title - @ivanlanin +- Endnote: Ability to add endnotes - @ivanlanin +- ListItem: Ability to create custom list and reset list number - @ivanlanin #10, #198 +- ODT Writer: Basic table writing support - @ivanlanin +- Image: Keep image aspect ratio if only 1 dimension styled - @japonicus #194 +- HTML Writer: Basic HTML writer: text, textrun, link, title, textbreak, table, image (as Base64), footnote, endnote - @ivanlanin #203, #67, #147 +- PDF Writer: Basic PDF writer using DomPDF: All HTML element except image - @ivanlanin #68 +- DOCX Writer: Change `docProps/app.xml` `Application` to `PHPWord` - @ivanlanin +- DOCX Writer: Create `word/settings.xml` and `word/webSettings.xml` dynamically - @ivanlanin +- ODT Writer: Basic image writing - @ivanlanin +- ODT Writer: Link writing - @ivanlanin +- ODT Reader: Basic ODText Reader - @ivanlanin #71 +- Section: Ability to define gutter and line numbering - @ivanlanin +- Font: Small caps, all caps, and double strikethrough - @ivanlanin #151 +- Settings: Ability to use measurement unit other than twips with `setMeasurementUnit` - @ivanlanin #199 +- Style: Remove `bgColor` from `Font`, `Table`, and `Cell` and put it into the new `Shading` style - @ivanlanin +- Style: New `Indentation` and `Spacing` style - @ivanlanin +- Paragraph: Ability to define first line and right indentation - @ivanlanin + +### Bugfixes +- Footnote: Footnote content doesn't show footnote reference number - @ivanlanin #170 +- Documentation: Error in a function - @theBeerNut #195 + +### Deprecated +- `createTextRun` replaced by `addTextRun` +- `createFootnote` replaced by `addFootnote` +- `createHeader` replaced by `addHeader` +- `createFooter` replaced by `addFooter` +- `createSection` replaced by `addSection` +- `Element\Footnote::getReferenceId` replaced by `Element\AbstractElement::getRelationId` +- `Element\Footnote::setReferenceId` replaced by `Element\AbstractElement::setRelationId` +- `Footnote::addFootnoteLinkElement` replaced by `Media::addElement` +- `Footnote::getFootnoteLinkElements` replaced by `Media::getElements` +- All current methods on `Media` +- `Element\Link::getLinkSrc` replaced by `Element\Link::getTarget` +- `Element\Link::getLinkName` replaced by `Element\Link::getText` +- `Style\Cell::getDefaultBorderColor` + +### Miscellaneous +- Documentation: Simplify page level docblock - @ivanlanin #179 +- Writer: Refactor writer classes and create a new `Write\AbstractWriter` abstract class - @ivanlanin #160 +- General: Refactor folders: `Element` and `Exception` - @ivanlanin #187 +- General: Remove legacy `HashTable` and `Shared\ZipStreamWrapper` and all related properties/methods - @ivanlanin #187 +- Element: New `AbstractElement` abstract class - @ivanlanin #187 +- Media: Refactor media class to use one method for all docPart (section, header, footer, footnote) - @ivanlanin #187 +- General: Remove underscore prefix from all private properties name - @ivanlanin #187 +- General: Move Section `Settings` to `Style\Section` - @ivanlanin #187 +- General: Give `Abstract` prefix and `Interface` suffix for all abstract classes and interfaces as per [PHP-FIG recommendation](https://github.com/php-fig/fig-standards/blob/master/bylaws/002-psr-naming-conventions.md) - @ivanlanin #187 +- Style: New `Style\AbstractStyle` abstract class - @ivanlanin #187 +- Writer: New 'ODText\Base` class - @ivanlanin #187 +- General: Rename `Footnote` to `Footnotes` to reflect the nature of collection - @ivanlanin +- General: Add some unit tests for Shared & Element (100%!) - @Progi1984 +- Test: Add some samples and tests for image wrapping style - @brunocasado #59 +- Refactor: Remove Style\Tabs - @ivanlanin +- Refactor: Apply composite pattern for writers - @ivanlanin +- Refactor: Split `AbstractContainer` from `AbstractElement` - @ivanlanin +- Refactor: Apply composite pattern for Word2007 reader - @ivanlanin + + diff --git a/docs/changes/0.x/0.10.1.md b/docs/changes/0.x/0.10.1.md new file mode 100644 index 0000000000..3fd3f620c9 --- /dev/null +++ b/docs/changes/0.x/0.10.1.md @@ -0,0 +1,9 @@ + + +# 0.10.1 (21 May 2014) + +This is a bugfix release for `php-zip` requirement in Composer. + +- Change Composer requirements for php-zip from `require` to `suggest` - @bskrtich #246 + + diff --git a/docs/changes/0.x/0.11.0.md b/docs/changes/0.x/0.11.0.md new file mode 100644 index 0000000000..303b4fe66d --- /dev/null +++ b/docs/changes/0.x/0.11.0.md @@ -0,0 +1,62 @@ +# 0.11.0 (1 June 2014) + +This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3. Four new elements were added: TextBox, ListItemRun, Field, and Line. Relative and absolute positioning for images and textboxes were added. Writer classes were refactored into parts, elements, and styles. ODT and RTF features were enhanced. Ability to add elements to PHPWord object via HTML were implemented. RTF and HTML reader were initiated. + +### Features +- Image: Ability to define relative and absolute positioning - @basjan #217 +- Footer: Conform footer with header by adding firstPage, evenPage and by inheritance - @basjan @ivanlanin #219 +- Element: New `TextBox` element - @basjan @ivanlanin #228, #229, #231 +- HTML: Ability to add elements to PHPWord object via html - @basjan #231 +- Element: New `ListItemRun` element that can add a list item with inline formatting like a textrun - @basjan #235 +- Table: Ability to add table inside a cell (nested table) - @ivanlanin #149 +- RTF Writer: UTF8 support for RTF: Internal UTF8 text is converted to Unicode before writing - @ivanlanin #158 +- Table: Ability to define table width (in percent and twip) and position - @ivanlanin #237 +- RTF Writer: Ability to add links and page breaks in RTF - @ivanlanin #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 #200 +- ODT Writer: Enable inline font style in TextRun - @ivanlanin +- ODT Writer: Enable underline, strike/doublestrike, smallcaps/allcaps, superscript/subscript font style - @ivanlanin +- ODT Writer: Enable section and column - @ivanlanin +- PDF Writer: Add TCPDF and mPDF as optional PDF renderer library - @ivanlanin +- ODT Writer: Enable title element and custom document properties - @ivanlanin +- ODT Reader: Ability to read standard and custom document properties - @ivanlanin +- Word2007 Writer: Enable the missing custom document properties writer - @ivanlanin +- Image: Enable "image float left" - @ivanlanin #244 +- RTF Writer: Ability to write document properties - @ivanlanin +- RTF Writer: Ability to write image - @ivanlanin +- Element: New `Field` element - @basjan #251 +- RTF Reader: Basic RTF reader - @ivanlanin #72, #252 +- Element: New `Line` element - @basjan #253 +- Title: Ability to apply numbering in heading - @ivanlanin #193 +- HTML Reader: Basic HTML reader - @ivanlanin #80, #254 +- RTF Writer: Basic table writing - @ivanlanin #245 + +### Bugfixes +- Header: All images added to the second header were assigned to the first header - @basjan #222 +- Conversion: Fix conversion from cm to pixel, pixel to cm, and pixel to point - @basjan #233, #234 +- PageBreak: Page break adds new line in the beginning of the new page - @ivanlanin #150 +- Image: `marginLeft` and `marginTop` cannot accept float value - @ivanlanin #248 +- Title: Orphan `w:fldChar` caused OpenOffice to crash when opening DOCX - @ivanlanin #236 + +### Deprecated +- Static classes `Footnotes`, `Endnotes`, and `TOC` +- `Writer\Word2007\Part`: `Numbering::writeNumbering()`, `Settings::writeSettings()`, `WebSettings::writeWebSettings()`, `ContentTypes::writeContentTypes()`, `Styles::writeStyles()`, `Document::writeDocument()` all changed into `write()` +- `Writer\Word2007\Part\DocProps`: Split into `Writer\Word2007\Part\DocPropsCore` and `Writer\Word2007\Part\DocPropsApp` +- `Element\Title::getBookmarkId()` replaced by `Element\Title::getRelationId()` +- `Writer\HTML::writeDocument`: Replaced by `Writer\HTML::getContent` + +### Miscellaneous +- License: Change the project license from LGPL 2.1 into LGPL 3.0 - #211 +- Word2007 Writer: New `Style\Image` class - @ivanlanin +- Refactor: Replace static classes `Footnotes`, `Endnotes`, and `TOC` with `Collections` - @ivanlanin #206 +- QA: Reactivate `phpcpd` and `phpmd` on Travis - @ivanlanin +- Refactor: PHPMD recommendation: Change all `get...` method that returns `boolean` into `is...` or `has...` - @ivanlanin +- Docs: Create gh-pages branch for API documentation - @Progi1984 #154 +- QA: Add `.scrutinizer.yml` and include `composer.lock` for preparation to Scrutinizer - @ivanlanin #186 +- Writer: Refactor writer parts using composite pattern - @ivanlanin +- Docs: Show code quality and test code coverage badge on README +- Style: Change behaviour of `set...` function of boolean properties; when none is defined, assumed true - @ivanlanin +- Shared: Unify PHP ZipArchive and PCLZip features into PhpWord ZipArchive - @ivanlanin +- Docs: Create VERSION file - @ivanlanin +- QA: Improve dan update requirement check in `samples` folder - @ivanlanin + diff --git a/docs/changes/0.x/0.11.1.md b/docs/changes/0.x/0.11.1.md new file mode 100644 index 0000000000..19be54c67c --- /dev/null +++ b/docs/changes/0.x/0.11.1.md @@ -0,0 +1,5 @@ +# 0.11.1 (2 June 2014) + +This is an immediate bugfix release for HTML reader. + +- HTML Reader: `

    ` and header tags puts no output - @canyildiz @ivanlanin #257 diff --git a/docs/changes/0.x/0.12.0.md b/docs/changes/0.x/0.12.0.md new file mode 100644 index 0000000000..28a1c3ec2f --- /dev/null +++ b/docs/changes/0.x/0.12.0.md @@ -0,0 +1,60 @@ +# 0.12.0 (3 January 2015) + +This release added form fields (textinput, checkbox, and dropdown), drawing shapes (arc, curve, line, polyline, rect, oval), and basic 2D chart (pie, doughnut, bar, line, area, scatter, radar) elements along with some new styles. Basic MsDoc reader is introduced. + +### Features +- Element: Ability to add drawing shapes (arc, curve, line, polyline, rect, oval) using new `Shape` element - @ivanlanin #123 +- Font: New `scale`, `spacing`, and `kerning` property of font style - @ivanlanin +- Paragraph: Added shading to the paragraph style for full width shading - @lrobert #264 +- RTF Writer: Support for sections, margins, and borders - @ivanlanin #249 +- Section: Ability to set paper size, e.g. A4, A3, and Legal - @ivanlanin #249 +- General: New `PhpWord::save()` method to encapsulate `IOFactory` - @ivanlanin +- General: New `Shared\Converter` static class - @ivanlanin +- Chart: Basic 2D chart (pie, doughnut, bar, line, area, scatter, radar) - @ivanlanin #278 +- Chart: 3D charts and ability to set width and height - @ivanlanin +- FormField: Ability to add textinput, checkbox, and dropdown form elements - @ivanlanin #266 +- Setting: Ability to define document protection (readOnly, comments, trackedChanges, forms) - @ivanlanin +- Setting: Ability to remove [Compatibility Mode] text in the MS Word title bar - @ivanlanin +- SDT: Ability to add structured document tag elements (comboBox, dropDownList, date) - @ivanlanin +- Paragraph: Support for paragraph with borders - @ivanlanin #294 +- Word2007 Writer : Support for RTL - @Progi1984 #331 +- MsDOC Reader: Basic MsDOC Reader - @Progi1984 #23, #287 +- "absolute" horizontal and vertical positioning of Frame - @basjan #302 +- Add new-page function for PDF generation. For multiple PDF-backends - @chc88 #426 +- Report style options enumerated when style unknown - @h6w + +### Bugfixes +- Fix rare PclZip/realpath/PHP version problem - @andrew-kzoo #261 +- `addHTML` encoding and ampersand fixes for PHP 5.3 - @bskrtich #270 +- Page breaks on titles and tables - @ivanlanin #274 +- Table inside vertical border does not rendered properly - @ivanlanin #280 +- `add` of container should be case insensitive, e.g. `addToc` should be accepted, not only `addTOC` - @ivanlanin #294 +- Fix specific borders (and margins) were not written correctly in word2007 writer - @pscheit #327 +- "HTML is not a valid writer" exception while running "Sample_36_RTL.php" - @RomanSyroeshko #340 +- "addShape()" magic method in AbstractContainer is mistakenly named as "addObject()" - @GMTA #356 +- `Element\Section::setPageSizeW()` and `Element\Section::setPageSizeH()` were mentioned in the docs but not implemented. +- Special Characters (ampersand) in Title break docx output - @RomanSyroeshko #401 +- `` tag is closed with `` tag: - @franzholz #438 + +### Deprecated +- `Element\Link::getTarget()` replaced by `Element\Link::getSource()` +- `Element\Section::getSettings()` and `Element\Section::setSettings()` replaced by `Element\Section::getStyle()` and `Element\Section::setStyle()` +- `Shared\Drawing` and `Shared\Font` merged into `Shared\Converter` +- `DocumentProperties` replaced by `Metadata\DocInfo` +- `Template` replaced by `TemplateProcessor` +- `PhpWord->loadTemplate($filename)` + +### Miscellaneous +- Docs: Add known issue on `README` about requirement for temporary folder to be writable and update `samples/index.php` for this requirement check - @ivanlanin #238 +- Docs: Correct elements.rst about Line - @chrissharkman #292 +- PclZip: Remove temporary file after used - @andrew-kzoo #265 +- Autoloader: Add the ability to set the autoloader options - @bskrtich #267 +- Element: Refactor elements to move set relation Id from container to element - @ivanlanin +- Introduced CreateTemporaryFileException, CopyFileException - @RomanSyroeshko +- Settings: added method to set user defined temporary directory - @RomanSyroeshko #310 +- Renamed `Template` into `TemplateProcessor` - @RomanSyroeshko #216 +- Reverted #51. All text escaping must be performed out of the library - @RomanSyroeshko #51 + + + +v \ No newline at end of file diff --git a/docs/changes/0.x/0.12.1.md b/docs/changes/0.x/0.12.1.md new file mode 100644 index 0000000000..db133ac462 --- /dev/null +++ b/docs/changes/0.x/0.12.1.md @@ -0,0 +1,11 @@ +# 0.12.1 (30 August 2015) + +Maintenance release. This release is focused primarily on `TemplateProcessor`. + +### Changes +- Changed visibility of all private properties and methods of `TemplateProcessor` to `protected`. - @RomanSyroeshko #498 +- Improved performance of `TemplateProcessor::setValue()`. - @RomanSyroeshko @nicoSWD #513 + +### Bugfixes +- Fixed issue with "Access denied" message while opening `Sample_07_TemplateCloneRow.docx` and `Sample_23_TemplateBlock.docx` result files on Windows platform. - @RomanSyroeshko @AshSat #532 +- Fixed `PreserveText` element alignment in footer (see `Sample_12_HeaderFooter.php`). - @RomanSyroeshko @SSchwaiger #495 diff --git a/docs/changes/0.x/0.13.0.md b/docs/changes/0.x/0.13.0.md new file mode 100644 index 0000000000..ece6d18990 --- /dev/null +++ b/docs/changes/0.x/0.13.0.md @@ -0,0 +1,47 @@ +# 0.13.0 (31 July 2016) + +This release brings several improvements in `TemplateProcessor`, automatic output escaping feature for OOXML, ODF, HTML, and RTF (turned off, by default). +It also introduces constants for horizontal alignment options, and resolves some issues with PHP 7. +Manual installation feature has been dropped since the release. Please, use [Composer](https://getcomposer.org/) to install PHPWord. + +### Added +- Introduced the `\PhpOffice\PhpWord\SimpleType\Jc` simple type. - @RomanSyroeshko +- Introduced the `\PhpOffice\PhpWord\SimpleType\JcTable` simple type. - @RomanSyroeshko +- Introduced writer for the "Paragraph Alignment" element (see `\PhpOffice\PhpWord\Writer\Word2007\Element\ParagraphAlignment`). - @RomanSyroeshko +- Introduced writer for the "Table Alignment" element (see `\PhpOffice\PhpWord\Writer\Word2007\Element\TableAlignment`). - @RomanSyroeshko +- Supported indexed arrays in arguments of `TemplateProcessor::setValue()`. - @RomanSyroeshko #618 +- Introduced automatic output escaping for OOXML, ODF, HTML, and RTF. To turn the feature on use `phpword.ini` or `\PhpOffice\PhpWord\Settings`. - @RomanSyroeshko #483 +- Supported processing of headers and footers in `TemplateProcessor::applyXslStyleSheet()`. - @RomanSyroeshko #335 + +### Changed +- Improved error message for the case when `autoload.php` is not found. - @RomanSyroeshko #371 +- Renamed the `align` option of `NumberingLevel`, `Frame`, `Table`, and `Paragraph` styles into `alignment`. - @RomanSyroeshko +- Improved performance of `TemplateProcessor::setValue()`. - @kazitanvirahsan #614, #617 +- Fixed some HTML tags not rendering any output (p, header & table) - #257, #324 - @twmobius and @garethellis + +### Deprecated +- `getAlign` and `setAlign` methods of `NumberingLevel`, `Frame`, `Table`, and `Paragraph` styles. +Use the correspondent `getAlignment` and `setAlignment` methods instead. - @RomanSyroeshko +- `left`, `right`, and `justify` alignment options for paragraphs (now are mapped to `Jc::START`, `Jc::END`, and `Jc::BOTH`). - @RomanSyroeshko +- `left`, `right`, and `justify` alignment options for tables (now are mapped to `Jc::START`, `Jc::END`, and `Jc::CENTER`). - @RomanSyroeshko +- `TCPDF` due to its limited HTML support. Use `DomPDF` or `MPDF` writer instead. - @RomanSyroeshko #399 + +### Removed +- `\PhpOffice\PhpWord\Style\Alignment`. Style properties, which previously stored instances of this class, now deal with strings. +In each case set of available string values is defined by the correspondent simple type. - @RomanSyroeshko +- Manual installation support. Since the release we have dependencies on third party libraries, +so installation via ZIP-archive download is not an option anymore. To install PHPWord use [Composer](https://getcomposer.org/). + We also removed `\PhpOffice\PhpWord\Autoloader`, because the latter change made it completely useless. + Autoloaders provided by Composer are in use now (see `bootstrap.php`). - @RomanSyroeshko +- `\PhpOffice\PhpWord\Shared\Drawing` replaced by `\PhpOffice\Common\Drawing`. - @Progi1984 #658 +- `\PhpOffice\PhpWord\Shared\Font`. - @Progi1984 #658 +- `\PhpOffice\PhpWord\Shared\String` replaced by `\PhpOffice\Common\Text`. - @Progi1984 @RomanSyroeshko #658 +- `\PhpOffice\PhpWord\Shared\XMLReader` replaced by `\PhpOffice\Common\XMLReader`. - @Progi1984 #658 +- `\PhpOffice\PhpWord\Shared\XMLWriter` replaced by `\PhpOffice\Common\XMLWriter`. - @Progi1984 @RomanSyroeshko #658 +- `AbstractContainer::addMemoryImage()`. Use `AbstractContainer::addImage()` instead. + +### Fixed +- `Undefined property` error while reading MS-DOC documents. - @jaberu #610 +- Corrupted OOXML template issue in case when its names is broken immediately after `$` sign. +That case wasn't taken into account in implementation of `TemplateProcessor::fixBrokenMacros()`. - @RomanSyroeshko @d-damien #548 + diff --git a/docs/changes/0.x/0.14.0.md b/docs/changes/0.x/0.14.0.md new file mode 100644 index 0000000000..c6a71267d5 --- /dev/null +++ b/docs/changes/0.x/0.14.0.md @@ -0,0 +1,47 @@ +# 0.14.0 (29 Dec 2017) + +This release fixes several bugs and adds some new features. +This version brings compatibility with PHP 7.0 & 7.1 + +### Added +- Possibility to control the footnote numbering -by [@troosan](https://github.com/troosan) in [#1068](https://github.com/PHPOffice/PHPWord/pull/1068) +- Image creation from string -by [@troosan](https://github.com/troosan) in [#937](https://github.com/PHPOffice/PHPWord/pull/937) +- Introduced the `\PhpOffice\PhpWord\SimpleType\NumberFormat` simple type. - @troosan +- Support for ContextualSpacing -by [@postHawk](https://github.com/postHawk) in [#1088](https://github.com/PHPOffice/PHPWord/pull/1088) +- Possiblity to hide spelling and/or grammatical errors -by [@troosan](https://github.com/troosan) in [#542](https://github.com/PHPOffice/PHPWord/pull/542) +- Possiblity to set default document language as well as changing the language for each text element -by [@troosan](https://github.com/troosan) in [#1108](https://github.com/PHPOffice/PHPWord/pull/1108) +- Support for Comments -by [@troosan](https://github.com/troosan) in [#1067](https://github.com/PHPOffice/PHPWord/pull/1067) +- Support for paragraph textAlignment -by [@troosan](https://github.com/troosan) in [#1165](https://github.com/PHPOffice/PHPWord/pull/1165) +- Add support for HTML underline tag `` in addHtml -by [@zNightFalLz](https://github.com/zNightFalLz) in [#1186](https://github.com/PHPOffice/PHPWord/pull/1186) +- Add support for HTML `
    ` in addHtml - @anrikunby [@troosan](https://github.com/troosan) in [#659](https://github.com/PHPOffice/PHPWord/pull/659) +- Allow to change cell width unit - guillaume-ro-fr #986 +- Allow to change the line height rule @troosan +- Implement PageBreak for odt writerby [@cookiekiller](https://github.com/cookiekiller) in [#863](https://github.com/PHPOffice/PHPWord/pull/863) #824 +- Allow to force an update of all fields on opening a document -by [@troosan](https://github.com/troosan) in [#951](https://github.com/PHPOffice/PHPWord/pull/951) +- Allow adding a CheckBox in a TextRun -by [@irond](https://github.com/irond) in [#727](https://github.com/PHPOffice/PHPWord/pull/727) +- Add support for HTML img tag -by [@srggroup](https://github.com/srggroup) in [#934](https://github.com/PHPOffice/PHPWord/pull/934) +- Add support for password protection for docx -by [@mariahaubner](https://github.com/mariahaubner) in [#1019](https://github.com/PHPOffice/PHPWord/pull/1019) + +### Fixed +- Loosen dependency to Zend +- Images are not being printed when generating PDF -by [@hubertinio](https://github.com/hubertinio) in [#1074](https://github.com/PHPOffice/PHPWord/pull/1074) #431 +- Fixed some PHP 7 warnings - @ likeuntomurphy #927 +- Fixed PHP 7.2 compatibility (renamed `Object` class names to `ObjectElement`) -by [@SailorMax](https://github.com/SailorMax) in [#1185](https://github.com/PHPOffice/PHPWord/pull/1185) +- Fixed Word 97 reader - @alsofronie @Benpxpxby [@mario-rivera](https://github.com/mario-rivera) in [#912](https://github.com/PHPOffice/PHPWord/pull/912) #920 #892 +- Fixed image loading over https -by [@troosan](https://github.com/troosan) in [#988](https://github.com/PHPOffice/PHPWord/pull/988) +- Impossibility to set different even and odd page headers -by [@troosan](https://github.com/troosan) in [#981](https://github.com/PHPOffice/PHPWord/pull/981) +- Fixed Word2007 reader where unnecessary paragraphs were being created -by [@donghaobo](https://github.com/donghaobo) in [#1043](https://github.com/PHPOffice/PHPWord/pull/1043) #620 +- Fixed Word2007 reader where margins were not being read correctly -by [@slowprog](https://github.com/slowprog) in [#885](https://github.com/PHPOffice/PHPWord/pull/885) #1008 +- Impossible to add element PreserveText in Section -by [@rvanlaak](https://github.com/rvanlaak) in [#452](https://github.com/PHPOffice/PHPWord/pull/452) +- Added missing options for numbering format -by [@troosan](https://github.com/troosan) in [#1041](https://github.com/PHPOffice/PHPWord/pull/1041) +- Fixed impossibility to set a different footer for first page -by [@ctrlaltca](https://github.com/ctrlaltca) in [#1116](https://github.com/PHPOffice/PHPWord/pull/1116),by [@aoloe](https://github.com/aoloe) in [#875](https://github.com/PHPOffice/PHPWord/pull/875) +- Fixed styles not being applied by HTML writer, better pdf output -by [@sarke](https://github.com/sarke) in [#1047](https://github.com/PHPOffice/PHPWord/pull/1047) #500 #1139 +- Fixed read docx error when document contains image from remote url -by [@FBnil](https://github.com/FBnil) in [#1173](https://github.com/PHPOffice/PHPWord/pull/1173) #1176 +- Padded the $args array to remove error -by [@kaigoh](https://github.com/kaigoh) in [#1150](https://github.com/PHPOffice/PHPWord/pull/1150),by [@reformed](https://github.com/reformed) in [#870](https://github.com/PHPOffice/PHPWord/pull/870) +- Fix incorrect image size between windows and mac -by [@bskrtich](https://github.com/bskrtich) in [#874](https://github.com/PHPOffice/PHPWord/pull/874) +- Fix adding HTML table to document - @mogilvieby [@arivanbastos](https://github.com/arivanbastos) in [#324](https://github.com/PHPOffice/PHPWord/pull/324) +- Fix parsing on/off values (w:val="true|false|1|0|on|off") -by [@troosan](https://github.com/troosan) in [#1221](https://github.com/PHPOffice/PHPWord/pull/1221) #1219 +- Fix error on Empty Dropdown Entry -by [@ComputerTinker](https://github.com/ComputerTinker) in [#592](https://github.com/PHPOffice/PHPWord/pull/592) + +### Deprecated +- PhpWord->getProtection(), get it from the settings instead PhpWord->getSettings()->getDocumentProtection(); diff --git a/docs/changes/0.x/0.15.0.md b/docs/changes/0.x/0.15.0.md new file mode 100644 index 0000000000..4fa0b8811d --- /dev/null +++ b/docs/changes/0.x/0.15.0.md @@ -0,0 +1,45 @@ +# 0.15.0 (14 Jul 2018) + +### Added +- Parsing of `align` HTML attribute -by [@troosan](https://github.com/troosan) in [#1231](https://github.com/PHPOffice/PHPWord/pull/1231) +- Parse formatting inside HTML lists - @troosanby [@samimussbach](https://github.com/samimussbach) in [#1239](https://github.com/PHPOffice/PHPWord/pull/1239) / [#945](https://github.com/PHPOffice/PHPWord/pull/945) / [#1215](https://github.com/PHPOffice/PHPWord/pull/1215) / [#508](https://github.com/PHPOffice/PHPWord/pull/508) +- Parsing of CSS `direction` instruction, HTML `lang` attribute, formatting inside table cell -by [@troosan](https://github.com/troosan) in [#1273](https://github.com/PHPOffice/PHPWord/pull/1273) / [#1252](https://github.com/PHPOffice/PHPWord/pull/1252) / [#1254](https://github.com/PHPOffice/PHPWord/pull/1254) +- Add support for Track changes @Cipby [@troosan](https://github.com/troosan) in [#354](https://github.com/PHPOffice/PHPWord/pull/354) / [#1262](https://github.com/PHPOffice/PHPWord/pull/1262) +- Add support for fixed Table Layout @aoloe @ekopachby [@troosan](https://github.com/troosan) in [#841](https://github.com/PHPOffice/PHPWord/pull/841) / [#1276](https://github.com/PHPOffice/PHPWord/pull/1276) +- Add support for Cell Spacing @dox07by [@troosan](https://github.com/troosan) in [#1040](https://github.com/PHPOffice/PHPWord/pull/1040) +- Add parsing of formatting inside lists @atomicalnetby [@troosan](https://github.com/troosan) in [#594](https://github.com/PHPOffice/PHPWord/pull/594) +- Added support for Vertically Raised or Lowered Text (w:position) @anrikunby [@troosan](https://github.com/troosan) in [#640](https://github.com/PHPOffice/PHPWord/pull/640) +- Add support for MACROBUTTON field @phryneasby [@troosan](https://github.com/troosan) in [#1021](https://github.com/PHPOffice/PHPWord/pull/1021) +- Add support for Hyphenationby [@Trainmaster](https://github.com/Trainmaster) in [#1282](https://github.com/PHPOffice/PHPWord/pull/1282) (Document: `autoHyphenation`, `consecutiveHyphenLimit`, `hyphenationZone`, `doNotHyphenateCaps`, Paragraph: `suppressAutoHyphens`) +- Added support for Floating Table Positioning (tblpPr)by [@anrikun](https://github.com/anrikun) in [#639](https://github.com/PHPOffice/PHPWord/pull/639) +- Added support for Image text wrapping distanceby [@troosan](https://github.com/troosan) in [#1310](https://github.com/PHPOffice/PHPWord/pull/1310) +- Added parsing of CSS line-height and text-indent in HTML readerby [@troosan](https://github.com/troosan) in [#1316](https://github.com/PHPOffice/PHPWord/pull/1316) +- Added the ability to enable gridlines and axislabels on chartsby [@FrankMeyer](https://github.com/FrankMeyer) in [#576](https://github.com/PHPOffice/PHPWord/pull/576) +- Add support for table indent (tblInd)by [@Trainmaster](https://github.com/Trainmaster) in [#1343](https://github.com/PHPOffice/PHPWord/pull/1343) +- Added parsing of internal links in HTML readerby [@lalop](https://github.com/lalop) in [#1336](https://github.com/PHPOffice/PHPWord/pull/1336) +- Several improvements to chartsby [@JAEK-S](https://github.com/JAEK-S) in [#1332](https://github.com/PHPOffice/PHPWord/pull/1332) +- Add parsing of html image in base64 formatby [@jgpATs2w](https://github.com/jgpATs2w) in [#1382](https://github.com/PHPOffice/PHPWord/pull/1382) +- Added Support for Indentation & Tabs on RTF Writer.by [@smaug1985](https://github.com/smaug1985) in [#1405](https://github.com/PHPOffice/PHPWord/pull/1405) +- Allows decimal numbers in HTML line-height styleby [@jgpATs2w](https://github.com/jgpATs2w) in [#1413](https://github.com/PHPOffice/PHPWord/pull/1413) + +### Fixed +- Fix reading of docx default style -by [@troosan](https://github.com/troosan) in [#1238](https://github.com/PHPOffice/PHPWord/pull/1238) +- Fix the size unit of when parsing html images -by [@troosan](https://github.com/troosan) in [#1254](https://github.com/PHPOffice/PHPWord/pull/1254) +- Fixed HTML parsing of nested lists -by [@troosan](https://github.com/troosan) in [#1265](https://github.com/PHPOffice/PHPWord/pull/1265) +- Save PNG alpha information when using remote images.by [@samsullivan](https://github.com/samsullivan) in [#779](https://github.com/PHPOffice/PHPWord/pull/779) +- Fix parsing of `` tag.by [@troosan](https://github.com/troosan) in [#1274](https://github.com/PHPOffice/PHPWord/pull/1274) +- Bookmark are not writton as internal link in html writerby [@troosan](https://github.com/troosan) in [#1263](https://github.com/PHPOffice/PHPWord/pull/1263) +- It should be possible to add a Footnote in a ListItemRunby [@troosan](https://github.com/troosan) in [#1287](https://github.com/PHPOffice/PHPWord/pull/1287) #1287 +- Fix colspan and rowspan for tables in HTML Writerby [@mattbolt](https://github.com/mattbolt) in [#1292](https://github.com/PHPOffice/PHPWord/pull/1292) +- Fix parsing of Heading and Title formating @troosanby [@gthomas2](https://github.com/gthomas2) in [#465](https://github.com/PHPOffice/PHPWord/pull/465) +- Fix Dateformat typo, fix hours casing, add Month-Day-Year formatsby [@ComputerTinker](https://github.com/ComputerTinker) in [#591](https://github.com/PHPOffice/PHPWord/pull/591) +- Support reading of w:drawing for documents produced by word 2011+by [@gthomas2](https://github.com/gthomas2) in [#464](https://github.com/PHPOffice/PHPWord/pull/464) #1324 +- Fix missing column width in ODText writerby [@potofcoffee](https://github.com/potofcoffee) in [#413](https://github.com/PHPOffice/PHPWord/pull/413) +- Disable entity loader before parsing XML to avoid XXE injectionby [@Tom4t0](https://github.com/Tom4t0) in [#1427](https://github.com/PHPOffice/PHPWord/pull/1427) + +### Changed +- Remove zend-stdlib dependencyby [@Trainmaster](https://github.com/Trainmaster) in [#1284](https://github.com/PHPOffice/PHPWord/pull/1284) +- The default unit for `\PhpOffice\PhpWord\Style\Image` changed from `px` to `pt`. + +### Miscellaneous +- Drop GitHub pages, switch to coveralls for code coverage analysisby [@czosel](https://github.com/czosel) in [#1360](https://github.com/PHPOffice/PHPWord/pull/1360) diff --git a/docs/changes/0.x/0.16.0.md b/docs/changes/0.x/0.16.0.md new file mode 100644 index 0000000000..3eccc34d03 --- /dev/null +++ b/docs/changes/0.x/0.16.0.md @@ -0,0 +1,27 @@ +# 0.16.0 (30 dec 2018) + +### Added +- Add getVariableCount method in TemplateProcessor.by [@nicoder](https://github.com/nicoder) in [#1272](https://github.com/PHPOffice/PHPWord/pull/1272) +- Add setting Chart Title and Legend visibilityby [@Tom-Magill](https://github.com/Tom-Magill) in [#1433](https://github.com/PHPOffice/PHPWord/pull/1433) +- Add ability to pass a Style object in Section constructorby [@ndench](https://github.com/ndench) in [#1416](https://github.com/PHPOffice/PHPWord/pull/1416) +- Add support for hidden textby [@Alexmg86](https://github.com/Alexmg86) in [#1527](https://github.com/PHPOffice/PHPWord/pull/1527) +- Add support for setting images in TemplateProcessorby [@SailorMax](https://github.com/SailorMax) in [#1170](https://github.com/PHPOffice/PHPWord/pull/1170) +- Add "Plain Text" type to SDT (Structured Document Tags)by [@morrisdj](https://github.com/morrisdj) in [#1541](https://github.com/PHPOffice/PHPWord/pull/1541) +- Added possibility to index variables inside cloned block in TemplateProcessorby [@JPBetley](https://github.com/JPBetley) in [#817](https://github.com/PHPOffice/PHPWord/pull/817) +- Added possibility to replace variables inside cloned block with values in TemplateProcessorby [@DIDoS](https://github.com/DIDoS) in [#1392](https://github.com/PHPOffice/PHPWord/pull/1392) + +### Fixed +- Fix regex in `cloneBlock` functionby [@nicoder](https://github.com/nicoder) in [#1269](https://github.com/PHPOffice/PHPWord/pull/1269) +- HTML Title Writer loses text when Title contains a TextRun instead a string.by [@begnini](https://github.com/begnini) in [#1436](https://github.com/PHPOffice/PHPWord/pull/1436) +- Fix regex in fixBrokenMacros, make it less greedy @MuriloSo @brainwoodby [@yurii-sio2](https://github.com/yurii-sio2) in [#1502](https://github.com/PHPOffice/PHPWord/pull/1502) / [#1345](https://github.com/PHPOffice/PHPWord/pull/1345) +- 240 twips are being added to line spacing, should not happen when using lineRule fixedby [@troosan](https://github.com/troosan) in [#1509](https://github.com/PHPOffice/PHPWord/pull/1509) / [#1505](https://github.com/PHPOffice/PHPWord/pull/1505) +- Adding table layout to the generated HTMLby [@aarangara](https://github.com/aarangara) in [#1441](https://github.com/PHPOffice/PHPWord/pull/1441) +- Fix loading of Sharepoint documentby [@Garrcomm](https://github.com/Garrcomm) in [#1498](https://github.com/PHPOffice/PHPWord/pull/1498) +- RTF writer: Round getPageSizeW and getPageSizeH to avoid decimalsby [@Patrick64](https://github.com/Patrick64) in [#1493](https://github.com/PHPOffice/PHPWord/pull/1493) +- Fix parsing of Office 365 documentsby [@Timanx](https://github.com/Timanx) in [#1485](https://github.com/PHPOffice/PHPWord/pull/1485) +- For RTF writers, sizes should should never have decimalsby [@Samuel-BF](https://github.com/Samuel-BF) in [#1536](https://github.com/PHPOffice/PHPWord/pull/1536) +- Style Name Parsing fails if document generated by a non-english word versionby [@begnini](https://github.com/begnini) in [#1434](https://github.com/PHPOffice/PHPWord/pull/1434) + +### Miscellaneous +- Get rid of duplicated code in TemplateProcessorby [@abcdmitry](https://github.com/abcdmitry) in [#1161](https://github.com/PHPOffice/PHPWord/pull/1161) + diff --git a/docs/changes/0.x/0.17.0.md b/docs/changes/0.x/0.17.0.md new file mode 100644 index 0000000000..ffd2d91dd4 --- /dev/null +++ b/docs/changes/0.x/0.17.0.md @@ -0,0 +1,27 @@ +# 0.17.0 (01 oct 2019) + +### Added +- Add methods setValuesFromArray and cloneRowFromArray to the TemplateProcessor [@geraldb-nicat](https://github.com/geraldb-nicat) GH-670 +- Set complex type in template [@troosan](https://github.com/troosan) GH-1565 +- implement support for section vAlign [@troosan](https://github.com/troosan) GH-1569 +- ParseStyle for border-color [@Gllrm0](https://github.com/Gllrm0) GH-1551 +- Html writer auto invert text color [@SailorMax](https://github.com/SailorMax) GH-1387 +- Add RightToLeft table presentation. [@troosan](https://github.com/troosan) GH-1550 +- Add support for page vertical alignment. [@troosan](https://github.com/troosan) GH-672 GH-1569 +- Adding setNumId method for ListItem style [@eweso](https://github.com/eweso) GH-1329 +- Add support for basic fields in RTF writer. [@Samuel-BF](https://github.com/Samuel-BF) GH-1717 + +### Fixed +- Fix HTML border-color parsing. [@troosan](https://github.com/troosan) GH-1551 / GH-1570 +- Language::validateLocale should pass with locale 'zxx'. [@efpapado](https://github.com/efpapado) GH-1558 +- can't align center vertically with the text [@ter987](https://github.com/ter987) GH-672 +- fix parsing of border-color and add test [@troosan](https://github.com/troosan) GH-1570 +- TrackChange doesn't handle all return types of \DateTime::createFromFormat(...) [@superhaggis](https://github.com/superhaggis) GH-1584 +- To support PreserveText inside sub container [@bhattnishant](https://github.com/bhattnishant) GH-1637 +- No nested w:pPr elements in ListItemRun. [@waltertamboer](https://github.com/waltertamboer) GH-1628 +- Ensure that entity_loader disable variable is re-set back to the original setting [@seamuslee001](https://github.com/seamuslee001) GH-1585 + +### Miscellaneous +- Use embedded http server to test loading of remote images [@troosan](https://github.com/troosan) GH-1544 +- Change private to protected to be able extending class Html [@SpinyMan](https://github.com/SpinyMan) GH-1646 +- Fix apt-get crash in Travis CI for PHP 5.3 [@mdupont](https://github.com/mdupont) GH-1707 \ No newline at end of file diff --git a/docs/changes/0.x/0.18.0.md b/docs/changes/0.x/0.18.0.md new file mode 100644 index 0000000000..5f9d6a4d2f --- /dev/null +++ b/docs/changes/0.x/0.18.0.md @@ -0,0 +1,47 @@ +# [0.18.0](https://github.com/PHPOffice/PHPWord/tree/0.18.0) (2021-02-12) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.17.0...0.18.0) + +### Enhancements +- Add support for charts in template processor [#2012](https://github.com/PHPOffice/PHPWord/pull/2012) ([@dbarzin](https://github.com/dbarzin)) +- add/setting page element border style. [#1986](https://github.com/PHPOffice/PHPWord/pull/1986) ([@emnabs](https://github.com/emnabs)) +- allow to use customized pdf library [#1983](https://github.com/PHPOffice/PHPWord/pull/1983) ([@SailorMax](https://github.com/SailorMax)) +- feat: Update addHtml to handle style inheritance [#1965](https://github.com/PHPOffice/PHPWord/pull/1965) ([@Julien1138](https://github.com/Julien1138)) +- Add parsing of Shape node values [#1924](https://github.com/PHPOffice/PHPWord/pull/1924) ([@sven-ahrens](https://github.com/sven-ahrens)) +- Allow to redefine TCPDF object [#1907](https://github.com/PHPOffice/PHPWord/pull/1907) ([@SailorMax](https://github.com/SailorMax)) +- Enhancements to addHTML parser [#1902](https://github.com/PHPOffice/PHPWord/pull/1902) ([@lubosdz](https://github.com/lubosdz)) +- Make Default Paper Configurable [#1851](https://github.com/PHPOffice/PHPWord/pull/1851) ([@oleibman](https://github.com/oleibman)) +- Implement various missing features for the ODT writer [#1796](https://github.com/PHPOffice/PHPWord/pull/1796) ([@oleibman](https://github.com/oleibman)) +- Added support for "cloudConvert" images [#1794](https://github.com/PHPOffice/PHPWord/pull/1794) ([@ErnestStaug](https://github.com/ErnestStaug)) +- Add support for several features for the RTF writer [#1775](https://github.com/PHPOffice/PHPWord/pull/1775) ([@oleibman](https://github.com/oleibman)) +- Add font style for Field elements [#1774](https://github.com/PHPOffice/PHPWord/pull/1774) ([@oleibman](https://github.com/oleibman)) +- Add support for ListItemRun in HTML writer [#1766](https://github.com/PHPOffice/PHPWord/pull/1766) ([@stefan-91](https://github.com/stefan-91)) +- Improvements in RTF writer [#1755](https://github.com/PHPOffice/PHPWord/pull/1755) ([@oleibman](https://github.com/oleibman)) +- Allow a closure to be passed with image replacement tags [#1716](https://github.com/PHPOffice/PHPWord/pull/1716) ([@mbardelmeijer](https://github.com/mbardelmeijer)) +- Add Option for Dynamic Chart Legend Position [#1699](https://github.com/PHPOffice/PHPWord/pull/1699) ([@Stephan212](https://github.com/Stephan212)) +- Add parsing of HTML checkbox input field [#1832](https://github.com/PHPOffice/PHPWord/pull/1832) ([@Matze2010](https://github.com/Matze2010)) + +### Bug fixes +- Fix image stroke in libreoffice 7.x [#1992](https://github.com/PHPOffice/PHPWord/pull/1992) ([@Adizbek](https://github.com/Adizbek)) +- Fix deprecated warning for non-hexadecimal number [#1988](https://github.com/PHPOffice/PHPWord/pull/1988) ([@Ciki](https://github.com/Ciki)) +- Fix limit not taken into account when adding image in template [#1967](https://github.com/PHPOffice/PHPWord/pull/1967) ([@jsochor](https://github.com/jsochor)) +- Add null check when setComplexValue is not found [#1936](https://github.com/PHPOffice/PHPWord/pull/1936) ([@YannikFirre](https://github.com/YannikFirre)) +- Some document have non-standard locale code [#1824](https://github.com/PHPOffice/PHPWord/pull/1824) ([@ErnestStaug](https://github.com/ErnestStaug)) +- Fixes PHPDoc @param and @return types for several Converter methods [#1818](https://github.com/PHPOffice/PHPWord/pull/1818) ([@caugner](https://github.com/caugner)) +- Update the regexp to avoid catastrophic backtracking [#1809](https://github.com/PHPOffice/PHPWord/pull/1809) ([@juzser](https://github.com/juzser)) +- Fix PHPUnit tests on develop branch [#1771](https://github.com/PHPOffice/PHPWord/pull/1771) ([@mdupont](https://github.com/mdupont)) +- TemplateProcessor cloneBlock wrongly clones images [#1763](https://github.com/PHPOffice/PHPWord/pull/1763) ([@alarai](https://github.com/alarai)) + +### Miscellaneous +- Compatibility with PHP 7.4, PHP 8.0 and migrate to Laminas Escaper [#1946](https://github.com/PHPOffice/PHPWord/pull/1946) ([@liborm85](https://github.com/liborm85)) +- Remove legacy PHPOffice/Common package, fix PHP 8.0 compatibility [#1996](https://github.com/PHPOffice/PHPWord/pull/1996) ([@liborm85](https://github.com/liborm85)) +- Improve Word2007 Test Coverage [#1858](https://github.com/PHPOffice/PHPWord/pull/1858) ([@oleibman](https://github.com/oleibman)) +- Fix typo in docs. Update templates-processing.rst [#1952](https://github.com/PHPOffice/PHPWord/pull/1952) ([@mnvx](https://github.com/mnvx)) +- Fix documentation and method name for FootnoteProperties [#1776](https://github.com/PHPOffice/PHPWord/pull/1776) ([@mdupont](https://github.com/mdupont)) +- fix: documentation about paragraph indentation [#1764](https://github.com/PHPOffice/PHPWord/pull/1764) ([@mdupont](https://github.com/mdupont)) +- Update templates-processing.rst [#1745](https://github.com/PHPOffice/PHPWord/pull/1745) ([@igronus](https://github.com/igronus)) +- Unused variables $rows, $cols in sample [#1877](https://github.com/PHPOffice/PHPWord/pull/1877) ([@ThanasisMpalatsoukas](https://github.com/ThanasisMpalatsoukas)) +- Add unit test for NumberingStyle [#1744](https://github.com/PHPOffice/PHPWord/pull/1744) ([@Manunchik](https://github.com/Manunchik)) +- Add unit test for PhpWord Settings [#1743](https://github.com/PHPOffice/PHPWord/pull/1743) (@[Manunchik](https://github.com/Manunchik)) +- Add unit test for Media elements [#1742](https://github.com/PHPOffice/PHPWord/pull/1742) ([@Manunchik](https://github.com/Manunchik)) +- Update templates processing docs [#1729](https://github.com/PHPOffice/PHPWord/pull/1729) ([@hcdias](https://github.com/hcdias)) diff --git a/docs/changes/0.x/0.18.1.md b/docs/changes/0.x/0.18.1.md new file mode 100644 index 0000000000..f4e1547a26 --- /dev/null +++ b/docs/changes/0.x/0.18.1.md @@ -0,0 +1,7 @@ +# [0.18.1](https://github.com/PHPOffice/PHPWord/tree/0.18.1) (2021-03-08) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.18.0...0.18.1) + +### Bug fixes +- Fix BC break in GH-1946. + This package does not replace laminas/laminas-zendframework-bridge by [@mussbach](https://github.com/mussbach) in [#2032](https://github.com/PHPOffice/PHPWord/pull/2032) \ No newline at end of file diff --git a/docs/changes/0.x/0.18.2.md b/docs/changes/0.x/0.18.2.md new file mode 100644 index 0000000000..fe40b7eb3a --- /dev/null +++ b/docs/changes/0.x/0.18.2.md @@ -0,0 +1,14 @@ +# [0.18.2](https://github.com/PHPOffice/PHPWord/tree/0.18.2) (2021-06-04) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.18.1...0.18.2) + +### Bug fixes +- when adding image to relationship first check that the generated RID is actually unique by [@tpv-ebben](https://github.com/tpv-ebben) in [#2063](https://github.com/PHPOffice/PHPWord/pull/2063) +- Update chart, don't write 'c:overlap' if grouping is 'clustered' by [@dfsd534](https://github.com/dfsd534) in [#2052](https://github.com/PHPOffice/PHPWord/pull/2052) +- Update Html parser to accept line-height:normal by [@joelgo](https://github.com/joelgo) in [#2041](https://github.com/PHPOffice/PHPWord/pull/2041) +- Fix image border in Word2007 Writer for LibreOffice 7 by [k@amilmmach](https://github.com/kamilmmach) in [#2021](https://github.com/PHPOffice/PHPWord/pull/2021) + +### Miscellaneous +- Corrected namespace for Language class in docs by [@MegaChriz](https://github.com/MegaChriz) in [#2087](https://github.com/PHPOffice/PHPWord/pull/2087) +- Added support for Garamond font by [@artemkolotilkin](https://github.com/artemkolotilkin) in [#2078](https://github.com/PHPOffice/PHPWord/pull/2078) +- Add BorderStyle for Cell Style to documentation by [@DShkrabak](https://github.com/DShkrabak) in [#2090](https://github.com/PHPOffice/PHPWord/pull/2090) diff --git a/docs/changes/0.x/0.18.3.md b/docs/changes/0.x/0.18.3.md new file mode 100644 index 0000000000..123fe1f2b0 --- /dev/null +++ b/docs/changes/0.x/0.18.3.md @@ -0,0 +1,6 @@ +# [0.18.3](https://github.com/PHPOffice/PHPWord/tree/0.18.3) (2022-02-17) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.18.2...0.18.3) + +### Bug fixes +- PHP 8.1 compatibility diff --git a/docs/changes/0.x/0.7.0.md b/docs/changes/0.x/0.7.0.md new file mode 100644 index 0000000000..11c3784bc3 --- /dev/null +++ b/docs/changes/0.x/0.7.0.md @@ -0,0 +1,26 @@ +# 0.7.0 (28 Jan 2014) + +This is the first release after a long development hiatus in [CodePlex](https://phpword.codeplex.com/). This release initialized ODT and RTF Writer, along with some other new features for the existing Word2007 Writer, e.g. tab, multiple header, rowspan and colspan. [Composer](https://packagist.org/packages/phpoffice/phpword) and [Travis](https://travis-ci.org/PHPOffice/PHPWord) were added. + +### Features +- Implement RTF Writer - @Progi1984 #1 +- Implement ODT Writer - @Progi1984 #2 +- Word2007: Add rowspan and colspan to cells - @kaystrobach +- Word2007: Support for tab stops - @RLovelett +- Word2007: Support Multiple headers - @RLovelett +- Word2007: Wrapping Styles to Images - @gabrielbull +- Added support for image wrapping style - @gabrielbull + +### Bugfixes +- "Warning: Invalid error type specified in ...\PHPWord.php on line 226" is thrown when the specified template file is not found - @RomanSyroeshko #32 +- PHPWord_Shared_String.IsUTF8 returns FALSE for Cyrillic UTF-8 input - @RomanSyroeshko #34 +- Temporary files naming logic in PHPWord_Template can lead to a collision - @RomanSyroeshko #38 + +### Miscellaneous +- Add superscript/subscript styling in Excel2007 Writer - @MarkBaker +- add indentation support to paragraphs - @deds +- Support for Composer - @Progi1984 #27 +- Basic CI with Travis - @Progi1984 +- Added PHPWord_Exception and exception when could not copy the template - @Progi1984 +- IMPROVED: Moved examples out of Classes directory - @Progi1984 +- IMPROVED: Advanced string replace in setValue for Template - @Esmeraldo [#49](http://phpword.codeplex.com/workitem/49) \ No newline at end of file diff --git a/docs/changes/0.x/0.8.0.md b/docs/changes/0.x/0.8.0.md new file mode 100644 index 0000000000..6d5ae7c37c --- /dev/null +++ b/docs/changes/0.x/0.8.0.md @@ -0,0 +1,45 @@ +# 0.8.0 (15 Mar 2014) + +This release merged a lot of improvements from the community. Unit tests introduced in this release and has reached 90% code coverage. + +### Features +- Template: Permit to save a template generated as a file (PHPWord_Template::saveAs()) - @RomanSyroeshko #56, #57 +- Word2007: Support sections page numbering - @gabrielbull +- Word2007: Added line height methods to mirror the line height settings in Word in the paragraph styling - @gabrielbull +- Word2007: Added support for page header & page footer height - @JillElaine #5 +- General: Add ability to manage line breaks after image insertion - @bskrtich #6, #66, #84 +- Template: Ability to limit number of replacements performed by setValue() method of Template class - @RomanSyroeshko #52, #53, #85 +- Table row: Repeat as header row & allow row to break across pages - @ivanlanin #48, #86 +- Table: Table width in percentage - @ivanlanin #48, #86 +- Font: Superscript and subscript - @ivanlanin #48, #86 +- Paragraph: Hanging paragraph - @ivanlanin #48, #86 +- Section: Multicolumn and section break - @ivanlanin #48, #86 +- Template: Ability to apply XSL style sheet to Template - @RomanSyroeshko #46, #47, #83 +- General: PHPWord_Shared_Font::pointSizeToTwips() converter - @ivanlanin #87 +- Paragraph: Ability to define normal paragraph style with PHPWord::setNormalStyle() - @ivanlanin #87 +- Paragraph: Ability to define parent style (basedOn) and style for following paragraph (next) - @ivanlanin #87 +- Clone table rows on the fly when using a template document - @jeroenmoors #44, #88 +- Initial addition of basic footnote support - @deds #16 +- Paragraph: Ability to define paragraph pagination: widow control, keep next, keep lines, and page break before - @ivanlanin #92 +- General: PHPWord_Style_Font refactoring - @ivanlanin #93 +- Font: Use points instead of halfpoints internally. Conversion to halfpoints done during XML Writing. - @ivanlanin #93 +- Paragraph: setTabs() function - @ivanlanin #92 +- General: Basic support for TextRun on ODT and RTF - @ivanlanin #99 +- Reader: Basic Reader for Word2007 - @ivanlanin #104 +- TextRun: Allow Text Break in Text Run - @bskrtich #109 +- General: Support for East Asian fontstyle - @jhfangying #111, #118 +- Image: Use exif_imagetype to check image format instead of extension name - @gabrielbull #114 +- General: Setting for XMLWriter Compatibility option - @bskrtich #103 +- MemoryImage: Allow remote image when allow_url_open = on - @ivanlanin #122 +- TextBreak: Allow font and paragraph style for text break - @ivanlanin #18 + +### Bugfixes +- Fixed bug with cell styling - @gabrielbull +- Fixed bug list items inside of cells - @gabrielbull +- Adding a value that contains "&" in a template breaks it - @SiebelsTim #51 +- Example in README.md is broken - @Progi1984 #89 +- General: PHPWord_Shared_Drawing::centimetersToPixels() conversion - @ivanlanin #94 +- Footnote: Corrupt DOCX reported by MS Word when sections > 1 and not every sections have footnote - @ivanlanin #125 + +### Miscellaneous +- UnitTests - @Progi1984 \ No newline at end of file diff --git a/docs/changes/0.x/0.8.1.md b/docs/changes/0.x/0.8.1.md new file mode 100644 index 0000000000..340e6e369a --- /dev/null +++ b/docs/changes/0.x/0.8.1.md @@ -0,0 +1,9 @@ + +# 0.8.1 (17 Mar 2014) + +This is a bugfix release for image detection functionality. + +- Added fallback for computers that do not have exif_imagetype - @bskrtich, @gabrielbull + + + diff --git a/docs/changes/0.x/0.9.0.md b/docs/changes/0.x/0.9.0.md new file mode 100644 index 0000000000..8b96f24a77 --- /dev/null +++ b/docs/changes/0.x/0.9.0.md @@ -0,0 +1,19 @@ +# 0.9.0 (26 Mar 2014) + +This release marked the transformation to namespaces (PHP 5.3+). + +### Features +- Image: Ability to use remote or GD images using `addImage()` on sections, headers, footer, cells, and textruns - @ivanlanin +- Header: Ability to use remote or GD images using `addWatermark()` - @ivanlanin + +### Bugfixes +- Preserve text doesn't render correctly when the text is not the first word, e.g. 'Page {PAGE}' - @ivanlanin + +### Miscellaneous +- Move documentation to [Read The Docs](http://phpword.readthedocs.org/en/develop/) - by [@Progi1984](https://github.com/Progi1984) & [@ivanlanin](https://github.com/ivanlanin) in [#82](https://github.com/PHPOffice/PHPWord/pull/82) +- Reorganize and redesign samples folder - @ivanlanin #137 +- Use `PhpOffice\PhpWord` namespace for PSR compliance - @RomanSyroeshko @gabrielbull #159, #58 +- Restructure folders and change folder name `Classes` to `src` and `Tests` to `test` for PSR compliance - @RomanSyroeshko @gabrielbull +- Compliance to phpDocumentor - @ivanlanin +- Merge Style\TableFull into Style\Table. Style\TableFull is deprecated - @ivanlanin #160 +- Merge Section\MemoryImage into Section\Image. Section\Image is deprecated - @ivanlanin #160 diff --git a/docs/changes/0.x/0.9.1.md b/docs/changes/0.x/0.9.1.md new file mode 100644 index 0000000000..9278f916cf --- /dev/null +++ b/docs/changes/0.x/0.9.1.md @@ -0,0 +1,8 @@ + +# 0.9.1 (27 Mar 2014) + +This is a bugfix release for PSR-4 compatibility. + +- Fixed PSR-4 composer autoloader - @AntonTyutin + + diff --git a/docs/changes/1.x/1.0.0.md b/docs/changes/1.x/1.0.0.md new file mode 100644 index 0000000000..4240a0bd18 --- /dev/null +++ b/docs/changes/1.x/1.0.0.md @@ -0,0 +1,110 @@ +# [1.0.0](https://github.com/PHPOffice/PHPWord/tree/1.0.0) (2022-11-15) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.18.3...1.0.0) + +### BREAKING CHANGE + +Most deprecated things were dropped. See details in +https://github.com/PHPOffice/PHPWord/commit/b9f1151bc6f90c276153c3c9dca10a5fc7f355fb. + +#### Dropped classes: + +- `PhpOffice\PhpWord\Template` + +#### Dropped constants: + +- `PhpOffice\PhpWord\Style\Font::UNDERLINE_DOTHASH` +- `PhpOffice\PhpWord\Style\Font::UNDERLINE_DOTHASHHEAVY` +- `PhpOffice\PhpWord\Style\Cell::VALIGN_TOP` +- `PhpOffice\PhpWord\Style\Cell::VALIGN_CENTER` +- `PhpOffice\PhpWord\Style\Cell::VALIGN_BOTTOM` +- `PhpOffice\PhpWord\Style\Cell::VALIGN_BOTH` +- `PhpOffice\PhpWord\Style\TOC::TABLEADER_DOT` +- `PhpOffice\PhpWord\Style\TOC::TABLEADER_UNDERSCORE` +- `PhpOffice\PhpWord\Style\TOC::TABLEADER_LINE` +- `PhpOffice\PhpWord\Style\TOC::TABLEADER_NONE` +- `PhpOffice\PhpWord\Style\Table::WIDTH_AUTO` +- `PhpOffice\PhpWord\Style\Table::WIDTH_PERCENT` +- `PhpOffice\PhpWord\Style\Table::WIDTH_TWIP` +- `PhpOffice\PhpWord\PhpWord::DEFAULT_FONT_NAME` +- `PhpOffice\PhpWord\PhpWord::DEFAULT_FONT_SIZE` +- `PhpOffice\PhpWord\PhpWord::DEFAULT_FONT_COLOR` +- `PhpOffice\PhpWord\PhpWord::DEFAULT_FONT_CONTENT_TYPE` +- +#### Dropped methods: + +- `PhpOffice\PhpWord\Ekement\AbstractContainer::createTextRun()` +- `PhpOffice\PhpWord\Ekement\AbstractContainer::createFootnote()` +- `PhpOffice\PhpWord\Ekement\Footnote::getReferenceId()` +- `PhpOffice\PhpWord\Ekement\Footnote::setReferenceId()` +- `PhpOffice\PhpWord\Ekement\Image::getIsWatermark()` +- `PhpOffice\PhpWord\Ekement\Image::getIsMemImage()` +- `PhpOffice\PhpWord\Ekement\Link::getTarget()` +- `PhpOffice\PhpWord\Ekement\Link::getLinkSrc()` +- `PhpOffice\PhpWord\Ekement\Link::getLinkName()` +- `PhpOffice\PhpWord\Ekement\OLEObject::getObjectId()` +- `PhpOffice\PhpWord\Ekement\OLEObject::setObjectId()` +- `PhpOffice\PhpWord\Ekement\Section::getFootnotePropoperties()` +- `PhpOffice\PhpWord\Ekement\Section::setSettings()` +- `PhpOffice\PhpWord\Ekement\Section::getSettings()` +- `PhpOffice\PhpWord\Ekement\Section::createHeader()` +- `PhpOffice\PhpWord\Ekement\Section::createFooter()` +- `PhpOffice\PhpWord\Ekement\Section::getFooter()` +- `PhpOffice\PhpWord\Media::addSectionMediaElement()` +- `PhpOffice\PhpWord\Media::addSectionLinkElement()` +- `PhpOffice\PhpWord\Media::getSectionMediaElements()` +- `PhpOffice\PhpWord\Media::countSectionMediaElements()` +- `PhpOffice\PhpWord\Media::addHeaderMediaElement()` +- `PhpOffice\PhpWord\Media::countHeaderMediaElements()` +- `PhpOffice\PhpWord\Media::getHeaderMediaElements()` +- `PhpOffice\PhpWord\Media::addFooterMediaElement()` +- `PhpOffice\PhpWord\Media::countFooterMediaElements()` +- `PhpOffice\PhpWord\Media::getFooterMediaElements()` +- `PhpOffice\PhpWord\PhpWord::getProtection()` +- `PhpOffice\PhpWord\PhpWord::loadTemplate()` +- `PhpOffice\PhpWord\PhpWord::createSection()` +- `PhpOffice\PhpWord\PhpWord::getDocumentProperties()` +- `PhpOffice\PhpWord\PhpWord::setDocumentProperties()` +- `PhpOffice\PhpWord\Reader\AbstractReader::getReadDataOnly()` +- `PhpOffice\PhpWord\Settings::getCompatibility()` +- `PhpOffice\PhpWord\Style\AbstractStyle::setArrayStyle()` +- `PhpOffice\PhpWord\Style\Cell::getDefaultBorderColor()` +- `PhpOffice\PhpWord\Style\Font::getBold()` +- `PhpOffice\PhpWord\Style\Font::getItalic()` +- `PhpOffice\PhpWord\Style\Font::getSuperScript()` +- `PhpOffice\PhpWord\Style\Font::getSubScript()` +- `PhpOffice\PhpWord\Style\Font::getStrikethrough()` +- `PhpOffice\PhpWord\Style\Font::getParagraphStyle()` +- `PhpOffice\PhpWord\Style\Frame::getAlign()` +- `PhpOffice\PhpWord\Style\Frame::setAlign()` +- `PhpOffice\PhpWord\Style\NumberingLevel::getAlign()` +- `PhpOffice\PhpWord\Style\NumberingLevel::setAlign()` +- `PhpOffice\PhpWord\Style\Paragraph::getAlign()` +- `PhpOffice\PhpWord\Style\Paragraph::setAlign()` +- `PhpOffice\PhpWord\Style\Paragraph::getWidowControl()` +- `PhpOffice\PhpWord\Style\Paragraph::getKeepNext()` +- `PhpOffice\PhpWord\Style\Paragraph::getKeepLines()` +- `PhpOffice\PhpWord\Style\Paragraph::getPageBreakBefore()` +- `PhpOffice\PhpWord\Style\Row::getTblHeader()` +- `PhpOffice\PhpWord\Style\Row::isTblHeader()` +- `PhpOffice\PhpWord\Style\Row::getCantSplit()` +- `PhpOffice\PhpWord\Style\Row::getExactHeight()` +- `PhpOffice\PhpWord\Style\Spacing::getRule()` +- `PhpOffice\PhpWord\Style\Spacing::setRule()` +- `PhpOffice\PhpWord\Style\Table::getAlign()` +- `PhpOffice\PhpWord\Style\Table::setAlign()` +- `PhpOffice\PhpWord\Writer\AbstractWriter::getUseDiskCaching()` +- `PhpOffice\PhpWord\Writer\HTML::writeDocument()` + +### Bug fixes + +- Multiple PHP 8.1 fixes +- `loadConfig` returns config that was actually applied +- HTML Reader : Override inline style on HTML attribute for table +- HTML Reader : Use `border` attribute for tables +- HTML Reader : Style page-break-after in paragraph +- HTML Reader : Heading in Text Run is not allowed + +### Miscellaneous + +- Drop support for PHP 7.0 and older \ No newline at end of file diff --git a/docs/changes/1.x/1.1.0.md b/docs/changes/1.x/1.1.0.md new file mode 100644 index 0000000000..1fee96fb87 --- /dev/null +++ b/docs/changes/1.x/1.1.0.md @@ -0,0 +1,24 @@ +# [1.1.0](https://github.com/PHPOffice/PHPWord/tree/1.1.0) (2023-05-30) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.0.0...1.1.0) + +### Enhancements + +- Introduce deleteRow() method for TemplateProcessor +- HTML Reader: Add basic support for CSS Style Tag +- Allow customizing macro syntax in TemplateProcessor +- Add background color support for textboxes +- Add softhyphen support to word reader +- Add support table row height when importing HTML +- Add support for fractional font sizes +- Added image quality support, with the maximum quality as default +- Support for reading nested tables + +### Bug fixes + +- DOCX reader: Read empty vmerge +- Fixed setting width of Cell Style + +### Miscellaneous + +- `master` is the new default branch \ No newline at end of file diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md new file mode 100644 index 0000000000..e52771c08c --- /dev/null +++ b/docs/changes/1.x/1.2.0.md @@ -0,0 +1,30 @@ +# [1.2.0](https://github.com/PHPOffice/PHPWord/tree/1.2.0) (WIP) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.1.0...1.2.0) + +## Enhancements + +- Word2007 Reader/Writer : Added noWrap table cell property by [@kernusr](https://github.com/kernusr) in GH-2359 +- HTML Reader : Support for `font-variant: small-caps` by [@cambraca](https://github.com/cambraca) in GH-2117 +- Improved TextDirection for styling a cell by [@terryzwt](https://github.com/terryzwt) in GH-2429 +- Word2007 Reader : Added option to disable loading images by [@aelliott1485](https://github.com/aelliott1485) in GH-2450 +- HTML Writer : Added border-spacing to default styles for table by [@kernusr](https://github.com/kernusr) in GH-2451 +- Word2007 Reader : Support for table cell borders and margins by [@kernusr](https://github.com/kernusr) in GH-2454 + +### Bug fixes + +- Fixed wrong mimetype for docx files by [@gamerlv](https://github.com/gamerlv) in GH-2416 +- Word2007 Reader : Read hyperlingks in headings by [@hannesdorn](https://github.com/hannesdorn) in GH-2433 +- PclZip : strtr using empty string by [@spl1nes](https://github.com/spl1nes) in GH-2432 +- Fixed PHP 8.2 deprecated about Allow access to an undefined property by [@DAdq26](https://github.com/DAdq26) in GH-2440 +- Template Processor : Fixed choose dimention for Float Value by [@gdevilbat](https://github.com/gdevilbat) in GH-2449 +- HTML Parser : Fix image parsing from url without extension by [@JokubasR](https://github.com/JokubasR) in GH-2459 + +### Miscellaneous + +- Added PHPStan by [@PowerKiKi](https://github.com/PowerKiKi) in GH-2405 +- Bump symfony/process from 4.4.44 to 5.4.26 by [@dependabot](https://github.com/dependabot) in GH-2431 +- Bump phpunit/phpunit from 9.6.8 to 9.6.10 by [@dependabot](https://github.com/dependabot) in GH-2430 +- Added Coveralls.io by [@Progi1984](https://github.com/Progi1984) in GH-2452 +- Added support for PHP 8.2 & PHP 8.3 by [@Progi1984](https://github.com/Progi1984) in GH-2453 +- Moved documention from ReadTheDocs to MkDocs & Github Pages by [@Progi1984](https://github.com/Progi1984) in GH-2465 \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100644 index ef7b2dcf6c..0000000000 --- a/docs/conf.py +++ /dev/null @@ -1,290 +0,0 @@ -# -*- coding: utf-8 -*- -# -# PhpWord documentation build configuration file, created by -# sphinx-quickstart on Fri Mar 14 23:09:26 2014. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'PHPWord' -copyright = u'2014-2021, PHPWord Contributors' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '0.18.2' -# The full version, including alpha/beta/rc tags. -release = version - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['_build'] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'default' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -#html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'PHPWorddoc' - - -# -- Options for LaTeX output -------------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'PHPWord.tex', u'PHPWord Documentation', - u'The PHPWord Team', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'PHPWord', u'PHPWord Documentation', - [u'The PHPWord Team'], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------------ - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'PHPWord', u'PHPWord Documentation', - u'The PHPWord Team', 'PHPWord', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - -# -- Options for Epub output --------------------------------------------------- - -# Bibliographic Dublin Core info. -epub_title = u'PHPWord' -epub_author = u'The PHPWord Team' -epub_publisher = u'The PHPWord Team' -epub_copyright = copyright - -# The language of the text. It defaults to the language option -# or en if the language is not set. -#epub_language = '' - -# The scheme of the identifier. Typical schemes are ISBN or URL. -#epub_scheme = '' - -# The unique identifier of the text. This can be a ISBN number -# or the project homepage. -#epub_identifier = '' - -# A unique identification for the text. -#epub_uid = '' - -# A tuple containing the cover image and cover page html template filenames. -#epub_cover = () - -# HTML files that should be inserted before the pages created by sphinx. -# The format is a list of tuples containing the path and title. -#epub_pre_files = [] - -# HTML files shat should be inserted after the pages created by sphinx. -# The format is a list of tuples containing the path and title. -#epub_post_files = [] - -# A list of files that should not be packed into the epub file. -#epub_exclude_files = [] - -# The depth of the table of contents in toc.ncx. -#epub_tocdepth = 3 - -# Allow duplicate toc entries. -#epub_tocdup = True - -# Highlight PHP without starting addText($text, [$fontStyle], [$paragraphStyle]); - $textrun = $section->addTextRun([$paragraphStyle]); - -- ``$text``. Text to be displayed in the document. -- ``$fontStyle``. See :ref:`font-style`. -- ``$paragraphStyle``. See :ref:`paragraph-style`. - -For available styling options see :ref:`font-style` and :ref:`paragraph-style`. - -If you want to enable track changes on added text you can mark it as INSERTED or DELETED by a specific user at a given time: - -.. code-block:: php - - $text = $section->addText('Hello World!'); - $text->setChanged(\PhpOffice\PhpWord\Element\ChangedElement::TYPE_INSERTED, 'Fred', (new \DateTime())); - -Titles -~~~~~~ - -If you want to structure your document or build table of contents, you need titles or headings. -To add a title to the document, use the ``addTitleStyle`` and ``addTitle`` method. -If `depth` is 0, a Title will be inserted, otherwise a Heading1, Heading2, ... - -.. code-block:: php - - $phpWord->addTitleStyle($depth, [$fontStyle], [$paragraphStyle]); - $section->addTitle($text, [$depth]); - -- ``depth``. -- ``$fontStyle``. See :ref:`font-style`. -- ``$paragraphStyle``. See :ref:`paragraph-style`. -- ``$text``. Text to be displayed in the document. This can be `string` or a `\PhpOffice\PhpWord\Element\TextRun` - -It's necessary to add a title style to your document because otherwise the title won't be detected as a real title. - -Links -~~~~~ - -You can add Hyperlinks to the document by using the function addLink: - -.. code-block:: php - - $section->addLink($linkSrc, [$linkName], [$fontStyle], [$paragraphStyle]); - -- ``$linkSrc``. The URL of the link. -- ``$linkName``. Placeholder of the URL that appears in the document. -- ``$fontStyle``. See :ref:`font-style`. -- ``$paragraphStyle``. See :ref:`paragraph-style`. - -Preserve texts -~~~~~~~~~~~~~~ - -The ``addPreserveText`` method is used to add a page number or page count to headers or footers. - -.. code-block:: php - - $footer->addPreserveText('Page {PAGE} of {NUMPAGES}.'); - -Breaks ------- - -Text breaks -~~~~~~~~~~~ - -Text breaks are empty new lines. To add text breaks, use the following syntax. All parameters are optional. - -.. code-block:: php - - $section->addTextBreak([$breakCount], [$fontStyle], [$paragraphStyle]); - -- ``$breakCount``. How many lines. -- ``$fontStyle``. See :ref:`font-style`. -- ``$paragraphStyle``. See :ref:`paragraph-style`. - -Page breaks -~~~~~~~~~~~ - -There are two ways to insert a page break, using the ``addPageBreak`` -method or using the ``pageBreakBefore`` style of paragraph. - -.. code-block:: php - - $section->addPageBreak(); - -Lists ------ - -Lists can be added by using ``addListItem`` and ``addListItemRun`` methods. -``addListItem`` is used for creating lists that only contain plain text. -``addListItemRun`` is used for creating complex list items that contains texts -with different style (some bold, other italics, etc) or other elements, e.g. -images or links. The syntaxes are as follow: - -Basic usage: - -.. code-block:: php - - $section->addListItem($text, [$depth], [$fontStyle], [$listStyle], [$paragraphStyle]); - $listItemRun = $section->addListItemRun([$depth], [$listStyle], [$paragraphStyle]) - -Parameters: - -- ``$text``. Text that appears in the document. -- ``$depth``. Depth of list item. -- ``$fontStyle``. See :ref:`font-style`. -- ``$listStyle``. List style of the current element TYPE\_NUMBER, - TYPE\_ALPHANUM, TYPE\_BULLET\_FILLED, etc. See list of constants in PHPWord\\Style\\ListItem. -- ``$paragraphStyle``. See :ref:`paragraph-style`. - -See ``Sample_14_ListItem.php`` for more code sample. - -Advanced usage: - -You can also create your own numbering style by changing the ``$listStyle`` parameter with the name of your numbering style. - -.. code-block:: php - - $phpWord->addNumberingStyle( - 'multilevel', - array( - 'type' => 'multilevel', - 'levels' => array( - array('format' => 'decimal', 'text' => '%1.', 'left' => 360, 'hanging' => 360, 'tabPos' => 360), - array('format' => 'upperLetter', 'text' => '%2.', 'left' => 720, 'hanging' => 360, 'tabPos' => 720), - ) - ) - ); - $section->addListItem('List Item I', 0, null, 'multilevel'); - $section->addListItem('List Item I.a', 1, null, 'multilevel'); - $section->addListItem('List Item I.b', 1, null, 'multilevel'); - $section->addListItem('List Item II', 0, null, 'multilevel'); - -For available styling options see :ref:`numbering-level-style`. - -Tables ------- - -To add tables, rows, and cells, use the ``addTable``, ``addRow``, and ``addCell`` methods: - -.. code-block:: php - - $table = $section->addTable([$tableStyle]); - $table->addRow([$height], [$rowStyle]); - $cell = $table->addCell($width, [$cellStyle]); - -Table style can be defined with ``addTableStyle``: - -.. code-block:: php - - $tableStyle = array( - 'borderColor' => '006699', - 'borderSize' => 6, - 'cellMargin' => 50 - ); - $firstRowStyle = array('bgColor' => '66BBFF'); - $phpWord->addTableStyle('myTable', $tableStyle, $firstRowStyle); - $table = $section->addTable('myTable'); - -For available styling options see :ref:`table-style`. - -Cell span -~~~~~~~~~ - -You can span a cell on multiple columns by using ``gridSpan`` or multiple rows by using ``vMerge``. - -.. code-block:: php - - $cell = $table->addCell(200); - $cell->getStyle()->setGridSpan(5); - -See ``Sample_09_Tables.php`` for more code sample. - -Images ------- - -To add an image, use the ``addImage`` method to sections, headers, footers, textruns, or table cells. - -.. code-block:: php - - $section->addImage($src, [$style]); - -- ``$src``. String path to a local image, URL of a remote image or the image data, as a string. Warning: Do not pass user-generated strings here, as that would allow an attacker to read arbitrary files or perform server-side request forgery by passing file paths or URLs instead of image data. -- ``$style``. See :ref:`image-style`. - -Examples: - -.. code-block:: php - - $section = $phpWord->addSection(); - $section->addImage( - 'mars.jpg', - array( - 'width' => 100, - 'height' => 100, - 'marginTop' => -1, - 'marginLeft' => -1, - 'wrappingStyle' => 'behind' - ) - ); - $footer = $section->addFooter(); - $footer->addImage('http://example.com/image.php'); - $textrun = $section->addTextRun(); - $textrun->addImage('http://php.net/logo.jpg'); - $source = file_get_contents('/path/to/my/images/earth.jpg'); - $textrun->addImage($source); - -Watermarks -~~~~~~~~~~ - -To add a watermark (or page background image), your section needs a -header reference. After creating a header, you can use the -``addWatermark`` method to add a watermark. - -.. code-block:: php - - $section = $phpWord->addSection(); - $header = $section->addHeader(); - $header->addWatermark('resources/_earth.jpg', array('marginTop' => 200, 'marginLeft' => 55)); - -Objects -------- - -You can add OLE embeddings, such as Excel spreadsheets or PowerPoint -presentations to the document by using ``addOLEObject`` method. - -.. code-block:: php - - $section->addOLEObject($src, [$style]); - -Table of contents ------------------ - -To add a table of contents (TOC), you can use the ``addTOC`` method. -Your TOC can only be generated if you have add at least one title (See "Titles"). - -.. code-block:: php - - $section->addTOC([$fontStyle], [$tocStyle], [$minDepth], [$maxDepth]); - -- ``$fontStyle``. See font style section. -- ``$tocStyle``. See available options below. -- ``$minDepth``. Minimum depth of header to be shown. Default 1. -- ``$maxDepth``. Maximum depth of header to be shown. Default 9. - -Options for ``$tocStyle``: - -- ``tabLeader``. Fill type between the title text and the page number. Use the defined constants in ``\PhpOffice\PhpWord\Style\TOC``. -- ``tabPos``. The position of the tab where the page number appears in *twip*. -- ``indent``. The indent factor of the titles in *twip*. - -Footnotes & endnotes --------------------- - -You can create footnotes with ``addFootnote`` and endnotes with -``addEndnote`` in texts or textruns, but it's recommended to use textrun -to have better layout. You can use ``addText``, ``addLink``, -``addTextBreak``, ``addImage``, ``addOLEObject`` on footnotes and endnotes. - -On textrun: - -.. code-block:: php - - $textrun = $section->addTextRun(); - $textrun->addText('Lead text.'); - $footnote = $textrun->addFootnote(); - $footnote->addText('Footnote text can have '); - $footnote->addLink('http://test.com/', 'links'); - $footnote->addText('.'); - $footnote->addTextBreak(); - $footnote->addText('And text break.'); - $textrun->addText('Trailing text.'); - $endnote = $textrun->addEndnote(); - $endnote->addText('Endnote put at the end'); - -On text: - -.. code-block:: php - - $section->addText('Lead text.'); - $footnote = $section->addFootnote(); - $footnote->addText('Footnote text.'); - -By default the footnote reference number will be displayed with decimal number -starting from 1. This number uses the ``FooterReference`` style which you can -redefine with the ``addFontStyle`` method. Default value for this style is -``array('superScript' => true)``; - -The footnote numbering can be controlled by setting the FootnoteProperties on the Section. - -.. code-block:: php - - $fp = new \PhpOffice\PhpWord\ComplexType\FootnoteProperties(); - //sets the position of the footnote (pageBottom (default), beneathText, sectEnd, docEnd) - $fp->setPos(\PhpOffice\PhpWord\ComplexType\FootnoteProperties::POSITION_BENEATH_TEXT); - //set the number format to use (decimal (default), upperRoman, upperLetter, ...) - $fp->setNumFmt(\PhpOffice\PhpWord\SimpleType\NumberFormat::LOWER_ROMAN); - //force starting at other than 1 - $fp->setNumStart(2); - //when to restart counting (continuous (default), eachSect, eachPage) - $fp->setNumRestart(\PhpOffice\PhpWord\ComplexType\FootnoteProperties::RESTART_NUMBER_EACH_PAGE); - //And finaly, set it on the Section - $section->setFootnoteProperties($fp); - -Checkboxes ----------- - -Checkbox elements can be added to sections or table cells by using ``addCheckBox``. - -.. code-block:: php - - $section->addCheckBox($name, $text, [$fontStyle], [$paragraphStyle]) - -- ``$name``. Name of the check box. -- ``$text``. Text to be displayed in the document. -- ``$fontStyle``. See :ref:`font-style`. -- ``$paragraphStyle``. See :ref:`paragraph-style`. - -Textboxes ---------- - -To be completed - -Fields ------- - -Currently the following fields are supported: - -- PAGE -- NUMPAGES -- DATE -- XE -- INDEX - -.. code-block:: php - - $section->addField($fieldType, [$properties], [$options], [$fieldText], [$fontStyle]) - -- ``$fontStyle``. See :ref:`font-style`. - -See ``\PhpOffice\PhpWord\Element\Field`` for list of properties and options available for each field type. -Options which are not specifically defined can be added. Those must start with a ``\``. - -For instance for the INDEX field, you can do the following (See `Index Field for list of available options `_ ): - -.. code-block:: php - - //the $fieldText can be either a simple string - $fieldText = 'The index value'; - - //or a 'TextRun', to be able to format the text you want in the index - $fieldText = new TextRun(); - $fieldText->addText('My '); - $fieldText->addText('bold index', ['bold' => true]); - $fieldText->addText(' entry'); - $section->addField('XE', array(), array(), $fieldText); - - //this actually adds the index - $section->addField('INDEX', array(), array('\\e " " \\h "A" \\c "3"'), 'right click to update index'); - -Line ----- - -Line elements can be added to sections by using ``addLine``. - -.. code-block:: php - - $lineStyle = array('weight' => 1, 'width' => 100, 'height' => 0, 'color' => 635552); - $section->addLine($lineStyle); - -Available line style attributes: - -- ``weight``. Line width in *twip*. -- ``color``. Defines the color of stroke. -- ``dash``. Line types: dash, rounddot, squaredot, dashdot, longdash, longdashdot, longdashdotdot. -- ``beginArrow``. Start type of arrow: block, open, classic, diamond, oval. -- ``endArrow``. End type of arrow: block, open, classic, diamond, oval. -- ``width``. Line-object width in *pt*. -- ``height``. Line-object height in *pt*. -- ``flip``. Flip the line element: true, false. - -Chart ------ - -Charts can be added using - -.. code-block:: php - - $categories = array('A', 'B', 'C', 'D', 'E'); - $series = array(1, 3, 2, 5, 4); - $chart = $section->addChart('line', $categories, $series, $style); - -For available styling options see :ref:`chart-style`. - -check out the Sample_32_Chart.php for more options and styling. - -Comments --------- - -Comments can be added to a document by using ``addComment``. -The comment can contain formatted text. Once the comment has been added, it can be linked to any element with ``setCommentStart``. - -.. code-block:: php - - // first create a comment - $comment= new \PhpOffice\PhpWord\Element\Comment('Authors name', new \DateTime(), 'my_initials'); - $comment->addText('Test', array('bold' => true)); - - // add it to the document - $phpWord->addComment($comment); - - $textrun = $section->addTextRun(); - $textrun->addText('This '); - $text = $textrun->addText('is'); - // link the comment to the text you just created - $text->setCommentStart($comment); - -If no end is set for a comment using the ``setCommentEnd``, the comment will be ended automatically at the end of the element it is started on. - -Track Changes -------------- - -Track changes can be set on text elements. There are 2 ways to set the change information on an element. -Either by calling the `setChangeInfo()`, or by setting the `TrackChange` instance on the element with `setTrackChange()`. - -.. code-block:: php - - $phpWord = new \PhpOffice\PhpWord\PhpWord(); - - // New portrait section - $section = $phpWord->addSection(); - $textRun = $section->addTextRun(); - - $text = $textRun->addText('Hello World! Time to '); - - $text = $textRun->addText('wake ', array('bold' => true)); - $text->setChangeInfo(TrackChange::INSERTED, 'Fred', time() - 1800); - - $text = $textRun->addText('up'); - $text->setTrackChange(new TrackChange(TrackChange::INSERTED, 'Fred')); - - $text = $textRun->addText('go to sleep'); - $text->setChangeInfo(TrackChange::DELETED, 'Barney', new \DateTime('@' . (time() - 3600))); diff --git a/docs/faq.md b/docs/faq.md new file mode 100644 index 0000000000..81341fbc18 --- /dev/null +++ b/docs/faq.md @@ -0,0 +1,5 @@ +# Frequently asked questions + +## How contribute to PHPWord? +- Improve the documentation + diff --git a/docs/faq.rst b/docs/faq.rst deleted file mode 100644 index 451e1d7305..0000000000 --- a/docs/faq.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. _faq: - -Frequently asked questions -========================== - -How contribute to PHPWord? --------------------------- -- Improve the documentation (`Sphinx Format `__) diff --git a/docs/general.rst b/docs/general.rst deleted file mode 100644 index 145df162ab..0000000000 --- a/docs/general.rst +++ /dev/null @@ -1,344 +0,0 @@ -.. _general: - -General usage -============= - -Basic example -------------- - -The following is a basic example of the PHPWord library. More examples -are provided in the `samples -folder `__. - -.. code-block:: php - - addSection(); - // Adding Text element to the Section having font styled by default... - $section->addText( - '"Learn from yesterday, live for today, hope for tomorrow. ' - . 'The important thing is not to stop questioning." ' - . '(Albert Einstein)' - ); - - /* - * Note: it's possible to customize font style of the Text element you add in three ways: - * - inline; - * - using named font style (new font style object will be implicitly created); - * - using explicitly created font style object. - */ - - // Adding Text element with font customized inline... - $section->addText( - '"Great achievement is usually born of great sacrifice, ' - . 'and is never the result of selfishness." ' - . '(Napoleon Hill)', - array('name' => 'Tahoma', 'size' => 10) - ); - - // Adding Text element with font customized using named font style... - $fontStyleName = 'oneUserDefinedStyle'; - $phpWord->addFontStyle( - $fontStyleName, - array('name' => 'Tahoma', 'size' => 10, 'color' => '1B2232', 'bold' => true) - ); - $section->addText( - '"The greatest accomplishment is not in never falling, ' - . 'but in rising again after you fall." ' - . '(Vince Lombardi)', - $fontStyleName - ); - - // Adding Text element with font customized using explicitly created font style object... - $fontStyle = new \PhpOffice\PhpWord\Style\Font(); - $fontStyle->setBold(true); - $fontStyle->setName('Tahoma'); - $fontStyle->setSize(13); - $myTextElement = $section->addText('"Believe you can and you\'re halfway there." (Theodor Roosevelt)'); - $myTextElement->setFontStyle($fontStyle); - - // Saving the document as OOXML file... - $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007'); - $objWriter->save('helloWorld.docx'); - - // Saving the document as ODF file... - $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'ODText'); - $objWriter->save('helloWorld.odt'); - - // Saving the document as HTML file... - $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'HTML'); - $objWriter->save('helloWorld.html'); - - /* Note: we skip RTF, because it's not XML-based and requires a different example. */ - /* Note: we skip PDF, because "HTML-to-PDF" approach is used to create PDF documents. */ - -PHPWord Settings ----------------- - -The ``PhpOffice\PhpWord\Settings`` class provides some options that will -affect the behavior of PHPWord. Below are the options. - -XML Writer compatibility -~~~~~~~~~~~~~~~~~~~~~~~~ - -This option sets -`XMLWriter::setIndent `__ -and -`XMLWriter::setIndentString `__. -The default value of this option is ``true`` (compatible), which is -`required for -OpenOffice `__ to -render OOXML document correctly. You can set this option to ``false`` -during development to make the resulting XML file easier to read. - -.. code-block:: php - - \PhpOffice\PhpWord\Settings::setCompatibility(false); - -Zip class -~~~~~~~~~ - -By default, PHPWord uses `Zip extension `__ -to deal with ZIP compressed archives and files inside them. If you can't have -Zip extension installed on your server, you can use pure PHP library -alternative, `PclZip `__, which is -included in PHPWord. - -.. code-block:: php - - \PhpOffice\PhpWord\Settings::setZipClass(\PhpOffice\PhpWord\Settings::PCLZIP); - -Output escaping -~~~~~~~~~~~~~~~ - -Writing documents of some formats, especially XML-based, requires correct output escaping. -Without it your document may become broken when you put special characters like ampersand, quotes, and others in it. - -Escaping can be performed in two ways: outside of the library by a software developer and inside of the library by built-in mechanism. -By default, the built-in mechanism is disabled for backward compatibility with versions prior to v0.13.0. -To turn it on set ``outputEscapingEnabled`` option to ``true`` in your PHPWord configuration file or use the following instruction at runtime: - -.. code-block:: php - - \PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(true); - -Default Paper -~~~~~~~~~~~~~ - -By default, all sections of the document will print on A4 paper. -You can alter the default paper by using the following function: - -.. code-block:: php - - \PhpOffice\PhpWord\Settings::setDefaultPaper('Letter'); - -Default font -~~~~~~~~~~~~ - -By default, every text appears in Arial 10 point. You can alter the -default font by using the following two functions: - -.. code-block:: php - - $phpWord->setDefaultFontName('Times New Roman'); - $phpWord->setDefaultFontSize(12); - -Document settings ------------------ -Settings for the generated document can be set using ``$phpWord->getSettings()`` - -Magnification Setting -~~~~~~~~~~~~~~~~~~~~~ -The default zoom value is 100 percent. This can be changed either to another percentage - -.. code-block:: php - - $phpWord->getSettings()->setZoom(75); - -Or to predefined values ``fullPage``, ``bestFit``, ``textFit`` - -.. code-block:: php - - $phpWord->getSettings()->setZoom(Zoom::BEST_FIT); - -Mirroring the Page Margins -~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use mirror margins to set up facing pages for double-sided documents, such as books or magazines. - -.. code-block:: php - - $phpWord->getSettings()->setMirrorMargins(true); - -Spelling and grammatical checks -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -By default spelling and grammatical errors are shown as soon as you open a word document. -For big documents this can slow down the opening of the document. You can hide the spelling and/or grammatical errors with: - -.. code-block:: php - - $phpWord->getSettings()->setHideGrammaticalErrors(true); - $phpWord->getSettings()->setHideSpellingErrors(true); - -You can also specify the status of the spell and grammar checks, marking spelling or grammar as dirty will force a re-check when opening the document. - -.. code-block:: php - - $proofState = new \PhpOffice\PhpWord\ComplexType\ProofState(); - $proofState->setGrammar(\PhpOffice\PhpWord\ComplexType\ProofState::CLEAN); - $proofState->setSpelling(\PhpOffice\PhpWord\ComplexType\ProofState::DIRTY); - - $phpWord->getSettings()->setProofState($proofState); - -Track Revisions -~~~~~~~~~~~~~~~ -Track changes can be activated using ``setTrackRevisions``, you can furture specify - -- Not to use move syntax, instead moved items will be seen as deleted in one place and added in another -- Not track formatting revisions - -.. code-block:: php - - $phpWord->getSettings()->setTrackRevisions(true); - $phpWord->getSettings()->setDoNotTrackMoves(true); - $phpWord->getSettings()->setDoNotTrackFormatting(true); - -Decimal Symbol -~~~~~~~~~~~~~~ -The default symbol to represent a decimal figure is the ``.`` in english. In french you might want to change it to ``,`` for instance. - -.. code-block:: php - - $phpWord->getSettings()->setDecimalSymbol(','); - -Document Language -~~~~~~~~~~~~~~~~~ -The default language of the document can be change with the following. - -.. code-block:: php - - $phpWord->getSettings()->setThemeFontLang(new Language(Language::FR_BE)); - -``Language`` has 3 parameters, one for Latin languages, one for East Asian languages and one for Complex (Bi-Directional) languages. -A couple of language codes are provided in the ``PhpOffice\PhpWord\Style\Language`` class but any valid code/ID can be used. - -In case you are generating an RTF document the language need to be set differently. - -.. code-block:: php - - $lang = new Language(); - $lang->setLangId(Language::EN_GB_ID); - $phpWord->getSettings()->setThemeFontLang($lang); - -Document information --------------------- - -You can set the document information such as title, creator, and company -name. Use the following functions: - -.. code-block:: php - - $properties = $phpWord->getDocInfo(); - $properties->setCreator('My name'); - $properties->setCompany('My factory'); - $properties->setTitle('My title'); - $properties->setDescription('My description'); - $properties->setCategory('My category'); - $properties->setLastModifiedBy('My name'); - $properties->setCreated(mktime(0, 0, 0, 3, 12, 2014)); - $properties->setModified(mktime(0, 0, 0, 3, 14, 2014)); - $properties->setSubject('My subject'); - $properties->setKeywords('my, key, word'); - -Measurement units ------------------ - -The base length unit in Open Office XML is twip. Twip means "TWentieth -of an Inch Point", i.e. 1 twip = 1/1440 inch. - -You can use PHPWord helper functions to convert inches, centimeters, or -points to twip. - -.. code-block:: php - - // Paragraph with 6 points space after - $phpWord->addParagraphStyle('My Style', array( - 'spaceAfter' => \PhpOffice\PhpWord\Shared\Converter::pointToTwip(6)) - ); - - $section = $phpWord->addSection(); - $sectionStyle = $section->getStyle(); - // half inch left margin - $sectionStyle->setMarginLeft(\PhpOffice\PhpWord\Shared\Converter::inchToTwip(.5)); - // 2 cm right margin - $sectionStyle->setMarginRight(\PhpOffice\PhpWord\Shared\Converter::cmToTwip(2)); - -Document protection -------------------- - -The document (or parts of it) can be password protected. - -.. code-block:: php - - $documentProtection = $phpWord->getSettings()->getDocumentProtection(); - $documentProtection->setEditing(DocProtect::READ_ONLY); - $documentProtection->setPassword('myPassword'); - -Automatically Recalculate Fields on Open ----------------------------------------- - -To force an update of the fields present in the document, set updateFields to true - -.. code-block:: php - - $phpWord->getSettings()->setUpdateFields(true); - -Hyphenation ------------ -Hyphenation describes the process of breaking words with hyphens. There are several options to control hyphenation. - -Auto hyphenation -~~~~~~~~~~~~~~~~ - -To automatically hyphenate text set ``autoHyphenation`` to ``true``. - -.. code-block:: php - - $phpWord->getSettings()->setAutoHyphenation(true); - -Consecutive Hyphen Limit -~~~~~~~~~~~~~~~~~~~~~~~~ - -The maximum number of consecutive lines of text ending with a hyphen can be controlled by the ``consecutiveHyphenLimit`` option. -There is no limit if the option is not set or the provided value is ``0``. - -.. code-block:: php - - $phpWord->getSettings()->setConsecutiveHyphenLimit(2); - -Hyphenation Zone -~~~~~~~~~~~~~~~~ - -The hyphenation zone (in *twip*) is the allowed amount of whitespace before hyphenation is applied. -The smaller the hyphenation zone the more words are hyphenated. Or in other words, the wider the hyphenation zone the less words are hyphenated. - -.. code-block:: php - - $phpWord->getSettings()->setHyphenationZone(\PhpOffice\PhpWord\Shared\Converter::cmToTwip(1)); - -Hyphenate Caps -~~~~~~~~~~~~~~ - -To control whether or not words in all capital letters shall be hyphenated use the `doNotHyphenateCaps` option. - -.. code-block:: php - - $phpWord->getSettings()->setDoNotHyphenateCaps(true); diff --git a/docs/howto.md b/docs/howto.md new file mode 100644 index 0000000000..f53217f869 --- /dev/null +++ b/docs/howto.md @@ -0,0 +1,101 @@ +# How to + +## Create float left image + +Use absolute positioning relative to margin horizontally and to line vertically. + +``` php + 40, + 'height' => 40, + 'wrappingStyle' => 'square', + 'positioning' => 'absolute', + 'posHorizontalRel' => 'margin', + 'posVerticalRel' => 'line', +); +$textrun->addImage('resources/_earth.jpg', $imageStyle); +``` + +## Download the produced file automatically + +Use ``php://output`` as the filename. + +``` php +addSection(); +$section->addText('Hello World!'); +$file = 'HelloWorld.docx'; +header("Content-Description: File Transfer"); +header('Content-Disposition: attachment; filename="' . $file . '"'); +header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document'); +header('Content-Transfer-Encoding: binary'); +header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); +header('Expires: 0'); +$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007'); +$xmlWriter->save("php://output"); +``` + +## Create numbered headings + +Define a numbering style and title styles, and match the two styles (with ``pStyle`` and ``numStyle``) like below. + +``` php +addNumberingStyle( + 'hNum', + array('type' => 'multilevel', 'levels' => array( + array('pStyle' => 'Heading1', 'format' => 'decimal', 'text' => '%1'), + array('pStyle' => 'Heading2', 'format' => 'decimal', 'text' => '%1.%2'), + array('pStyle' => 'Heading3', 'format' => 'decimal', 'text' => '%1.%2.%3'), + ) + ) +); +$phpWord->addTitleStyle(1, array('size' => 16), array('numStyle' => 'hNum', 'numLevel' => 0)); +$phpWord->addTitleStyle(2, array('size' => 14), array('numStyle' => 'hNum', 'numLevel' => 1)); +$phpWord->addTitleStyle(3, array('size' => 12), array('numStyle' => 'hNum', 'numLevel' => 2)); + +$section->addTitle('Heading 1', 1); +$section->addTitle('Heading 2', 2); +$section->addTitle('Heading 3', 3); +``` + +## Add a link within a title + +Apply 'HeadingN' paragraph style to TextRun or Link. Sample code: + +``` php +addTitleStyle(1, array('size' => 16, 'bold' => true)); +$phpWord->addTitleStyle(2, array('size' => 14, 'bold' => true)); +$phpWord->addFontStyle('Link', array('color' => '0000FF', 'underline' => 'single')); + +$section = $phpWord->addSection(); + +// Textrun +$textrun = $section->addTextRun('Heading1'); +$textrun->addText('The '); +$textrun->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord', 'Link'); + +// Link +$section->addLink('https://github.com/', 'GitHub', 'Link', 'Heading2'); +``` + +## Remove [Compatibility Mode] text in the MS Word title bar + +Use the ``Metadata\Compatibility\setOoxmlVersion(n)`` method with ``n`` is the version of Office: + +* 14 = Office 2010 +* 15 = Office 2013 + +``` php +getCompatibility()->setOoxmlVersion(15); +``` diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000000..1398fd90c4 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,115 @@ +# + +![PHPWord](images/phpword.svg) + +PHPWord is a library written in pure PHP that provides a set ofclasses to write to different document file formats, i.e. [Microsoft Office Open XML](http://en.wikipedia.org/wiki/Office_Open_XML)(`.docx`), OASIS [Open Document Format for Office Applications](http://en.wikipedia.org/wiki/OpenDocument) (`.odt`), [Rich Text Format](http://en.wikipedia.org/wiki/Rich_Text_Format) (`.rtf`), [Microsoft Word Binary File](https://en.wikipedia.org/wiki/Doc_(computing)) (`.doc`), HTML (`.html`), and PDF (`.pdf`). + +PHPWord is an open source project licensed under the terms of [LGPL version 3](https://github.com/PHPOffice/PHPWord/blob/master/COPYING.LESSER). PHPWord is aimed to be a high quality software product by incorporating [continuous integration and unit testing](https://github.com/PHPOffice/PHPWord/actions/workflows/php.yml). You can learn more about PHPWord by reading this Developers'Documentation. + + +## Features + +- Set document properties, e.g. title, subject, and creator. +- Create document sections with different settings, e.g. portrait/landscape, page size, and page numbering +- Create header and footer for each sections +- Set default font type, font size, and paragraph style +- Use UTF-8 and East Asia fonts/characters +- Define custom font styles (e.g. bold, italic, color) and paragraph styles (e.g. centered, multicolumns, spacing) either as named style or inline in text +- Insert paragraphs, either as a simple text or complex one (a text run) that contains other elements +- Insert titles (headers) and table of contents +- Insert text breaks and page breaks +- Insert and format images, either local, remote, or as page watermarks +- Insert binary OLE Objects such as Excel or Visio +- Insert and format table with customized properties for each rows (e.g. repeat as header row) and cells (e.g. background color, rowspan, colspan) +- Insert list items as bulleted, numbered, or multilevel +- Insert hyperlinks +- Insert footnotes and endnotes +- Insert drawing shapes (arc, curve, line, polyline, rect, oval) +- Insert charts (pie, doughnut, bar, line, area, scatter, radar) +- Insert form fields (textinput, checkbox, and dropdown) +- Create document from templates +- Use XSL 1.0 style sheets to transform headers, main document part, and footers of an OOXML template +- ... and many more features on progress + +## File formats + +Below are the supported features for each file formats. + + +### Writers + + +| Features | | OOXML | ODF | RTF | HTML | PDF | +|---------------------------|----------------------|--------|-------|-------|--------|--------| +| **Document Properties** | Standard | :material-check: | :material-check: | :material-check: | :material-check: | :material-check: | +| | Custom | :material-check: | :material-check: | | | | +| **Element Type** | Text | :material-check: | :material-check: | :material-check: | :material-check: | :material-check: | +| | Text Run | :material-check: | :material-check: | :material-check: | :material-check: | :material-check: | +| | Title | :material-check: | :material-check: | | :material-check: | :material-check: | +| | Link | :material-check: | :material-check: | :material-check: | :material-check: | :material-check: | +| | Preserve Text | :material-check: | | | | | +| | Text Break | :material-check: | :material-check: | :material-check: | :material-check: | :material-check: | +| | Page Break | :material-check: | | :material-check: | | | +| | List | :material-check: | | | | | +| | Table | :material-check: | :material-check: | :material-check: | :material-check: | :material-check: | +| | Image | :material-check: | :material-check: | :material-check: | :material-check: | | +| | Object | :material-check: | | | | | +| | Watermark | :material-check: | | | | | +| | Table of Contents | :material-check: | | | | | +| | Header | :material-check: | | | | | +| | Footer | :material-check: | | | | | +| | Footnote | :material-check: | | | :material-check: | | +| | Endnote | :material-check: | | | :material-check: | | +| | Comments | :material-check: | | | | | +| **Graphs** | 2D basic graphs | :material-check: | | | | | +| | 2D advanced graphs | | | | | | +| | 3D graphs | :material-check: | | | | | +| **Math** | OMML support | | | | | | +| | MathML support | | | | | | +| **Bonus** | Encryption | | | | | | +| | Protection | | | | | | + +### Readers + + +| Features | | OOXML | DOC | ODF | RTF | HTML | +|---------------------------|----------------------|--------|-------|-------|-------|-------| +| **Document Properties** | Standard | :material-check: | | | | | +| | Custom | :material-check: | | | | | +| **Element Type** | Text | :material-check: | :material-check: | :material-check: | :material-check: | :material-check: | +| | Text Run | :material-check: | | | | | +| | Title | :material-check: | | :material-check: | | | +| | Link | :material-check: | :material-check: | | | | +| | Preserve Text | :material-check: | | | | | +| | Text Break | :material-check: | :material-check: | | | | +| | Page Break | :material-check: | | | | | +| | List | :material-check: | | :material-check: | | :material-check: | +| | Table | :material-check: | | | | :material-check: | +| | Image | :material-check: | :material-check: | | | | +| | Object | | | | | | +| | Watermark | | | | | | +| | Table of Contents | | | | | | +| | Header | :material-check: | | | | | +| | Footer | :material-check: | | | | | +| | Footnote | :material-check: | | | | | +| | Endnote | :material-check: | | | | | +| | Comments | | | | | | +| **Graphs** | 2D basic graphs | | | | | | +| | 2D advanced graphs | | | | | | +| | 3D graphs | | | | | | +| **Math** | OMML support | | | | | | +| | MathML support | | | | | | +| **Bonus** | Encryption | | | | | | +| | Protection | | | | | | + + +## Contributing + +We welcome everyone to contribute to PHPWord. Below are some of the things that you can do to contribute: + +- Read [our contributing guide](https://github.com/PHPOffice/PHPWord/blob/master/CONTRIBUTING.md) +- [Fork us](https://github.com/PHPOffice/PHPWord/fork) and [request a pull](https://github.com/PHPOffice/PHPWord/pulls) to the [master](https://github.com/PHPOffice/PHPWord/tree/master) branch +- Submit [bug reports or feature requests](https://github.com/PHPOffice/PHPWord/issues) to GitHub +- Follow [@PHPOffice](https://twitter.com/PHPOffice) on Twitter diff --git a/docs/index.rst b/docs/index.rst deleted file mode 100644 index 671c32a64c..0000000000 --- a/docs/index.rst +++ /dev/null @@ -1,40 +0,0 @@ -.. PHPWord documentation master file, created by - sphinx-quickstart on Fri Mar 14 23:09:26 2014. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to PHPWord's documentation -================================== - -|PHPWord| - -PHPWord is a library written in pure PHP that provides a set of classes to -write to and read from different document file formats. The current version of -PHPWord supports Microsoft Office Open XML (OOXML or OpenXML), OASIS Open -Document Format for Office Applications (OpenDocument or ODF), and Rich Text -Format (RTF). - -.. toctree:: - :maxdepth: 2 - - intro - installing - general - containers - elements - styles - templates-processing - writersreaders - recipes - faq - credits - references - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - -.. |PHPWord| image:: images/phpword.png diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 0000000000..1b54a3173f --- /dev/null +++ b/docs/install.md @@ -0,0 +1,52 @@ +# Installation + +## Requirements + +Mandatory: + +- PHP 7.1+ +- PHP [DOM extension](http://php.net/manual/en/book.dom.php) +- PHP [JSON extension](http://php.net/manual/en/book.json.php) +- PHP [XML Parser extension](http://www.php.net/manual/en/xml.installation.php) +- PHP [XMLWriter extension](http://php.net/manual/en/book.xmlwriter.php) + + +## Installation + +There are two ways to install PHPWord, i.e. via [Composer](http://getcomposer.org) or manually by downloading the library. + +### Using Composer + +To install via Composer, add the following lines to your `composer.json`: + +``` json +{ + "require": { + "phpoffice/phpword": "dev-master" + } +} +``` + + +### Using manual install +To install manually: + +* [download PHPOffice\PHPWord package from GitHub](https://github.com/PHPOffice/PHPWord/archive/master.zip) +* [download PHPOffice\Common package from GitHub](https://github.com/PHPOffice/Common/archive/master.zip) +* extract the package and put the contents to your machine. + + +``` php +`__ extension - -Optional: - -- `Zip `__ extension -- `GD `__ extension -- `XMLWriter `__ extension -- `XSL `__ extension -- `dompdf `__ library - -Installation ------------- - -PHPWord is installed via `Composer `__. -You just need to `add dependency `__ on PHPWord into your package. - -Example: - -.. code-block:: bash - - composer require phpoffice/phpword - -If you are a developer or if you want to help us with testing then fetch the latest branch for developers. -Notice: all contributions must be done against the developer branch. - -Example: - -.. code-block:: bash - - composer require phpoffice/phpword:dev-master - -Using samples -------------- - -More examples are provided in the ``samples`` directory. -For an easy access to those samples launch ``php -S localhost:8000`` in the samples directory then browse to http://localhost:8000 to view the samples. diff --git a/docs/intro.rst b/docs/intro.rst deleted file mode 100644 index 94cc48d19e..0000000000 --- a/docs/intro.rst +++ /dev/null @@ -1,196 +0,0 @@ -.. _intro: - -Introduction -============ - -PHPWord is a library written in pure PHP that provides a set of classes -to write to and read from different document file formats. The current -version of PHPWord supports Microsoft `Office Open -XML `__ (OOXML or -OpenXML), OASIS `Open Document Format for Office -Applications `__ -(OpenDocument or ODF), and `Rich Text -Format `__ (RTF). - -PHPWord is an open source project licensed under the terms of `LGPL -version 3 `__. -PHPWord is aimed to be a high quality software product. -You can learn more about PHPWord by reading this Developers' -Documentation. - -Features --------- - -- Set document properties, e.g. title, subject, and creator. -- Create document sections with different settings, e.g. - portrait/landscape, page size, and page numbering -- Create header and footer for each sections -- Set default font type, font size, and paragraph style -- Use UTF-8 and East Asia fonts/characters -- Define custom font styles (e.g. bold, italic, color) and paragraph - styles (e.g. centered, multicolumns, spacing) either as named style - or inline in text -- Insert paragraphs, either as a simple text or complex one (a text - run) that contains other elements -- Insert titles (headers) and table of contents -- Insert text breaks and page breaks -- Insert right-to-left text -- Insert and format images, either local, remote, or as page watermarks -- Insert binary OLE Objects such as Excel or Visio -- Insert and format table with customized properties for each rows - (e.g. repeat as header row) and cells (e.g. background color, - rowspan, colspan) -- Insert list items as bulleted, numbered, or multilevel -- Insert hyperlinks -- Insert footnotes and endnotes -- Insert drawing shapes (arc, curve, line, polyline, rect, oval) -- Insert charts (pie, doughnut, bar, line, area, scatter, radar) -- Insert form fields (textinput, checkbox, and dropdown) -- Insert comments -- Create document from templates -- Use XSL 1.0 style sheets to transform headers, main document part, and footers of an OOXML template -- ... and many more features on progress - -File formats ------------- - -Below are the supported features for each file formats. - -Writers -~~~~~~~ - -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| Features | | OOXML | ODF | RTF | HTML | PDF | -+===========================+======================+========+=======+=======+========+=======+ -| **Document Properties** | Standard | ✓ | ✓ | ✓ | ✓ | ✓ | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Custom | ✓ | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| **Element Type** | Text | ✓ | ✓ | ✓ | ✓ | ✓ | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Text Run | ✓ | ✓ | ✓ | ✓ | ✓ | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Title | ✓ | ✓ | | ✓ | ✓ | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Link | ✓ | ✓ | ✓ | ✓ | ✓ | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Preserve Text | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Text Break | ✓ | ✓ | ✓ | ✓ | ✓ | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Page Break | ✓ | | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | List | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Table | ✓ | ✓ | ✓ | ✓ | ✓ | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Image | ✓ | ✓ | ✓ | ✓ | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Object | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Watermark | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Table of Contents | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Header | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Footer | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Footnote | ✓ | | | ✓ | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Endnote | ✓ | | | ✓ | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Comments | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| **Graphs** | 2D basic graphs | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | 2D advanced graphs | | | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | 3D graphs | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| **Math** | OMML support | | | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | MathML support | | | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| **Bonus** | Encryption | | | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | Protection | | | | | | -+---------------------------+----------------------+--------+-------+-------+--------+-------+ - -Readers -~~~~~~~ - -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| Features | | OOXML | DOC | ODF | RTF | HTML | -+===========================+======================+========+=======+=======+=======+=======+ -| **Document Properties** | Standard | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Custom | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| **Element Type** | Text | ✓ | ✓ | ✓ | ✓ | ✓ | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Text Run | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Title | ✓ | | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Link | ✓ | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Preserve Text | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Text Break | ✓ | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Page Break | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | List | ✓ | | ✓ | | ✓ | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Table | ✓ | | | | ✓ | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Image | ✓ | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Object | | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Watermark | | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Table of Contents | | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Header | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Footer | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Footnote | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Endnote | ✓ | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Comments | | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| **Graphs** | 2D basic graphs | | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | 2D advanced graphs | | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | 3D graphs | | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| **Math** | OMML support | | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | MathML support | | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| **Bonus** | Encryption | | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ -| | Protection | | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+-------+ - -Contributing ------------- - -We welcome everyone to contribute to PHPWord. Below are some of the -things that you can do to contribute. - -- Read `our contributing - guide `__. -- `Fork us `__ and `request - a pull `__ to the - `master `__ - branch. -- Submit `bug reports or feature - requests `__ to GitHub. -- Follow `@PHPWord `__ and - `@PHPOffice `__ on Twitter. diff --git a/docs/recipes.rst b/docs/recipes.rst deleted file mode 100644 index b470d28615..0000000000 --- a/docs/recipes.rst +++ /dev/null @@ -1,97 +0,0 @@ -.. _recipes: - -Recipes -======= - -Create float left image ------------------------ - -Use absolute positioning relative to margin horizontally and to line vertically. - -.. code-block:: php - - $imageStyle = array( - 'width' => 40, - 'height' => 40, - 'wrappingStyle' => 'square', - 'positioning' => 'absolute', - 'posHorizontalRel' => 'margin', - 'posVerticalRel' => 'line', - ); - $textrun->addImage('resources/_earth.jpg', $imageStyle); - $textrun->addText($lipsumText); - -Download the produced file automatically ----------------------------------------- - -Use ``php://output`` as the filename. - -.. code-block:: php - - $phpWord = new \PhpOffice\PhpWord\PhpWord(); - $section = $phpWord->addSection(); - $section->addText('Hello World!'); - $file = 'HelloWorld.docx'; - header("Content-Description: File Transfer"); - header('Content-Disposition: attachment; filename="' . $file . '"'); - header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document'); - header('Content-Transfer-Encoding: binary'); - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - header('Expires: 0'); - $xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007'); - $xmlWriter->save("php://output"); - -Create numbered headings ------------------------- - -Define a numbering style and title styles, and match the two styles (with ``pStyle`` and ``numStyle``) like below. - -.. code-block:: php - - $phpWord->addNumberingStyle( - 'hNum', - array('type' => 'multilevel', 'levels' => array( - array('pStyle' => 'Heading1', 'format' => 'decimal', 'text' => '%1'), - array('pStyle' => 'Heading2', 'format' => 'decimal', 'text' => '%1.%2'), - array('pStyle' => 'Heading3', 'format' => 'decimal', 'text' => '%1.%2.%3'), - ) - ) - ); - $phpWord->addTitleStyle(1, array('size' => 16), array('numStyle' => 'hNum', 'numLevel' => 0)); - $phpWord->addTitleStyle(2, array('size' => 14), array('numStyle' => 'hNum', 'numLevel' => 1)); - $phpWord->addTitleStyle(3, array('size' => 12), array('numStyle' => 'hNum', 'numLevel' => 2)); - - $section->addTitle('Heading 1', 1); - $section->addTitle('Heading 2', 2); - $section->addTitle('Heading 3', 3); - -Add a link within a title -------------------------- - -Apply 'HeadingN' paragraph style to TextRun or Link. Sample code: - -.. code-block:: php - - $phpWord = new \PhpOffice\PhpWord\PhpWord(); - $phpWord->addTitleStyle(1, array('size' => 16, 'bold' => true)); - $phpWord->addTitleStyle(2, array('size' => 14, 'bold' => true)); - $phpWord->addFontStyle('Link', array('color' => '0000FF', 'underline' => 'single')); - - $section = $phpWord->addSection(); - - // Textrun - $textrun = $section->addTextRun('Heading1'); - $textrun->addText('The '); - $textrun->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord', 'Link'); - - // Link - $section->addLink('https://github.com/', 'GitHub', 'Link', 'Heading2'); - -Remove [Compatibility Mode] text in the MS Word title bar ---------------------------------------------------------- - -Use the ``Metadata\Compatibility\setOoxmlVersion(n)`` method with ``n`` is the version of Office (14 = Office 2010, 15 = Office 2013). - -.. code-block:: php - - $phpWord->getCompatibility()->setOoxmlVersion(15); diff --git a/docs/references.rst b/docs/references.rst deleted file mode 100644 index a17f558db6..0000000000 --- a/docs/references.rst +++ /dev/null @@ -1,28 +0,0 @@ -.. _references: - -References -========== - -ISO/IEC 29500, Third edition, 2012-09-01 ----------------------------------------- - -- `Part 1: Fundamentals and Markup Language Reference - `__ -- `Part 2: Open Packaging Conventions - `__ -- `Part 3: Markup Compatibility and Extensibility - `__ -- `Part 4: Transitional Migration Features - `__ - -Formal specifications ---------------------- - -- `Oasis OpenDocument Standard Version 1.2 `__ -- `Rich Text Format (RTF) Specification, version 1.9.1 `__ - -Other resources ---------------- - -- `DocumentFormat.OpenXml.Wordprocessing Namespace on - MSDN `__ diff --git a/docs/styles.rst b/docs/styles.rst deleted file mode 100644 index 075dd3967d..0000000000 --- a/docs/styles.rst +++ /dev/null @@ -1,213 +0,0 @@ -.. _styles: - -Styles -====== - -.. _section-style: - -Section -------- - -Available Section style options: - -- ``borderBottomColor``. Border bottom color. -- ``borderBottomSize``. Border bottom size in *twip*. -- ``borderLeftColor``. Border left color. -- ``borderLeftSize``. Border left size in *twip*. -- ``borderRightColor``. Border right color. -- ``borderRightSize``. Border right size in *twip*. -- ``borderTopColor``. Border top color. -- ``borderTopSize``. Border top size in *twip*. -- ``breakType``. Section break type (nextPage, nextColumn, continuous, evenPage, oddPage). -- ``colsNum``. Number of columns. -- ``colsSpace``. Spacing between columns. -- ``footerHeight``. Spacing to bottom of footer. -- ``gutter``. Page gutter spacing. -- ``headerHeight``. Spacing to top of header. -- ``marginTop``. Page margin top in *twip*. -- ``marginLeft``. Page margin left in *twip*. -- ``marginRight``. Page margin right in *twip*. -- ``marginBottom``. Page margin bottom in *twip*. -- ``orientation``. Page orientation (``portrait``, which is default, or ``landscape``). - See ``\PhpOffice\PhpWord\Style\Section::ORIENTATION_...`` class constants for possible values -- ``pageSizeH``. Page height in *twip*. Implicitly defined by ``orientation`` option. Any changes are discouraged. -- ``pageSizeW``. Page width in *twip*. Implicitly defined by ``orientation`` option. Any changes are discouraged. -- ``vAlign``. Vertical Page Alignment - See ``\PhpOffice\PhpWord\SimpleType\VerticalJc`` for possible values - -.. _font-style: - -Font ----- - -Available Font style options: - -- ``allCaps``. All caps, *true* or *false*. -- ``bgColor``. Font background color, e.g. *FF0000*. -- ``bold``. Bold, *true* or *false*. -- ``color``. Font color, e.g. *FF0000*. -- ``doubleStrikethrough``. Double strikethrough, *true* or *false*. -- ``fgColor``. Font highlight color, e.g. *yellow*, *green*, *blue*. - See ``\PhpOffice\PhpWord\Style\Font::FGCOLOR_...`` class constants for possible values -- ``hint``. Font content type, *default*, *eastAsia*, or *cs*. -- ``italic``. Italic, *true* or *false*. -- ``name``. Font name, e.g. *Arial*. -- ``rtl``. Right to Left language, *true* or *false*. -- ``size``. Font size, e.g. *20*, *22*. -- ``smallCaps``. Small caps, *true* or *false*. -- ``strikethrough``. Strikethrough, *true* or *false*. -- ``subScript``. Subscript, *true* or *false*. -- ``superScript``. Superscript, *true* or *false*. -- ``underline``. Underline, *single*, *dash*, *dotted*, etc. - See ``\PhpOffice\PhpWord\Style\Font::UNDERLINE_...`` class constants for possible values -- ``lang``. Language, either a language code like *en-US*, *fr-BE*, etc. or an object (or as an array) if you need to set eastAsian or bidirectional languages - 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*. - -.. _paragraph-style: - -Paragraph ---------- - -Available Paragraph style options: - -- ``alignment``. Supports all alignment modes since 1st Edition of ECMA-376 standard up till ISO/IEC 29500:2012. - See ``\PhpOffice\PhpWord\SimpleType\Jc`` class constants for possible values. -- ``basedOn``. Parent style. -- ``hanging``. Hanging indentation in *half inches*. -- ``indent``. Indent (left indentation) in *half inches*. -- ``indentation``. An array of indentation key => value pairs in *twip*. Supports *left*, *right*, *firstLine* and *hanging* indentation. - See ``\PhpOffice\PhpWord\Style\Indentation`` for possible identation types. -- ``keepLines``. Keep all lines on one page, *true* or *false*. -- ``keepNext``. Keep paragraph with next paragraph, *true* or *false*. -- ``lineHeight``. Text line height, e.g. *1.0*, *1.5*, etc. -- ``next``. Style for next paragraph. -- ``pageBreakBefore``. Start paragraph on next page, *true* or *false*. -- ``spaceBefore``. Space before paragraph in *twip*. -- ``spaceAfter``. Space after paragraph in *twip*. -- ``spacing``. Space between lines in *twip*. If spacingLineRule is auto, 240 (height of 1 line) will be added, so if you want a double line height, set this to 240. -- ``spacingLineRule``. Line Spacing Rule. *auto*, *exact*, *atLeast* - See ``\PhpOffice\PhpWord\SimpleType\LineSpacingRule`` class constants for possible values. -- ``suppressAutoHyphens``. Hyphenation for paragraph, *true* or *false*. -- ``tabs``. Set of custom tab stops. -- ``widowControl``. Allow first/last line to display on a separate page, *true* or *false*. -- ``contextualSpacing``. Ignore Spacing Above and Below When Using Identical Styles, *true* or *false*. -- ``bidi``. Right to Left Paragraph Layout, *true* or *false*. -- ``shading``. Paragraph Shading. -- ``textAlignment``. Vertical Character Alignment on Line. - See ``\PhpOffice\PhpWord\SimpleType\TextAlignment`` class constants for possible values. - -.. _table-style: - -Table ------ - -Available Table style options: - -- ``alignment``. Supports all alignment modes since 1st Edition of ECMA-376 standard up till ISO/IEC 29500:2012. - See ``\PhpOffice\PhpWord\SimpleType\JcTable`` and ``\PhpOffice\PhpWord\SimpleType\Jc`` class constants for possible values. -- ``bgColor``. Background color, e.g. '9966CC'. -- ``border(Top|Right|Bottom|Left)Color``. Border color, e.g. '9966CC'. -- ``border(Top|Right|Bottom|Left)Size``. Border size in *twip*. -- ``cellMargin(Top|Right|Bottom|Left)``. Cell margin in *twip*. -- ``indent``. Table indent from leading margin. Must be an instance of ``\PhpOffice\PhpWord\ComplexType\TblWidth``. -- ``width``. Table width in Fiftieths of a Percent or Twentieths of a Point. -- ``unit``. The unit to use for the width. One of ``\PhpOffice\PhpWord\SimpleType\TblWidth``. Defaults to *auto*. -- ``layout``. Table layout, either *fixed* or *autofit* See ``\PhpOffice\PhpWord\Style\Table`` for constants. -- ``cellSpacing`` Cell spacing in *twip* -- ``position`` Floating Table Positioning, see below for options -- ``bidiVisual`` Present table as Right-To-Left - -Floating Table Positioning options: - -- ``leftFromText`` Distance From Left of Table to Text in *twip* -- ``rightFromText`` Distance From Right of Table to Text in *twip* -- ``topFromText`` Distance From Top of Table to Text in *twip* -- ``bottomFromText`` Distance From Top of Table to Text in *twip* -- ``vertAnchor`` Table Vertical Anchor, one of ``\PhpOffice\PhpWord\Style\TablePosition::VANCHOR_*`` -- ``horzAnchor`` Table Horizontal Anchor, one of ``\PhpOffice\PhpWord\Style\TablePosition::HANCHOR_*`` -- ``tblpXSpec`` Relative Horizontal Alignment From Anchor, one of ``\PhpOffice\PhpWord\Style\TablePosition::XALIGN_*`` -- ``tblpX`` Absolute Horizontal Distance From Anchorin *twip* -- ``tblpYSpec`` Relative Vertical Alignment From Anchor, one of ``\PhpOffice\PhpWord\Style\TablePosition::YALIGN_*`` -- ``tblpY`` Absolute Vertical Distance From Anchorin *twip* - -Available Row style options: - -- ``cantSplit``. Table row cannot break across pages, *true* or *false*. -- ``exactHeight``. Row height is exact or at least. -- ``tblHeader``. Repeat table row on every new page, *true* or *false*. - -Available Cell style options: - -- ``bgColor``. Background color, e.g. '9966CC'. -- ``border(Top|Right|Bottom|Left)Color``. Border color, e.g. '9966CC'. -- ``border(Top|Right|Bottom|Left)Size``. Border size in *twip*. -- ``border(Top|Right|Bottom|Left)Style``. Border style. You can use constants from ``\PhpOffice\PhpWord\SimpleType\Border`` -- ``gridSpan``. Number of columns spanned. -- ``textDirection(btLr|tbRl)``. Direction of text. - You can use constants ``\PhpOffice\PhpWord\Style\Cell::TEXT_DIR_BTLR`` and ``\PhpOffice\PhpWord\Style\Cell::TEXT_DIR_TBRL`` -- ``valign``. Vertical alignment, *top*, *center*, *both*, *bottom*. -- ``vMerge``. *restart* or *continue*. -- ``width``. Cell width in *twip*. - -.. _image-style: - -Image ------ - -Available Image style options: - -- ``alignment``. See ``\PhpOffice\PhpWord\SimpleType\Jc`` class for the details. -- ``height``. Height in *pt*. -- ``marginLeft``. Left margin in inches, can be negative. -- ``marginTop``. Top margin in inches, can be negative. -- ``width``. Width in *pt*. -- ``wrappingStyle``. Wrapping style, *inline*, *square*, *tight*, *behind*, or *infront*. -- ``wrapDistanceTop``. Top text wrapping in pixels. -- ``wrapDistanceBottom``. Bottom text wrapping in pixels. -- ``wrapDistanceLeft``. Left text wrapping in pixels. -- ``wrapDistanceRight``. Right text wrapping in pixels. - -.. _numbering-level-style: - -Numbering level ---------------- - -Available NumberingLevel style options: - -- ``alignment``. Supports all alignment modes since 1st Edition of ECMA-376 standard up till ISO/IEC 29500:2012. - See ``\PhpOffice\PhpWord\SimpleType\Jc`` class constants for possible values. -- ``font``. Font name. -- ``format``. Numbering format bullet\|decimal\|upperRoman\|lowerRoman\|upperLetter\|lowerLetter. -- ``hanging``. See paragraph style. -- ``hint``. See font style. -- ``left``. See paragraph style. -- ``restart``. Restart numbering level symbol. -- ``start``. Starting value. -- ``suffix``. Content between numbering symbol and paragraph text tab\|space\|nothing. -- ``tabPos``. See paragraph style. -- ``text``. Numbering level text e.g. %1 for nonbullet or bullet character. - -.. _chart-style: - -Chart ------ - -Available Chart style options: - -- ``width``. Width (in EMU). -- ``height``. Height (in EMU). -- ``3d``. Is 3D; applies to pie, bar, line, area, *true* or *false*. -- ``colors``. A list of colors to use in the chart. -- ``title``. The title for the chart. -- ``showLegend``. Show legend, *true* or *false*. -- ``LegendPosition``. Legend position, *r* (default), *b*, *t*, *l* or *tr*. -- ``categoryLabelPosition``. Label position for categories, *nextTo* (default), *low* or *high*. -- ``valueLabelPosition``. Label position for values, *nextTo* (default), *low* or *high*. -- ``categoryAxisTitle``. The title for the category axis. -- ``valueAxisTitle``. The title for the values axis. -- ``majorTickMarkPos``. The position for major tick marks, *in*, *out*, *cross*, *none* (default). -- ``showAxisLabels``. Show labels for axis, *true* or *false*. -- ``gridX``. Show Gridlines for X-Axis, *true* or *false*. -- ``gridY``. Show Gridlines for Y-Axis, *true* or *false*. diff --git a/docs/templates-processing.rst b/docs/templates-processing.rst deleted file mode 100644 index 1f7f5f2b80..0000000000 --- a/docs/templates-processing.rst +++ /dev/null @@ -1,303 +0,0 @@ -.. _templates-processing: - -Templates processing -==================== - -You can create an OOXML document template with included search-patterns (macros) which can be replaced by any value you wish. Only single-line values can be replaced. -By default Macros are defined like this: ``${search-pattern}`` but you can define custom macros. -To load a template file, create a new instance of the TemplateProcessor. - -.. code-block:: php - - $templateProcessor = new TemplateProcessor('Template.docx'); - -setValue -"""""""" -Given a template containing - -.. code-block:: clean - - Hello ${firstname} ${lastname}! - -The following will replace ``${firstname}`` with ``John``, and ``${lastname}`` with ``Doe`` . -The resulting document will now contain ``Hello John Doe!`` - -.. code-block:: php - - $templateProcessor->setValue('firstname', 'John'); - $templateProcessor->setValue('lastname', 'Doe'); - -setValues -""""""""" -You can also set multiple values by passing all of them in an array. - -.. code-block:: php - - $templateProcessor->setValues(array('firstname' => 'John', 'lastname' => 'Doe')); - -setMacroOpeningChars -"""""""" -You can define a custom opening macro. The following will set ``{#`` as the opening search pattern. - -.. code-block:: php - - $templateProcessor->setMacroOpeningChars('{#'); - -setMacroClosingChars -"""""""" -You can define a custom closing macro. The following will set ``#}`` as the closing search pattern. - -.. code-block:: php - - $templateProcessor->setMacroClosingChars('#}'); - -setMacroChars -"""""""" -You can define a custom opening and closing macro at the same time . The following will set the search-pattern like this: ``{#search-pattern#}`` . - -.. code-block:: php - - $templateProcessor->setMacroChars('{#', '#}'); - -setImageValue -""""""""""""" -The search-pattern model for images can be like: - - ``${search-image-pattern}`` - - ``${search-image-pattern:[width]:[height]:[ratio]}`` - - ``${search-image-pattern:[width]x[height]}`` - - ``${search-image-pattern:size=[width]x[height]}`` - - ``${search-image-pattern:width=[width]:height=[height]:ratio=false}`` - -Where: - - [width] and [height] can be just numbers or numbers with measure, which supported by Word (cm, mm, in, pt, pc, px, %, em, ex) - - [ratio] uses only for ``false``, ``-`` or ``f`` to turn off respect aspect ration of image. By default template image size uses as 'container' size. - -Example: - -.. code-block:: clean - - ${CompanyLogo} - ${UserLogo:50:50} ${Name} - ${City} - ${Street} - -.. code-block:: php - - $templateProcessor = new TemplateProcessor('Template.docx'); - $templateProcessor->setValue('Name', 'John Doe'); - $templateProcessor->setValue(array('City', 'Street'), array('Detroit', '12th Street')); - - $templateProcessor->setImageValue('CompanyLogo', 'path/to/company/logo.png'); - $templateProcessor->setImageValue('UserLogo', array('path' => 'path/to/logo.png', 'width' => 100, 'height' => 100, 'ratio' => false)); - $templateProcessor->setImageValue('FeatureImage', function () { - // Closure will only be executed if the replacement tag is found in the template - - return array('path' => SlowFeatureImageGenerator::make(), 'width' => 100, 'height' => 100, 'ratio' => false); - }); - -cloneBlock -"""""""""" -Given a template containing -See ``Sample_23_TemplateBlock.php`` for an example. - -.. code-block:: clean - - ${block_name} - Customer: ${customer_name} - Address: ${customer_address} - ${/block_name} - -The following will duplicate everything between ``${block_name}`` and ``${/block_name}`` 3 times. - -.. code-block:: php - - $templateProcessor->cloneBlock('block_name', 3, true, true); - -The last parameter will rename any macro defined inside the block and add #1, #2, #3 ... to the macro name. -The result will be - -.. code-block:: clean - - Customer: ${customer_name#1} - Address: ${customer_address#1} - - Customer: ${customer_name#2} - Address: ${customer_address#2} - - Customer: ${customer_name#3} - Address: ${customer_address#3} - -It is also possible to pass an array with the values to replace the marcros with. -If an array with replacements is passed, the ``count`` argument is ignored, it is the size of the array that counts. - -.. code-block:: php - - $replacements = array( - array('customer_name' => 'Batman', 'customer_address' => 'Gotham City'), - array('customer_name' => 'Superman', 'customer_address' => 'Metropolis'), - ); - $templateProcessor->cloneBlock('block_name', 0, true, false, $replacements); - -The result will then be - -.. code-block:: clean - - Customer: Batman - Address: Gotham City - - Customer: Superman - Address: Metropolis - -replaceBlock -"""""""""""" -Given a template containing - -.. code-block:: clean - - ${block_name} - This block content will be replaced - ${/block_name} - -The following will replace everything between ``${block_name}`` and ``${/block_name}`` with the value passed. - -.. code-block:: php - - $templateProcessor->replaceBlock('block_name', 'This is the replacement text.'); - -deleteBlock -""""""""""" -Same as previous, but it deletes the block - -.. code-block:: php - - $templateProcessor->deleteBlock('block_name'); - -cloneRow -"""""""" -Clones a table row in a template document. -See ``Sample_07_TemplateCloneRow.php`` for an example. - -.. code-block:: clean - - +-----------+----------------+ - | ${userId} | ${userName} | - | |----------------+ - | | ${userAddress} | - +-----------+----------------+ - -.. code-block:: php - - $templateProcessor->cloneRow('userId', 2); - -Will result in - -.. code-block:: clean - - +-------------+------------------+ - | ${userId#1} | ${userName#1} | - | |------------------+ - | | ${userAddress#1} | - +-------------+------------------+ - | ${userId#2} | ${userName#2} | - | |------------------+ - | | ${userAddress#2} | - +-------------+------------------+ - -cloneRowAndSetValues -"""""""""""""""""""" -Finds a row in a table row identified by `$search` param and clones it as many times as there are entries in `$values`. - -.. code-block:: clean - - +-----------+----------------+ - | ${userId} | ${userName} | - | |----------------+ - | | ${userAddress} | - +-----------+----------------+ - -.. code-block:: php - - $values = [ - ['userId' => 1, 'userName' => 'Batman', 'userAddress' => 'Gotham City'], - ['userId' => 2, 'userName' => 'Superman', 'userAddress' => 'Metropolis'], - ]; - $templateProcessor->cloneRowAndSetValues('userId', $values); - -Will result in - -.. code-block:: clean - - +---+-------------+ - | 1 | Batman | - | |-------------+ - | | Gotham City | - +---+-------------+ - | 2 | Superman | - | |-------------+ - | | Metropolis | - +---+-------------+ - -applyXslStyleSheet -"""""""""""""""""" -Applies the XSL stylesheet passed to header part, footer part and main part - -.. code-block:: php - - $xslDomDocument = new \DOMDocument(); - $xslDomDocument->load('/path/to/my/stylesheet.xsl'); - $templateProcessor->applyXslStyleSheet($xslDomDocument); - -setComplexValue -""""""""""""""" -Replaces a ${macro} with the ComplexType passed. -See ``Sample_40_TemplateSetComplexValue.php`` for examples. - -.. code-block:: php - - $inline = new TextRun(); - $inline->addText('by a red italic text', array('italic' => true, 'color' => 'red')); - $templateProcessor->setComplexValue('inline', $inline); - -setComplexBlock -""""""""""""""" -Replaces a ${macro} with the ComplexType passed. -See ``Sample_40_TemplateSetComplexValue.php`` for examples. - -.. code-block:: php - - $table = new Table(array('borderSize' => 12, 'borderColor' => 'green', 'width' => 6000, 'unit' => TblWidth::TWIP)); - $table->addRow(); - $table->addCell(150)->addText('Cell A1'); - $table->addCell(150)->addText('Cell A2'); - $table->addCell(150)->addText('Cell A3'); - $table->addRow(); - $table->addCell(150)->addText('Cell B1'); - $table->addCell(150)->addText('Cell B2'); - $table->addCell(150)->addText('Cell B3'); - $templateProcessor->setComplexBlock('table', $table); - -setChartValue -""""""""""""" -Replace a variable by a chart. - -.. code-block:: php - - $categories = array('A', 'B', 'C', 'D', 'E'); - $series1 = array(1, 3, 2, 5, 4); - $chart = new Chart('doughnut', $categories, $series1); - $templateProcessor->setChartValue('myChart', $chart); - -save -"""" -Saves the loaded template within the current directory. Returns the file path. - -.. code-block:: php - - $filepath = $templateProcessor->save(); - -saveAs -"""""" -Saves a copy of the loaded template in the indicated path. - -.. code-block:: php - - $pathToSave = 'path/to/save/file.ext'; - $templateProcessor->saveAs($pathToSave); diff --git a/docs/containers.rst b/docs/usage/containers.md similarity index 59% rename from docs/containers.rst rename to docs/usage/containers.md index 9ee58efcd4..e85a700f48 100644 --- a/docs/containers.rst +++ b/docs/usage/containers.md @@ -1,79 +1,77 @@ -.. _containers: +# Containers -Containers -========== +Containers are objects where you can put elements (texts, lists, tables, etc). There are 3 main containers, i.e. sections, headers, and footers.There are 3 elements that can also act as containers, i.e. textruns, table cells, and footnotes. -Containers are objects where you can put elements (texts, lists, tables, -etc). There are 3 main containers, i.e. sections, headers, and footers. -There are 3 elements that can also act as containers, i.e. textruns, -table cells, and footnotes. +## Sections -Sections --------- +Every visible element in word is placed inside of a section. To create a section, use the following code: -Every visible element in word is placed inside of a section. To create a -section, use the following code: +``` php +addSection($sectionStyle); +``` - $section = $phpWord->addSection($sectionStyle); +The ``$sectionStyle`` is an optional associative array that sets the section. Example: -The ``$sectionStyle`` is an optional associative array that sets the -section. Example: +``` php + 'landscape', + 'marginTop' => 600, + 'colsNum' => 2, +); +``` - $sectionStyle = array( - 'orientation' => 'landscape', - 'marginTop' => 600, - 'colsNum' => 2, - ); - -Page number -~~~~~~~~~~~ +### Page number You can change a section page number by using the ``pageNumberingStart`` style of the section. -.. code-block:: php +``` php +addSection(array('pageNumberingStart' => 1)); +// Method 1 +$section = $phpWord->addSection(array('pageNumberingStart' => 1)); - // Method 2 - $section = $phpWord->addSection(); - $section->getStyle()->setPageNumberingStart(1); +// Method 2 +$section = $phpWord->addSection(); +$section->getStyle()->setPageNumberingStart(1); +``` -Multicolumn -~~~~~~~~~~~ +### Multicolumn You can change a section layout to multicolumn (like in a newspaper) by using the ``breakType`` and ``colsNum`` style of the section. -.. code-block:: php +``` php +addSection(array('breakType' => 'continuous', 'colsNum' => 2)); +// Method 1 +$section = $phpWord->addSection(array('breakType' => 'continuous', 'colsNum' => 2)); - // Method 2 - $section = $phpWord->addSection(); - $section->getStyle()->setBreakType('continuous'); - $section->getStyle()->setColsNum(2); +// Method 2 +$section = $phpWord->addSection(); +$section->getStyle()->setBreakType('continuous'); +$section->getStyle()->setColsNum(2); +``` -Line numbering -~~~~~~~~~~~~~~ +### Line numbering You can apply line numbering to a section by using the ``lineNumbering`` style of the section. -.. code-block:: php +``` php +addSection(array('lineNumbering' => array())); +// Method 1 +$section = $phpWord->addSection(array('lineNumbering' => array())); - // Method 2 - $section = $phpWord->addSection(); - $section->getStyle()->setLineNumbering(array()); +// Method 2 +$section = $phpWord->addSection(); +$section->getStyle()->setLineNumbering(array()); +``` Below are the properties of the line numbering style. @@ -83,15 +81,16 @@ Below are the properties of the line numbering style. - ``restart`` Line numbering restart setting continuous\|newPage\|newSection -Headers -------- +## Headers Each section can have its own header reference. To create a header use the ``addHeader`` method: -.. code-block:: php +``` php +addHeader(); +$header = $section->addHeader(); +``` Be sure to save the result in a local object. You can use all elements that are available for the footer. See "Footer" section for detail. @@ -106,19 +105,22 @@ You can pass an optional parameter to specify where the header/footer should be To change the evenAndOddHeaders use the ``getSettings`` method to return the Settings object, and then call the ``setEvenAndOddHeaders`` method: -.. code-block:: php +``` php +getSettings()->setEvenAndOddHeaders(true); +$phpWord->getSettings()->setEvenAndOddHeaders(true); +``` -Footers -------- +## Footers Each section can have its own footer reference. To create a footer, use the ``addFooter`` method: -.. code-block:: php +``` php +addFooter(); +$footer = $section->addFooter(); +``` Be sure to save the result in a local object to add elements to a footer. You can add the following elements to footers: @@ -131,8 +133,7 @@ footer. You can add the following elements to footers: See the "Elements" section for the detail of each elements. -Other containers ----------------- +### Other containers Textruns, table cells, and footnotes are elements that can also act as containers. See the corresponding "Elements" section for the detail of diff --git a/docs/usage/elements/chart.md b/docs/usage/elements/chart.md new file mode 100644 index 0000000000..d204425b18 --- /dev/null +++ b/docs/usage/elements/chart.md @@ -0,0 +1,15 @@ +# Chart + +Charts can be added using + +``` php +addChart('line', $categories, $series, $style); +``` + +For available styling options, see [`Styles > Chart`](../styles/chart.md). + +Check out the Sample_32_Chart.php for more options and styling. \ No newline at end of file diff --git a/docs/usage/elements/checkbox.md b/docs/usage/elements/checkbox.md new file mode 100644 index 0000000000..67c58163d1 --- /dev/null +++ b/docs/usage/elements/checkbox.md @@ -0,0 +1,14 @@ +# Checkbox + +Checkbox elements can be added to sections or table cells by using ``addCheckBox``. + +``` php +addCheckBox($name, $text, [$fontStyle], [$paragraphStyle]); +``` + +- ``$name``. Name of the check box. +- ``$text``. Text to be displayed in the document. +- ``$fontStyle``. See [`Styles > Font`](../styles/font.md). +- ``$paragraphStyle``. See [`Styles > Paragraph`](../styles/paragraph.md). \ No newline at end of file diff --git a/docs/usage/elements/comment.md b/docs/usage/elements/comment.md new file mode 100644 index 0000000000..06a3866a3e --- /dev/null +++ b/docs/usage/elements/comment.md @@ -0,0 +1,23 @@ +# Comment + +Comments can be added to a document by using ``addComment``. +The comment can contain formatted text. Once the comment has been added, it can be linked to any element with ``setCommentStart``. + +``` php +addText('Test', array('bold' => true)); + +// add it to the document +$phpWord->addComment($comment); + +$textrun = $section->addTextRun(); +$textrun->addText('This '); +$text = $textrun->addText('is'); +// link the comment to the text you just created +$text->setCommentStart($comment); +``` + +If no end is set for a comment using the ``setCommentEnd``, the comment will be ended automatically at the end of the element it is started on. \ No newline at end of file diff --git a/docs/usage/elements/field.md b/docs/usage/elements/field.md new file mode 100644 index 0000000000..10492cc742 --- /dev/null +++ b/docs/usage/elements/field.md @@ -0,0 +1,39 @@ +# Field + +Currently the following fields are supported: + +- PAGE +- NUMPAGES +- DATE +- XE +- INDEX + +``` php +addField($fieldType, [$properties], [$options], [$fieldText], [$fontStyle]) +``` + +- ``$fontStyle``. See [`Styles > Font`](../styles/font.md). + +See ``\PhpOffice\PhpWord\Element\Field`` for list of properties and options available for each field type. +Options which are not specifically defined can be added. Those must start with a ``\``. + +For instance for the INDEX field, you can do the following (See `Index Field for list of available options `_ ): + +``` php +addText('My '); +$fieldText->addText('bold index', ['bold' => true]); +$fieldText->addText(' entry'); +$section->addField('XE', array(), array(), $fieldText); + +//this actually adds the index +$section->addField('INDEX', array(), array('\\e " " \\h "A" \\c "3"'), 'right click to update index'); +``` \ No newline at end of file diff --git a/docs/usage/elements/image.md b/docs/usage/elements/image.md new file mode 100644 index 0000000000..cb288bbf3d --- /dev/null +++ b/docs/usage/elements/image.md @@ -0,0 +1,36 @@ +# Image + +To add an image, use the ``addImage`` method to sections, headers, footers, textruns, or table cells. + +``` php +addImage($src, [$style]); +``` + +- ``$src``. String path to a local image, URL of a remote image or the image data, as a string. Warning: Do not pass user-generated strings here, as that would allow an attacker to read arbitrary files or perform server-side request forgery by passing file paths or URLs instead of image data. +- ``$style``. See [`Styles > Image`](../styles/image.md). + +Examples: + +``` php +addSection(); +$section->addImage( + 'mars.jpg', + array( + 'width' => 100, + 'height' => 100, + 'marginTop' => -1, + 'marginLeft' => -1, + 'wrappingStyle' => 'behind' + ) +); +$footer = $section->addFooter(); +$footer->addImage('http://example.com/image.php'); +$textrun = $section->addTextRun(); +$textrun->addImage('http://php.net/logo.jpg'); +$source = file_get_contents('/path/to/my/images/earth.jpg'); +$textrun->addImage($source); +``` \ No newline at end of file diff --git a/docs/usage/elements/index.md b/docs/usage/elements/index.md new file mode 100644 index 0000000000..6106c8914b --- /dev/null +++ b/docs/usage/elements/index.md @@ -0,0 +1,34 @@ +# Elements + +Below are the matrix of element availability in each container. The column shows the containers while the rows lists the elements. + +| Num | Element | Section | Header | Footer | Cell | Text Run | Footnote | +|-------|-----------------|-----------|----------|----------|---------|------------|------------| +| 1 | [Text](text.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| 2 | Text Run | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :red_circle: | :red_circle: | +| 3 | [Link](link.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| 4 | [Title](title.md) | :white_check_mark: | :question: | :question: | :question: | :question: | :question: | +| 5 | [Preserve Text](preservetext.md) | :question: | :white_check_mark: | :white_check_mark: | :material-check-decagram-outline: | :red_circle: | :red_circle: | +| 6 | [Text Break](textbreak.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| 7 | [Page Break](pagebreak.md) | :white_check_mark: | :red_circle: | :red_circle: | :red_circle: | :red_circle: | :red_circle: | +| 8 | [List](list.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :red_circle: | :red_circle: | +| 9 | [Table](table.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :red_circle: | :red_circle: | +| 10 | [Image](image.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| 11 | [Watermark](watermark.md) | :red_circle: | :white_check_mark: | :red_circle: | :red_circle: | :red_circle: | :red_circle: | +| 12 | [OLEObject](oleobject.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| 13 | [TOC](toc.md) | :white_check_mark: | :red_circle: | :red_circle: | :red_circle: | :red_circle: | :red_circle: | +| 14 | [Footnote](note.md) | :white_check_mark: | :red_circle: | :red_circle: | :material-check-decagram: | :material-check-decagram: | :red_circle: | +| 15 | [Endnote](note.md) | :white_check_mark: | :red_circle: | :red_circle: | :material-check-decagram: | :material-check-decagram: | :red_circle: | +| 16 | [CheckBox](checkbox.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :red_circle: | +| 17 | [TextBox](textbox.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :red_circle: | :red_circle: | +| 18 | [Field](field.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| 19 | [Line](line.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| 20 | [Chart](chart.md) | :white_check_mark: | | | :white_check_mark: | | | + +Legend: + +- :white_check_mark: : Available. +- :material-check-decagram-outline: : Available only when inside header/footer. +- :material-check-decagram: : Available only when inside section. +- :red_circle: : Not available. +- :question: : Should be available. \ No newline at end of file diff --git a/docs/usage/elements/line.md b/docs/usage/elements/line.md new file mode 100644 index 0000000000..7062f884da --- /dev/null +++ b/docs/usage/elements/line.md @@ -0,0 +1,21 @@ +# Line + +Line elements can be added to sections by using ``addLine``. + +``` php + 1, 'width' => 100, 'height' => 0, 'color' => 635552); +$section->addLine($lineStyle); +``` + +Available line style attributes: + +- ``weight``. Line width in *twip*. +- ``color``. Defines the color of stroke. +- ``dash``. Line types: dash, rounddot, squaredot, dashdot, longdash, longdashdot, longdashdotdot. +- ``beginArrow``. Start type of arrow: block, open, classic, diamond, oval. +- ``endArrow``. End type of arrow: block, open, classic, diamond, oval. +- ``width``. Line-object width in *pt*. +- ``height``. Line-object height in *pt*. +- ``flip``. Flip the line element: true, false. \ No newline at end of file diff --git a/docs/usage/elements/link.md b/docs/usage/elements/link.md new file mode 100644 index 0000000000..0719c1c018 --- /dev/null +++ b/docs/usage/elements/link.md @@ -0,0 +1,14 @@ +# Link + +You can add Hyperlinks to the document by using the function addLink: + +``` php +addLink($linkSrc, [$linkName], [$fontStyle], [$paragraphStyle]); +``` + +- ``$linkSrc``. The URL of the link. +- ``$linkName``. Placeholder of the URL that appears in the document. +- ``$fontStyle``. See [`Styles > Font`](../styles/font.md). +- ``$paragraphStyle``. See [`Styles > Paragraph`](../styles/paragraph.md). \ No newline at end of file diff --git a/docs/usage/elements/list.md b/docs/usage/elements/list.md new file mode 100644 index 0000000000..4b51cd8634 --- /dev/null +++ b/docs/usage/elements/list.md @@ -0,0 +1,48 @@ +# List + +Lists can be added by using ``addListItem`` and ``addListItemRun`` methods. ``addListItem`` is used for creating lists that only contain plain text. ``addListItemRun`` is used for creating complex list items that contains texts with different style (some bold, other italics, etc) or other elements, e.g. images or links. The syntaxes are as follow: + +Basic usage: + +``` php +addListItem($text, [$depth], [$fontStyle], [$listStyle], [$paragraphStyle]); +$listItemRun = $section->addListItemRun([$depth], [$listStyle], [$paragraphStyle]) +``` + +Parameters: + +- ``$text``. Text that appears in the document. +- ``$depth``. Depth of list item. +- ``$fontStyle``. See [`Styles > Font`](../styles/font.md).. +- ``$listStyle``. List style of the current element TYPE\_NUMBER, + TYPE\_ALPHANUM, TYPE\_BULLET\_FILLED, etc. See list of constants in PHPWord\\Style\\ListItem. +- ``$paragraphStyle``. See [`Styles > Paragraph`](../styles/paragraph.md).. + +See ``Sample_14_ListItem.php`` for more code sample. + +Advanced usage: + +You can also create your own numbering style by changing the ``$listStyle`` parameter with the name of your numbering style. + +``` php +addNumberingStyle( + 'multilevel', + array( + 'type' => 'multilevel', + 'levels' => array( + array('format' => 'decimal', 'text' => '%1.', 'left' => 360, 'hanging' => 360, 'tabPos' => 360), + array('format' => 'upperLetter', 'text' => '%2.', 'left' => 720, 'hanging' => 360, 'tabPos' => 720), + ) + ) +); +$section->addListItem('List Item I', 0, null, 'multilevel'); +$section->addListItem('List Item I.a', 1, null, 'multilevel'); +$section->addListItem('List Item I.b', 1, null, 'multilevel'); +$section->addListItem('List Item II', 0, null, 'multilevel'); +``` + +For available styling options see [`Styles > Numbering Level`](../styles/numberinglevel.md). \ No newline at end of file diff --git a/docs/usage/elements/note.md b/docs/usage/elements/note.md new file mode 100644 index 0000000000..69a1947357 --- /dev/null +++ b/docs/usage/elements/note.md @@ -0,0 +1,54 @@ +# Footnote & Endnote + +You can create footnotes with ``addFootnote`` and endnotes with``addEndnote`` in texts or textruns, but it's recommended to use textrun to have better layout. You can use ``addText``, ``addLink``,``addTextBreak``, ``addImage``, ``addOLEObject`` on footnotes and endnotes. + +On textrun: + +``` php +addTextRun(); +$textrun->addText('Lead text.'); +$footnote = $textrun->addFootnote(); +$footnote->addText('Footnote text can have '); +$footnote->addLink('http://test.com/', 'links'); +$footnote->addText('.'); +$footnote->addTextBreak(); +$footnote->addText('And text break.'); +$textrun->addText('Trailing text.'); +$endnote = $textrun->addEndnote(); +$endnote->addText('Endnote put at the end'); +``` + +On text: + +``` php +addText('Lead text.'); +$footnote = $section->addFootnote(); +$footnote->addText('Footnote text.'); +``` + +By default the footnote reference number will be displayed with decimal number +starting from 1. This number uses the ``FooterReference`` style which you can +redefine with the ``addFontStyle`` method. Default value for this style is +``array('superScript' => true)``; + +The footnote numbering can be controlled by setting the FootnoteProperties on the Section. + +``` php +setPos(\PhpOffice\PhpWord\ComplexType\FootnoteProperties::POSITION_BENEATH_TEXT); +//set the number format to use (decimal (default), upperRoman, upperLetter, ...) +$fp->setNumFmt(\PhpOffice\PhpWord\SimpleType\NumberFormat::LOWER_ROMAN); +//force starting at other than 1 +$fp->setNumStart(2); +//when to restart counting (continuous (default), eachSect, eachPage) +$fp->setNumRestart(\PhpOffice\PhpWord\ComplexType\FootnoteProperties::RESTART_NUMBER_EACH_PAGE); +//And finaly, set it on the Section +$section->setFootnoteProperties($fp); +``` \ No newline at end of file diff --git a/docs/usage/elements/oleobject.md b/docs/usage/elements/oleobject.md new file mode 100644 index 0000000000..ebee5fbafa --- /dev/null +++ b/docs/usage/elements/oleobject.md @@ -0,0 +1,9 @@ +# Object + +You can add OLE embeddings, such as Excel spreadsheets or PowerPoint presentations to the document by using ``addOLEObject`` method. + +``` php +addOLEObject($src, [$style]); +``` \ No newline at end of file diff --git a/docs/usage/elements/pagebreak.md b/docs/usage/elements/pagebreak.md new file mode 100644 index 0000000000..12f0fad57b --- /dev/null +++ b/docs/usage/elements/pagebreak.md @@ -0,0 +1,9 @@ +# Page breaks + +There are two ways to insert a page break, using the ``addPageBreak`` method or using the ``pageBreakBefore`` style of paragraph. + +``` php +addPageBreak(); +``` \ No newline at end of file diff --git a/docs/usage/elements/preservetext.md b/docs/usage/elements/preservetext.md new file mode 100644 index 0000000000..67a9cb0920 --- /dev/null +++ b/docs/usage/elements/preservetext.md @@ -0,0 +1,9 @@ +# Preserve text + +The ``addPreserveText`` method is used to add a page number or page count to headers or footers. + +``` php +addPreserveText('Page {PAGE} of {NUMPAGES}.'); +``` \ No newline at end of file diff --git a/docs/usage/elements/table.md b/docs/usage/elements/table.md new file mode 100644 index 0000000000..04b06429e7 --- /dev/null +++ b/docs/usage/elements/table.md @@ -0,0 +1,41 @@ +# Table + +To add tables, rows, and cells, use the ``addTable``, ``addRow``, and ``addCell`` methods: + +``` php +addTable([$tableStyle]); +$table->addRow([$height], [$rowStyle]); +$cell = $table->addCell($width, [$cellStyle]); +``` + +Table style can be defined with ``addTableStyle``: + +``` php + '006699', + 'borderSize' => 6, + 'cellMargin' => 50 +); +$firstRowStyle = array('bgColor' => '66BBFF'); +$phpWord->addTableStyle('myTable', $tableStyle, $firstRowStyle); +$table = $section->addTable('myTable'); +``` + +For available styling options see [`Styles > Table`](../styles/table.md). + +## Cell span + +You can span a cell on multiple columns by using ``gridSpan`` or multiple rows by using ``vMerge``. + +``` php +addCell(200); +$cell->getStyle()->setGridSpan(5); +``` + +See ``Sample_09_Tables.php`` for more code sample. \ No newline at end of file diff --git a/docs/usage/elements/text.md b/docs/usage/elements/text.md new file mode 100644 index 0000000000..41984be095 --- /dev/null +++ b/docs/usage/elements/text.md @@ -0,0 +1,26 @@ +# Text + + +Text can be added by using ``addText`` and ``addTextRun`` methods. ``addText`` is used for creating simple paragraphs that only contain texts with the same style. ``addTextRun`` is used for creating complex paragraphs that contain text with different style (some bold, other italics, etc) or other elements, e.g. images or links. The syntaxes are as follow: + +``` php +addText($text, [$fontStyle], [$paragraphStyle]); +$textrun = $section->addTextRun([$paragraphStyle]); +``` + +- ``$text``. Text to be displayed in the document. +- ``$fontStyle``. See [`Styles > Font`](../styles/font.md). +- ``$paragraphStyle``. See [`Styles > Paragraph`](../styles/paragraph.md). + +For available styling options, see [`Styles > Font`](../styles/font.md) and [`Styles > Paragraph`](../styles/paragraph.md). + +If you want to enable track changes on added text you can mark it as INSERTED or DELETED by a specific user at a given time: + +``` php +addText('Hello World!'); +$text->setChanged(\PhpOffice\PhpWord\Element\ChangedElement::TYPE_INSERTED, 'Fred', (new \DateTime())); +``` \ No newline at end of file diff --git a/docs/usage/elements/textbox.md b/docs/usage/elements/textbox.md new file mode 100644 index 0000000000..9341cdcbd9 --- /dev/null +++ b/docs/usage/elements/textbox.md @@ -0,0 +1,3 @@ +# TextBox + +To Be Completed... \ No newline at end of file diff --git a/docs/usage/elements/textbreak.md b/docs/usage/elements/textbreak.md new file mode 100644 index 0000000000..1937101cc8 --- /dev/null +++ b/docs/usage/elements/textbreak.md @@ -0,0 +1,13 @@ +# Text breaks + +Text breaks are empty new lines. To add text breaks, use the following syntax. All parameters are optional. + +``` php +addTextBreak([$breakCount], [$fontStyle], [$paragraphStyle]); +``` + +- ``$breakCount``. How many lines. +- ``$fontStyle``. See [`Styles > Font`](../styles/font.md). +- ``$paragraphStyle``. See [`Styles > Paragraph`](../styles/paragraph.md). \ No newline at end of file diff --git a/docs/usage/elements/title.md b/docs/usage/elements/title.md new file mode 100644 index 0000000000..f778d6ddb7 --- /dev/null +++ b/docs/usage/elements/title.md @@ -0,0 +1,19 @@ +# Title + +If you want to structure your document or build table of contents, you need titles or headings. +To add a title to the document, use the ``addTitleStyle`` and ``addTitle`` method. +If `depth` is 0, a Title will be inserted, otherwise a Heading1, Heading2, ... + +``` php +addTitleStyle($depth, [$fontStyle], [$paragraphStyle]); +$section->addTitle($text, [$depth]); +``` + +- ``depth``. +- ``$fontStyle``. See [`Styles > Font`](../styles/font.md). +- ``$paragraphStyle``. See [`Styles > Paragraph`](../styles/paragraph.md). +- ``$text``. Text to be displayed in the document. This can be `string` or a `\PhpOffice\PhpWord\Element\TextRun` + +It's necessary to add a title style to your document because otherwise the title won't be detected as a real title. \ No newline at end of file diff --git a/docs/usage/elements/toc.md b/docs/usage/elements/toc.md new file mode 100644 index 0000000000..d7b05c2e96 --- /dev/null +++ b/docs/usage/elements/toc.md @@ -0,0 +1,21 @@ +# Table of contents + +To add a table of contents (TOC), you can use the ``addTOC`` method. +Your TOC can only be generated if you have add at least one title (See "[Title](title.md)"). + +``` php +addTOC([$fontStyle], [$tocStyle], [$minDepth], [$maxDepth]); +``` + +- ``$fontStyle``. See font style section. +- ``$tocStyle``. See available options below. +- ``$minDepth``. Minimum depth of header to be shown. Default 1. +- ``$maxDepth``. Maximum depth of header to be shown. Default 9. + +Options for ``$tocStyle``: + +- ``tabLeader``. Fill type between the title text and the page number. Use the defined constants in ``\PhpOffice\PhpWord\Style\TOC``. +- ``tabPos``. The position of the tab where the page number appears in *twip*. +- ``indent``. The indent factor of the titles in *twip*. \ No newline at end of file diff --git a/docs/usage/elements/trackchanges.md b/docs/usage/elements/trackchanges.md new file mode 100644 index 0000000000..70cd312543 --- /dev/null +++ b/docs/usage/elements/trackchanges.md @@ -0,0 +1,25 @@ +# Track Changes + +Track changes can be set on text elements. There are 2 ways to set the change information on an element. +Either by calling the `setChangeInfo()`, or by setting the `TrackChange` instance on the element with `setTrackChange()`. + +``` php +addSection(); +$textRun = $section->addTextRun(); + +$text = $textRun->addText('Hello World! Time to '); + +$text = $textRun->addText('wake ', array('bold' => true)); +$text->setChangeInfo(TrackChange::INSERTED, 'Fred', time() - 1800); + +$text = $textRun->addText('up'); +$text->setTrackChange(new TrackChange(TrackChange::INSERTED, 'Fred')); + +$text = $textRun->addText('go to sleep'); +$text->setChangeInfo(TrackChange::DELETED, 'Barney', new \DateTime('@' . (time() - 3600))); +``` \ No newline at end of file diff --git a/docs/usage/elements/watermark.md b/docs/usage/elements/watermark.md new file mode 100644 index 0000000000..0b2bae6bf0 --- /dev/null +++ b/docs/usage/elements/watermark.md @@ -0,0 +1,13 @@ +# Watermark + +To add a watermark (or page background image), your section needs a +header reference. After creating a header, you can use the +``addWatermark`` method to add a watermark. + +``` php +addSection(); +$header = $section->addHeader(); +$header->addWatermark('resources/_earth.jpg', array('marginTop' => 200, 'marginLeft' => 55)); +``` \ No newline at end of file diff --git a/docs/usage/introduction.md b/docs/usage/introduction.md new file mode 100644 index 0000000000..94a6fd915d --- /dev/null +++ b/docs/usage/introduction.md @@ -0,0 +1,356 @@ +# Introduction + +## Basic example + +The following is a basic example of the PHPWord library. More examples +are provided in the [samples folder](https://github.com/PHPOffice/PHPWord/tree/master/samples/). + +``` php +addSection(); +// Adding Text element to the Section having font styled by default... +$section->addText( + '"Learn from yesterday, live for today, hope for tomorrow. ' + . 'The important thing is not to stop questioning." ' + . '(Albert Einstein)' +); + +/* + * Note: it's possible to customize font style of the Text element you add in three ways: + * - inline; + * - using named font style (new font style object will be implicitly created); + * - using explicitly created font style object. + */ + +// Adding Text element with font customized inline... +$section->addText( + '"Great achievement is usually born of great sacrifice, ' + . 'and is never the result of selfishness." ' + . '(Napoleon Hill)', + array('name' => 'Tahoma', 'size' => 10) +); + +// Adding Text element with font customized using named font style... +$fontStyleName = 'oneUserDefinedStyle'; +$phpWord->addFontStyle( + $fontStyleName, + array('name' => 'Tahoma', 'size' => 10, 'color' => '1B2232', 'bold' => true) +); +$section->addText( + '"The greatest accomplishment is not in never falling, ' + . 'but in rising again after you fall." ' + . '(Vince Lombardi)', + $fontStyleName +); + +// Adding Text element with font customized using explicitly created font style object... +$fontStyle = new \PhpOffice\PhpWord\Style\Font(); +$fontStyle->setBold(true); +$fontStyle->setName('Tahoma'); +$fontStyle->setSize(13); +$myTextElement = $section->addText('"Believe you can and you\'re halfway there." (Theodor Roosevelt)'); +$myTextElement->setFontStyle($fontStyle); + +// Saving the document as OOXML file... +$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007'); +$objWriter->save('helloWorld.docx'); + +// Saving the document as ODF file... +$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'ODText'); +$objWriter->save('helloWorld.odt'); + +// Saving the document as HTML file... +$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'HTML'); +$objWriter->save('helloWorld.html'); + +/* Note: we skip RTF, because it's not XML-based and requires a different example. */ +/* Note: we skip PDF, because "HTML-to-PDF" approach is used to create PDF documents. */ +``` + +## PHPWord Settings + +The ``PhpOffice\PhpWord\Settings`` class provides some options that will +affect the behavior of PHPWord. Below are the options. + +### XML Writer compatibility + +This option sets [XMLWriter::setIndent](http://www.php.net/manual/en/function.xmlwriter-set-indent.php) and [XMLWriter::setIndentString](http://www.php.net/manual/en/function.xmlwriter-set-indent-string.php>). The default value of this option is ``true`` (compatible), which is [required for OpenOffice](https://github.com/PHPOffice/PHPWord/issues/103) to render OOXML document correctly. You can set this option to ``false`` during development to make the resulting XML file easier to read. + +``` php +setDefaultFontName('Times New Roman'); +$phpWord->setDefaultFontSize(12); +``` + +## Document settings + +Settings for the generated document can be set using ``$phpWord->getSettings()`` + +### Magnification Setting + +The default zoom value is 100 percent. This can be changed either to another percentage + +``` php +getSettings()->setZoom(75); +``` + +Or to predefined values ``fullPage``, ``bestFit``, ``textFit`` + +``` php +getSettings()->setZoom(Zoom::BEST_FIT); +``` + +### Mirroring the Page Margins + +Use mirror margins to set up facing pages for double-sided documents, such as books or magazines. + +``` php +getSettings()->setMirrorMargins(true); +``` + +### Spelling and grammatical checks + +By default spelling and grammatical errors are shown as soon as you open a word document. +For big documents this can slow down the opening of the document. You can hide the spelling and/or grammatical errors with: + +``` php +getSettings()->setHideGrammaticalErrors(true); +$phpWord->getSettings()->setHideSpellingErrors(true); +``` + +You can also specify the status of the spell and grammar checks, marking spelling or grammar as dirty will force a re-check when opening the document. + +``` php +setGrammar(\PhpOffice\PhpWord\ComplexType\ProofState::CLEAN); +$proofState->setSpelling(\PhpOffice\PhpWord\ComplexType\ProofState::DIRTY); + +$phpWord->getSettings()->setProofState($proofState); +``` + +### Track Revisions + +Track changes can be activated using ``setTrackRevisions``, you can furture specify + +- Not to use move syntax, instead moved items will be seen as deleted in one place and added in another +- Not track formatting revisions + +``` php +getSettings()->setTrackRevisions(true); +$phpWord->getSettings()->setDoNotTrackMoves(true); +$phpWord->getSettings()->setDoNotTrackFormatting(true); +``` + +### Decimal Symbol + +The default symbol to represent a decimal figure is the ``.`` in english. In french you might want to change it to ``,`` for instance. + +``` php +getSettings()->setDecimalSymbol(','); +``` + +### Document Language + +The default language of the document can be change with the following. + +``` php +getSettings()->setThemeFontLang(new Language(Language::FR_BE)); +``` + +``Language`` has 3 parameters, one for Latin languages, one for East Asian languages and one for Complex (Bi-Directional) languages. +A couple of language codes are provided in the ``PhpOffice\PhpWord\Style\Language`` class but any valid code/ID can be used. + +In case you are generating an RTF document the language need to be set differently. + +``` php +setLangId(Language::EN_GB_ID); +$phpWord->getSettings()->setThemeFontLang($lang); +``` + +## Document information + +You can set the document information such as title, creator, and company +name. Use the following functions: + +``` php +getDocInfo(); +$properties->setCreator('My name'); +$properties->setCompany('My factory'); +$properties->setTitle('My title'); +$properties->setDescription('My description'); +$properties->setCategory('My category'); +$properties->setLastModifiedBy('My name'); +$properties->setCreated(mktime(0, 0, 0, 3, 12, 2014)); +$properties->setModified(mktime(0, 0, 0, 3, 14, 2014)); +$properties->setSubject('My subject'); +$properties->setKeywords('my, key, word'); +``` + +## Measurement units + +The base length unit in Open Office XML is twip. Twip means "TWentieth +of an Inch Point", i.e. 1 twip = 1/1440 inch. + +You can use PHPWord helper functions to convert inches, centimeters, or +points to twip. + +``` php +addParagraphStyle('My Style', array( + 'spaceAfter' => \PhpOffice\PhpWord\Shared\Converter::pointToTwip(6)) +); + +$section = $phpWord->addSection(); +$sectionStyle = $section->getStyle(); +// half inch left margin +$sectionStyle->setMarginLeft(\PhpOffice\PhpWord\Shared\Converter::inchToTwip(.5)); +// 2 cm right margin +$sectionStyle->setMarginRight(\PhpOffice\PhpWord\Shared\Converter::cmToTwip(2)); +``` + +## Document protection + +The document (or parts of it) can be password protected. + +``` php +getSettings()->getDocumentProtection(); +$documentProtection->setEditing(DocProtect::READ_ONLY); +$documentProtection->setPassword('myPassword'); +``` + +## Automatically Recalculate Fields on Open + +To force an update of the fields present in the document, set updateFields to true + +``` php +getSettings()->setUpdateFields(true); +``` + +## Hyphenation + +Hyphenation describes the process of breaking words with hyphens. There are several options to control hyphenation. + +### Auto hyphenation + +To automatically hyphenate text set ``autoHyphenation`` to ``true``. + +``` php +getSettings()->setAutoHyphenation(true); +``` + +### Consecutive Hyphen Limit + +The maximum number of consecutive lines of text ending with a hyphen can be controlled by the ``consecutiveHyphenLimit`` option. +There is no limit if the option is not set or the provided value is ``0``. + +``` php +getSettings()->setConsecutiveHyphenLimit(2); +``` + +### Hyphenation Zone + +The hyphenation zone (in *twip*) is the allowed amount of whitespace before hyphenation is applied. +The smaller the hyphenation zone the more words are hyphenated. Or in other words, the wider the hyphenation zone the less words are hyphenated. + +``` php +getSettings()->setHyphenationZone(\PhpOffice\PhpWord\Shared\Converter::cmToTwip(1)); +``` + +### Hyphenate Caps + +To control whether or not words in all capital letters shall be hyphenated use the `doNotHyphenateCaps` option. + +``` php +getSettings()->setDoNotHyphenateCaps(true); +``` \ No newline at end of file diff --git a/docs/usage/readers.md b/docs/usage/readers.md new file mode 100644 index 0000000000..9cd9c1c4d6 --- /dev/null +++ b/docs/usage/readers.md @@ -0,0 +1,51 @@ +# Readers + +## HTML +The name of the reader is `HTML`. + +``` php +load(__DIR__ . '/sample.html'); +``` + +## MsDoc +The name of the reader is `MsDoc`. + +``` php +load(__DIR__ . '/sample.doc'); +``` + +## ODText +The name of the reader is `ODText`. + +``` php +load(__DIR__ . '/sample.odt'); +``` + +## RTF +The name of the reader is `RTF`. + +``` php +load(__DIR__ . '/sample.rtf'); +``` + +## Word2007 +The name of the reader is `Word2007`. + +``` php +load(__DIR__ . '/sample.docx'); +``` \ No newline at end of file diff --git a/docs/usage/styles/chart.md b/docs/usage/styles/chart.md new file mode 100644 index 0000000000..f297718d24 --- /dev/null +++ b/docs/usage/styles/chart.md @@ -0,0 +1,19 @@ +# Chart + +Available Chart style options: + +- ``width``. Width (in EMU). +- ``height``. Height (in EMU). +- ``3d``. Is 3D; applies to pie, bar, line, area, *true* or *false*. +- ``colors``. A list of colors to use in the chart. +- ``title``. The title for the chart. +- ``showLegend``. Show legend, *true* or *false*. +- ``LegendPosition``. Legend position, *r* (default), *b*, *t*, *l* or *tr*. +- ``categoryLabelPosition``. Label position for categories, *nextTo* (default), *low* or *high*. +- ``valueLabelPosition``. Label position for values, *nextTo* (default), *low* or *high*. +- ``categoryAxisTitle``. The title for the category axis. +- ``valueAxisTitle``. The title for the values axis. +- ``majorTickMarkPos``. The position for major tick marks, *in*, *out*, *cross*, *none* (default). +- ``showAxisLabels``. Show labels for axis, *true* or *false*. +- ``gridX``. Show Gridlines for X-Axis, *true* or *false*. +- ``gridY``. Show Gridlines for Y-Axis, *true* or *false*. \ No newline at end of file diff --git a/docs/usage/styles/font.md b/docs/usage/styles/font.md new file mode 100644 index 0000000000..90e492bf0e --- /dev/null +++ b/docs/usage/styles/font.md @@ -0,0 +1,26 @@ +# Font + +Available Font style options: + +- ``allCaps``. All caps, *true* or *false*. +- ``bgColor``. Font background color, e.g. *FF0000*. +- ``bold``. Bold, *true* or *false*. +- ``color``. Font color, e.g. *FF0000*. +- ``doubleStrikethrough``. Double strikethrough, *true* or *false*. +- ``fgColor``. Font highlight color, e.g. *yellow*, *green*, *blue*. + See ``\PhpOffice\PhpWord\Style\Font::FGCOLOR_...`` class constants for possible values +- ``hint``. Font content type, *default*, *eastAsia*, or *cs*. +- ``italic``. Italic, *true* or *false*. +- ``name``. Font name, e.g. *Arial*. +- ``rtl``. Right to Left language, *true* or *false*. +- ``size``. Font size, e.g. *20*, *22*. +- ``smallCaps``. Small caps, *true* or *false*. +- ``strikethrough``. Strikethrough, *true* or *false*. +- ``subScript``. Subscript, *true* or *false*. +- ``superScript``. Superscript, *true* or *false*. +- ``underline``. Underline, *single*, *dash*, *dotted*, etc. + See ``\PhpOffice\PhpWord\Style\Font::UNDERLINE_...`` class constants for possible values +- ``lang``. Language, either a language code like *en-US*, *fr-BE*, etc. or an object (or as an array) if you need to set eastAsian or bidirectional languages + 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*. \ No newline at end of file diff --git a/docs/usage/styles/image.md b/docs/usage/styles/image.md new file mode 100644 index 0000000000..b6c4ddf936 --- /dev/null +++ b/docs/usage/styles/image.md @@ -0,0 +1,14 @@ +# Image + +Available Image style options: + +- ``alignment``. See ``\PhpOffice\PhpWord\SimpleType\Jc`` class for the details. +- ``height``. Height in *pt*. +- ``marginLeft``. Left margin in inches, can be negative. +- ``marginTop``. Top margin in inches, can be negative. +- ``width``. Width in *pt*. +- ``wrappingStyle``. Wrapping style, *inline*, *square*, *tight*, *behind*, or *infront*. +- ``wrapDistanceTop``. Top text wrapping in pixels. +- ``wrapDistanceBottom``. Bottom text wrapping in pixels. +- ``wrapDistanceLeft``. Left text wrapping in pixels. +- ``wrapDistanceRight``. Right text wrapping in pixels. \ No newline at end of file diff --git a/docs/usage/styles/numberinglevel.md b/docs/usage/styles/numberinglevel.md new file mode 100644 index 0000000000..392e820048 --- /dev/null +++ b/docs/usage/styles/numberinglevel.md @@ -0,0 +1,16 @@ +# Numbering level + +Available NumberingLevel style options: + +- ``alignment``. Supports all alignment modes since 1st Edition of ECMA-376 standard up till ISO/IEC 29500:2012. + See ``\PhpOffice\PhpWord\SimpleType\Jc`` class constants for possible values. +- ``font``. Font name. +- ``format``. Numbering format bullet\|decimal\|upperRoman\|lowerRoman\|upperLetter\|lowerLetter. +- ``hanging``. See paragraph style. +- ``hint``. See font style. +- ``left``. See paragraph style. +- ``restart``. Restart numbering level symbol. +- ``start``. Starting value. +- ``suffix``. Content between numbering symbol and paragraph text tab\|space\|nothing. +- ``tabPos``. See paragraph style. +- ``text``. Numbering level text e.g. %1 for nonbullet or bullet character. \ No newline at end of file diff --git a/docs/usage/styles/paragraph.md b/docs/usage/styles/paragraph.md new file mode 100644 index 0000000000..e9ca155005 --- /dev/null +++ b/docs/usage/styles/paragraph.md @@ -0,0 +1,29 @@ +# Paragraph + +Available Paragraph style options: + +- ``alignment``. Supports all alignment modes since 1st Edition of ECMA-376 standard up till ISO/IEC 29500:2012. + See ``\PhpOffice\PhpWord\SimpleType\Jc`` class constants for possible values. +- ``basedOn``. Parent style. +- ``hanging``. Hanging indentation in *half inches*. +- ``indent``. Indent (left indentation) in *half inches*. +- ``indentation``. An array of indentation key => value pairs in *twip*. Supports *left*, *right*, *firstLine* and *hanging* indentation. + See ``\PhpOffice\PhpWord\Style\Indentation`` for possible identation types. +- ``keepLines``. Keep all lines on one page, *true* or *false*. +- ``keepNext``. Keep paragraph with next paragraph, *true* or *false*. +- ``lineHeight``. Text line height, e.g. *1.0*, *1.5*, etc. +- ``next``. Style for next paragraph. +- ``pageBreakBefore``. Start paragraph on next page, *true* or *false*. +- ``spaceBefore``. Space before paragraph in *twip*. +- ``spaceAfter``. Space after paragraph in *twip*. +- ``spacing``. Space between lines in *twip*. If spacingLineRule is auto, 240 (height of 1 line) will be added, so if you want a double line height, set this to 240. +- ``spacingLineRule``. Line Spacing Rule. *auto*, *exact*, *atLeast* + See ``\PhpOffice\PhpWord\SimpleType\LineSpacingRule`` class constants for possible values. +- ``suppressAutoHyphens``. Hyphenation for paragraph, *true* or *false*. +- ``tabs``. Set of custom tab stops. +- ``widowControl``. Allow first/last line to display on a separate page, *true* or *false*. +- ``contextualSpacing``. Ignore Spacing Above and Below When Using Identical Styles, *true* or *false*. +- ``bidi``. Right to Left Paragraph Layout, *true* or *false*. +- ``shading``. Paragraph Shading. +- ``textAlignment``. Vertical Character Alignment on Line. + See ``\PhpOffice\PhpWord\SimpleType\TextAlignment`` class constants for possible values. \ No newline at end of file diff --git a/docs/usage/styles/section.md b/docs/usage/styles/section.md new file mode 100644 index 0000000000..2be22e8077 --- /dev/null +++ b/docs/usage/styles/section.md @@ -0,0 +1,28 @@ +# Section + +Available Section style options: + +- ``borderBottomColor``. Border bottom color. +- ``borderBottomSize``. Border bottom size in *twip*. +- ``borderLeftColor``. Border left color. +- ``borderLeftSize``. Border left size in *twip*. +- ``borderRightColor``. Border right color. +- ``borderRightSize``. Border right size in *twip*. +- ``borderTopColor``. Border top color. +- ``borderTopSize``. Border top size in *twip*. +- ``breakType``. Section break type (nextPage, nextColumn, continuous, evenPage, oddPage). +- ``colsNum``. Number of columns. +- ``colsSpace``. Spacing between columns. +- ``footerHeight``. Spacing to bottom of footer. +- ``gutter``. Page gutter spacing. +- ``headerHeight``. Spacing to top of header. +- ``marginTop``. Page margin top in *twip*. +- ``marginLeft``. Page margin left in *twip*. +- ``marginRight``. Page margin right in *twip*. +- ``marginBottom``. Page margin bottom in *twip*. +- ``orientation``. Page orientation (``portrait``, which is default, or ``landscape``). + See ``\PhpOffice\PhpWord\Style\Section::ORIENTATION_...`` class constants for possible values +- ``pageSizeH``. Page height in *twip*. Implicitly defined by ``orientation`` option. Any changes are discouraged. +- ``pageSizeW``. Page width in *twip*. Implicitly defined by ``orientation`` option. Any changes are discouraged. +- ``vAlign``. Vertical Page Alignment + See ``\PhpOffice\PhpWord\SimpleType\VerticalJc`` for possible values \ No newline at end of file diff --git a/docs/usage/styles/table.md b/docs/usage/styles/table.md new file mode 100644 index 0000000000..1f82f3c638 --- /dev/null +++ b/docs/usage/styles/table.md @@ -0,0 +1,49 @@ +# Table + +Available Table style options: + +- ``alignment``. Supports all alignment modes since 1st Edition of ECMA-376 standard up till ISO/IEC 29500:2012. + See ``\PhpOffice\PhpWord\SimpleType\JcTable`` and ``\PhpOffice\PhpWord\SimpleType\Jc`` class constants for possible values. +- ``bgColor``. Background color, e.g. '9966CC'. +- ``border(Top|Right|Bottom|Left)Color``. Border color, e.g. '9966CC'. +- ``border(Top|Right|Bottom|Left)Size``. Border size in *twip*. +- ``cellMargin(Top|Right|Bottom|Left)``. Cell margin in *twip*. +- ``indent``. Table indent from leading margin. Must be an instance of ``\PhpOffice\PhpWord\ComplexType\TblWidth``. +- ``width``. Table width in Fiftieths of a Percent or Twentieths of a Point. +- ``unit``. The unit to use for the width. One of ``\PhpOffice\PhpWord\SimpleType\TblWidth``. Defaults to *auto*. +- ``layout``. Table layout, either *fixed* or *autofit* See ``\PhpOffice\PhpWord\Style\Table`` for constants. +- ``cellSpacing`` Cell spacing in *twip* +- ``position`` Floating Table Positioning, see below for options +- ``bidiVisual`` Present table as Right-To-Left + +Floating Table Positioning options: + +- ``leftFromText`` Distance From Left of Table to Text in *twip* +- ``rightFromText`` Distance From Right of Table to Text in *twip* +- ``topFromText`` Distance From Top of Table to Text in *twip* +- ``bottomFromText`` Distance From Top of Table to Text in *twip* +- ``vertAnchor`` Table Vertical Anchor, one of ``\PhpOffice\PhpWord\Style\TablePosition::VANCHOR_*`` +- ``horzAnchor`` Table Horizontal Anchor, one of ``\PhpOffice\PhpWord\Style\TablePosition::HANCHOR_*`` +- ``tblpXSpec`` Relative Horizontal Alignment From Anchor, one of ``\PhpOffice\PhpWord\Style\TablePosition::XALIGN_*`` +- ``tblpX`` Absolute Horizontal Distance From Anchorin *twip* +- ``tblpYSpec`` Relative Vertical Alignment From Anchor, one of ``\PhpOffice\PhpWord\Style\TablePosition::YALIGN_*`` +- ``tblpY`` Absolute Vertical Distance From Anchorin *twip* + +Available Row style options: + +- ``cantSplit``. Table row cannot break across pages, *true* or *false*. +- ``exactHeight``. Row height is exact or at least. +- ``tblHeader``. Repeat table row on every new page, *true* or *false*. + +Available Cell style options: + +- ``bgColor``. Background color, e.g. '9966CC'. +- ``border(Top|Right|Bottom|Left)Color``. Border color, e.g. '9966CC'. +- ``border(Top|Right|Bottom|Left)Size``. Border size in *twip*. +- ``border(Top|Right|Bottom|Left)Style``. Border style. You can use constants from ``\PhpOffice\PhpWord\SimpleType\Border`` +- ``gridSpan``. Number of columns spanned. +- ``textDirection(btLr|tbRl)``. Direction of text. + You can use constants ``\PhpOffice\PhpWord\Style\Cell::TEXT_DIR_BTLR`` and ``\PhpOffice\PhpWord\Style\Cell::TEXT_DIR_TBRL`` +- ``valign``. Vertical alignment, *top*, *center*, *both*, *bottom*. +- ``vMerge``. *restart* or *continue*. +- ``width``. Cell width in *twip*. \ No newline at end of file diff --git a/docs/usage/template.md b/docs/usage/template.md new file mode 100644 index 0000000000..17612357fd --- /dev/null +++ b/docs/usage/template.md @@ -0,0 +1,347 @@ +# Template processing + +You can create an OOXML document template with included search-patterns (macros) which can be replaced by any value you wish. Only single-line values can be replaced. +By default Macros are defined like this: ``${search-pattern}`` but you can define custom macros. +To load a template file, create a new instance of the TemplateProcessor. + +``` php +setValue('firstname', 'John'); +$templateProcessor->setValue('lastname', 'Doe'); +``` + +## setValues + +You can also set multiple values by passing all of them in an array. + +``` php +setValues(array('firstname' => 'John', 'lastname' => 'Doe')); +``` + +## setMacroOpeningChars + +You can define a custom opening macro. The following will set ``{#`` as the opening search pattern. + +``` php +setMacroOpeningChars('{#'); +``` + +## setMacroClosingChars + +You can define a custom closing macro. The following will set ``#}`` as the closing search pattern. + +``` php +setMacroClosingChars('#}'); +``` + +## setMacroChars + +You can define a custom opening and closing macro at the same time . The following will set the search-pattern like this: ``{#search-pattern#}`` . + +``` php +setMacroChars('{#', '#}'); +``` + +## setImageValue + +The search-pattern model for images can be like: + - ``${search-image-pattern}`` + - ``${search-image-pattern:[width]:[height]:[ratio]}`` + - ``${search-image-pattern:[width]x[height]}`` + - ``${search-image-pattern:size=[width]x[height]}`` + - ``${search-image-pattern:width=[width]:height=[height]:ratio=false}`` + +Where: + - [width] and [height] can be just numbers or numbers with measure, which supported by Word (cm, mm, in, pt, pc, px, %, em, ex) + - [ratio] uses only for ``false``, ``-`` or ``f`` to turn off respect aspect ration of image. By default template image size uses as 'container' size. + +Example: + +``` clean + +${CompanyLogo} +${UserLogo:50:50} ${Name} - ${City} - ${Street} +``` + +``` php +setValue('Name', 'John Doe'); +$templateProcessor->setValue(array('City', 'Street'), array('Detroit', '12th Street')); + +$templateProcessor->setImageValue('CompanyLogo', 'path/to/company/logo.png'); +$templateProcessor->setImageValue('UserLogo', array('path' => 'path/to/logo.png', 'width' => 100, 'height' => 100, 'ratio' => false)); +$templateProcessor->setImageValue('FeatureImage', function () { + // Closure will only be executed if the replacement tag is found in the template + + return array('path' => SlowFeatureImageGenerator::make(), 'width' => 100, 'height' => 100, 'ratio' => false); +}); +``` + +## cloneBlock + +Given a template containing +See ``Sample_23_TemplateBlock.php`` for an example. + +``` clean + +${block_name} +Customer: ${customer_name} +Address: ${customer_address} +${/block_name} +``` + +The following will duplicate everything between ``${block_name}`` and ``${/block_name}`` 3 times. + +``` php +cloneBlock('block_name', 3, true, true); +``` + +The last parameter will rename any macro defined inside the block and add #1, #2, #3 ... to the macro name. +The result will be + +``` clean + +Customer: ${customer_name#1} +Address: ${customer_address#1} + +Customer: ${customer_name#2} +Address: ${customer_address#2} + +Customer: ${customer_name#3} +Address: ${customer_address#3} +``` + +It is also possible to pass an array with the values to replace the marcros with. +If an array with replacements is passed, the ``count`` argument is ignored, it is the size of the array that counts. + +``` php + 'Batman', 'customer_address' => 'Gotham City'), + array('customer_name' => 'Superman', 'customer_address' => 'Metropolis'), +); +$templateProcessor->cloneBlock('block_name', 0, true, false, $replacements); +``` + +The result will then be + +``` clean + +Customer: Batman +Address: Gotham City + +Customer: Superman +Address: Metropolis +``` + +## replaceBlock + +Given a template containing + +``` clean + +${block_name} +This block content will be replaced +${/block_name} +``` + +The following will replace everything between ``${block_name}`` and ``${/block_name}`` with the value passed. + +``` php +replaceBlock('block_name', 'This is the replacement text.'); +``` + +## deleteBlock + +Same as previous, but it deletes the block + +``` php +deleteBlock('block_name'); +``` + +## cloneRow + +Clones a table row in a template document. +See ``Sample_07_TemplateCloneRow.php`` for an example. + +``` clean + ++-----------+----------------+ +| ${userId} | ${userName} | +| |----------------+ +| | ${userAddress} | ++-----------+----------------+ +``` + +``` php +cloneRow('userId', 2); +``` + +Will result in + +``` clean + + +-------------+------------------+ +| ${userId#1} | ${userName#1} | +| |------------------+ +| | ${userAddress#1} | ++-------------+------------------+ +| ${userId#2} | ${userName#2} | +| |------------------+ +| | ${userAddress#2} | ++-------------+------------------+ +``` + +## cloneRowAndSetValues + +Finds a row in a table row identified by `$search` param and clones it as many times as there are entries in `$values`. + +``` clean + ++-----------+----------------+ +| ${userId} | ${userName} | +| |----------------+ +| | ${userAddress} | ++-----------+----------------+ +``` + +``` php + 1, 'userName' => 'Batman', 'userAddress' => 'Gotham City'], + ['userId' => 2, 'userName' => 'Superman', 'userAddress' => 'Metropolis'], +]; +$templateProcessor->cloneRowAndSetValues('userId', $values); +``` + +Will result in + +``` clean + ++---+-------------+ +| 1 | Batman | +| |-------------+ +| | Gotham City | ++---+-------------+ +| 2 | Superman | +| |-------------+ +| | Metropolis | ++---+-------------+ +``` + +## applyXslStyleSheet + +Applies the XSL stylesheet passed to header part, footer part and main part + +``` php +load('/path/to/my/stylesheet.xsl'); +$templateProcessor->applyXslStyleSheet($xslDomDocument); +``` + +## setComplexValue + +Replaces a ${macro} with the ComplexType passed. +See ``Sample_40_TemplateSetComplexValue.php`` for examples. + +``` php +addText('by a red italic text', array('italic' => true, 'color' => 'red')); +$templateProcessor->setComplexValue('inline', $inline); +``` + +## setComplexBlock + +Replaces a ${macro} with the ComplexType passed. +See ``Sample_40_TemplateSetComplexValue.php`` for examples. + +``` php + 12, 'borderColor' => 'green', 'width' => 6000, 'unit' => TblWidth::TWIP)); +$table->addRow(); +$table->addCell(150)->addText('Cell A1'); +$table->addCell(150)->addText('Cell A2'); +$table->addCell(150)->addText('Cell A3'); +$table->addRow(); +$table->addCell(150)->addText('Cell B1'); +$table->addCell(150)->addText('Cell B2'); +$table->addCell(150)->addText('Cell B3'); +$templateProcessor->setComplexBlock('table', $table); +``` + +## setChartValue + +Replace a variable by a chart. + +``` php +setChartValue('myChart', $chart); +``` + +## save + +Saves the loaded template within the current directory. Returns the file path. + +``` php +save(); +``` + +## saveAs + +Saves a copy of the loaded template in the indicated path. + +``` php +saveAs($pathToSave); +``` diff --git a/docs/usage/writers.md b/docs/usage/writers.md new file mode 100644 index 0000000000..86458cecef --- /dev/null +++ b/docs/usage/writers.md @@ -0,0 +1,65 @@ +# Writers + +## HTML +The name of the writer is `HTML`. + +``` php +save(__DIR__ . '/sample.html'); +``` + +## ODText +The name of the writer is `ODText`. + +``` php +save(__DIR__ . '/sample.docx'); +``` + +## PDF +The name of the writer is `PDF`. + +``` php +save(__DIR__ . '/sample.pdf'); +``` + +## RTF +The name of the writer is `RTF`. + +``` php +save(__DIR__ . '/sample.rtf'); +``` + +## Word2007 +The name of the writer is `Word2007`. + +``` php +save(__DIR__ . '/sample.docx'); +``` + +### ZIP Adapter +You can change the ZIP Adapter for the writer. By default, the ZIP Adapter is `ZipArchiveAdapter`. + +``` php +setZipAdapter(new PclZipAdapter()); +$writer->save(__DIR__ . '/sample.docx'); +``` diff --git a/docs/writersreaders.rst b/docs/writersreaders.rst deleted file mode 100644 index 33aacc72af..0000000000 --- a/docs/writersreaders.rst +++ /dev/null @@ -1,110 +0,0 @@ -.. _writersreaders: - -Writers & readers -================= - -OOXML ------ - -The package of OOXML document consists of the following files. - -- \_rels/ - - - .rels - -- docProps/ - - - app.xml - - core.xml - - custom.xml - -- word/ - - - rels/ - - - document.rels.xml - - - media/ - - theme/ - - - theme1.xml - - - document.xml - - fontTable.xml - - numbering.xml - - settings.xml - - styles.xml - - webSettings.xml - -- [Content\_Types].xml - -OpenDocument ------------- - -Package -~~~~~~~ - -The package of OpenDocument document consists of the following files. - -- META-INF/ - - - manifest.xml - -- Pictures/ -- content.xml -- meta.xml -- styles.xml - -content.xml -~~~~~~~~~~~ - -The structure of ``content.xml`` is described below. - -- office:document-content - - - office:font-facedecls - - office:automatic-styles - - office:body - - - office:text - - - draw:\* - - office:forms - - table:table - - text:list - - text:numbered-paragraph - - text:p - - text:table-of-contents - - text:section - - - office:chart - - office:image - - office:drawing - -styles.xml -~~~~~~~~~~ - -The structure of ``styles.xml`` is described below. - -- office:document-styles - - - office:styles - - office:automatic-styles - - office:master-styles - - - office:master-page - -RTF ---- - -To be completed. - -HTML ----- - -To be completed. - -PDF ---- - -To be completed. diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000000..5618dec88c --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,116 @@ +site_name: PHPWord +site_url: https://phpoffice.github.io/PHPWord +repo_url: https://github.com/PHPOffice/PHPWord +repo_name: PHPOffice/PHPWord +edit_uri: edit/develop/docs/ + +## Theme +theme: + name: material + palette: + primary: indigo + features: + - search.highlight + - search.suggest + +## Plugins +plugins: + - search + - autolink_references: + autolinks: + - reference_prefix: GP- + target_url: https://github.com/ + - reference_prefix: GH- + target_url: https://github.com/PHPOffice/PHPWord/issues/ + - reference_prefix: CP- + target_url: https://archive.codeplex.com/?p=phpword& + +## Config +extra: + generator: false +markdown_extensions: + ## Syntax highlighting + - pymdownx.highlight + - pymdownx.superfences + ## Support for emojis + - pymdownx.emoji: + emoji_index: !!python/name:materialx.emoji.twemoji + emoji_generator: !!python/name:materialx.emoji.to_svg + ## Support for call-outs + - admonition + - pymdownx.details +use_directory_urls: false + +## Navigation +nav: + - Introduction: 'index.md' + - Install: 'install.md' + - Usage: + - Introduction: 'usage/introduction.md' + - Containers: 'usage/containers.md' + - Elements: + - Introduction: 'usage/elements/index.md' + - Chart: 'usage/elements/chart.md' + - Checkbox: 'usage/elements/checkbox.md' + - Comment: 'usage/elements/comment.md' + - Field: 'usage/elements/field.md' + - Footnote & Endnote: 'usage/elements/note.md' + - Image: 'usage/elements/image.md' + - Line: 'usage/elements/line.md' + - Link: 'usage/elements/link.md' + - List: 'usage/elements/list.md' + - OLE Object: 'usage/elements/oleobject.md' + - Page Break: 'usage/elements/pagebreak.md' + - Preserve Text: 'usage/elements/preservetext.md' + - Text: 'usage/elements/text.md' + - TextBox: 'usage/elements/textbox.md' + - Text Break: 'usage/elements/textbreak.md' + - Table: 'usage/elements/table.md' + - Table of contents: 'usage/elements/toc.md' + - Title: 'usage/elements/title.md' + - Track Changes: 'usage/elements/trackchanges.md' + - Watermark: 'usage/elements/watermark.md' + - Styles: + - Chart: 'usage/styles/chart.md' + - Font: 'usage/styles/font.md' + - Image: 'usage/styles/image.md' + - Numbering Level: 'usage/styles/numberinglevel.md' + - Paragraph: 'usage/styles/paragraph.md' + - Section: 'usage/styles/section.md' + - Table: 'usage/styles/table.md' + - Template Processing: 'usage/template.md' + - Readers: 'usage/readers.md' + - Writers: 'usage/writers.md' + - FAQ: 'faq.md' + - How to: 'howto.md' + - Credits: 'credits.md' + - Releases: + - '1.x': + - '1.2.0 (WIP)': 'changes/1.x/1.2.0.md' + - '1.1.0': 'changes/1.x/1.1.0.md' + - '1.0.0': 'changes/1.x/1.0.0.md' + - '0.x': + - '0.18.3': 'changes/0.x/0.18.3.md' + - '0.18.2': 'changes/0.x/0.18.2.md' + - '0.18.1': 'changes/0.x/0.18.1.md' + - '0.18.0': 'changes/0.x/0.18.0.md' + - '0.17.0': 'changes/0.x/0.17.0.md' + - '0.16.0': 'changes/0.x/0.16.0.md' + - '0.15.0': 'changes/0.x/0.15.0.md' + - '0.14.0': 'changes/0.x/0.14.0.md' + - '0.13.0': 'changes/0.x/0.13.0.md' + - '0.12.1': 'changes/0.x/0.12.1.md' + - '0.12.0': 'changes/0.x/0.12.0.md' + - '0.11.1': 'changes/0.x/0.11.1.md' + - '0.11.0': 'changes/0.x/0.11.0.md' + - '0.10.1': 'changes/0.x/0.10.1.md' + - '0.10.0': 'changes/0.x/0.10.0.md' + - '0.9.1': 'changes/0.x/0.9.1.md' + - '0.9.0': 'changes/0.x/0.9.0.md' + - '0.8.1': 'changes/0.x/0.8.1.md' + - '0.8.0': 'changes/0.x/0.8.0.md' + - '0.7.0': 'changes/0.x/0.7.0.md' + - Developers: + - 'Coveralls': 'https://coveralls.io/github/PHPOffice/PHPWord' + - 'Code Coverage': 'coverage/index.html' + - 'PHPDoc': 'docs/index.html' diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index 84468faaa5..daf109966c 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -12,7 +12,7 @@ $html .= '

    Some well-formed HTML snippet needs to be used

    '; $html .= '

    With for example some1 inline formatting1

    '; -$html .= '

    A link to Read the docs

    '; +$html .= '

    A link to Read the docs

    '; $html .= '

    היי, זה פסקה מימין לשמאל

    '; diff --git a/samples/Sample_Header.php b/samples/Sample_Header.php index 53674b7914..8d05a2a34e 100644 --- a/samples/Sample_Header.php +++ b/samples/Sample_Header.php @@ -165,8 +165,8 @@ function getEndingNotes($writers, $filename)
diff --git a/samples/index.php b/samples/index.php index a867eb3d80..a9733d2c7c 100644 --- a/samples/index.php +++ b/samples/index.php @@ -19,7 +19,7 @@

 

Fork us on Github! - Read the Docs + Read the Docs

Adding element via HTML

Double height

Includes images

- + diff --git a/sonar-project.properties b/sonar-project.properties deleted file mode 100644 index 7741cfb475..0000000000 --- a/sonar-project.properties +++ /dev/null @@ -1,17 +0,0 @@ -# must be unique in a given SonarQube instance -sonar.projectKey=phpoffice:phpword -# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1. -sonar.projectName=PHPWord -sonar.projectVersion=0.16 - -# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. -# This property is optional if sonar.modules is set. -sonar.sources=src -sonar.tests=tests -sonar.php.coverage.reportPaths=build/logs/clover.xml -sonar.php.tests.reportPath=build/logs/logfile.xml - -# Encoding of the source code. Default is default system encoding -#sonar.sourceEncoding=UTF-8 - -sonar.host.url=http://localhost:9000 \ No newline at end of file diff --git a/src/PhpWord/Reader/MsDoc.php b/src/PhpWord/Reader/MsDoc.php index c76f5df3e0..fed6c99188 100644 --- a/src/PhpWord/Reader/MsDoc.php +++ b/src/PhpWord/Reader/MsDoc.php @@ -1141,7 +1141,7 @@ private function readFibContent(): void /** * Section and information about them. * - * @see : http://msdn.microsoft.com/en-us/library/dd924458%28v=office.12%29.aspx + * @see http://msdn.microsoft.com/en-us/library/dd924458%28v=office.12%29.aspx */ private function readRecordPlcfSed(): void { @@ -1187,7 +1187,7 @@ private function readRecordPlcfSed(): void /** * Specifies the fonts that are used in the document. * - * @see : http://msdn.microsoft.com/en-us/library/dd943880%28v=office.12%29.aspx + * @see http://msdn.microsoft.com/en-us/library/dd943880%28v=office.12%29.aspx */ private function readRecordSttbfFfn(): void { @@ -1271,7 +1271,7 @@ private function readRecordPlcfBtePapx(): void } $arrayRGB = []; for ($inc = 1; $inc <= $numRun; ++$inc) { - // @see http://msdn.microsoft.com/en-us/library/dd925804(v=office.12).aspx + //@see http://msdn.microsoft.com/en-us/library/dd925804(v=office.12).aspx $arrayRGB[$inc] = self::getInt1d($this->dataWorkDocument, $offset); ++$offset; // reserved @@ -1478,7 +1478,7 @@ private function readRecordPlcfBteChpx(): void $offset = $offsetBase; // ChpxFkp - // @see : http://msdn.microsoft.com/en-us/library/dd910989%28v=office.12%29.aspx + //@see : http://msdn.microsoft.com/en-us/library/dd910989%28v=office.12%29.aspx $numRGFC = self::getInt1d($this->dataWorkDocument, $offset + 511); $arrayRGFC = []; for ($inc = 0; $inc <= $numRGFC; ++$inc) { @@ -1501,7 +1501,7 @@ private function readRecordPlcfBteChpx(): void if ($rgb > 0) { // Chp Structure - // @see : http://msdn.microsoft.com/en-us/library/dd772849%28v=office.12%29.aspx + //@see : http://msdn.microsoft.com/en-us/library/dd772849%28v=office.12%29.aspx $posRGB = $offsetBase + $rgb * 2; $cb = self::getInt1d($this->dataWorkDocument, $posRGB); diff --git a/src/PhpWord/Writer/Word2007.php b/src/PhpWord/Writer/Word2007.php index 9e17efa611..ae10ba5a74 100644 --- a/src/PhpWord/Writer/Word2007.php +++ b/src/PhpWord/Writer/Word2007.php @@ -121,7 +121,7 @@ public function save($filename = null): void $this->addHeaderFooterMedia($zip, 'footer'); // Add header/footer contents - $rId = Media::countElements('section') + 6; // @see Rels::writeDocRels for 6 first elements + $rId = Media::countElements('section') + 6; //@see Rels::writeDocRels for 6 first elements $sections = $phpWord->getSections(); foreach ($sections as $section) { $this->addHeaderFooterContent($section, $zip, 'header', $rId); diff --git a/tests/PhpWordTests/Shared/HtmlTest.php b/tests/PhpWordTests/Shared/HtmlTest.php index d65066d54c..b0ab159150 100644 --- a/tests/PhpWordTests/Shared/HtmlTest.php +++ b/tests/PhpWordTests/Shared/HtmlTest.php @@ -891,7 +891,7 @@ public function testParseLink(): void { $phpWord = new PhpWord(); $section = $phpWord->addSection(); - $html = '

link text

'; + $html = '

link text

'; Html::addHtml($section, $html); $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); From 9adbc2d32140a75d5b1d41f8f26e71481c25847d Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Fri, 8 Sep 2023 15:11:38 +0200 Subject: [PATCH 131/246] Moved documention from ReadTheDocs to MkDocs & Github Pages (Fixed build) --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 433a62077a..c349d7c59a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -3,7 +3,7 @@ name: Deploy on: push: branches: - - develop + - master pull_request: jobs: From c3391b9a8d08e138e66aa0a62c96d9ce508b8c97 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Fri, 8 Sep 2023 15:16:59 +0200 Subject: [PATCH 132/246] Moved documention from ReadTheDocs to MkDocs & Github Pages (Fixed deploy) --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c349d7c59a..7a1c2a6ea7 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -45,7 +45,7 @@ jobs: ### Deploy - name: Deploy uses: peaceiris/actions-gh-pages@v3 - if: github.ref == 'refs/heads/develop' + if: github.ref == 'refs/heads/master' with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./public From 1881d29db8a547c2c2a3da340780f2ceacdc130b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 11:39:14 +0000 Subject: [PATCH 133/246] Bump phpstan/phpstan-phpunit from 1.3.13 to 1.3.14 Bumps [phpstan/phpstan-phpunit](https://github.com/phpstan/phpstan-phpunit) from 1.3.13 to 1.3.14. - [Release notes](https://github.com/phpstan/phpstan-phpunit/releases) - [Commits](https://github.com/phpstan/phpstan-phpunit/compare/1.3.13...1.3.14) --- updated-dependencies: - dependency-name: phpstan/phpstan-phpunit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/composer.lock b/composer.lock index 189f67eb60..a1b5feff6a 100644 --- a/composer.lock +++ b/composer.lock @@ -1461,16 +1461,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.15", + "version": "1.10.32", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd" + "reference": "c47e47d3ab03137c0e121e77c4d2cb58672f6d44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/762c4dac4da6f8756eebb80e528c3a47855da9bd", - "reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c47e47d3ab03137c0e121e77c4d2cb58672f6d44", + "reference": "c47e47d3ab03137c0e121e77c4d2cb58672f6d44", "shasum": "" }, "require": { @@ -1519,20 +1519,20 @@ "type": "tidelift" } ], - "time": "2023-05-09T15:28:01+00:00" + "time": "2023-08-24T21:54:50+00:00" }, { "name": "phpstan/phpstan-phpunit", - "version": "1.3.13", + "version": "1.3.14", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "d8bdab0218c5eb0964338d24a8511b65e9c94fa5" + "reference": "614acc10c522e319639bf38b0698a4a566665f04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/d8bdab0218c5eb0964338d24a8511b65e9c94fa5", - "reference": "d8bdab0218c5eb0964338d24a8511b65e9c94fa5", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/614acc10c522e319639bf38b0698a4a566665f04", + "reference": "614acc10c522e319639bf38b0698a4a566665f04", "shasum": "" }, "require": { @@ -1545,7 +1545,7 @@ "require-dev": { "nikic/php-parser": "^4.13.0", "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-strict-rules": "^1.0", + "phpstan/phpstan-strict-rules": "^1.5.1", "phpunit/phpunit": "^9.5" }, "type": "phpstan-extension", @@ -1569,9 +1569,9 @@ "description": "PHPUnit extensions and rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.13" + "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.14" }, - "time": "2023-05-26T11:05:59+00:00" + "time": "2023-08-25T09:46:39+00:00" }, { "name": "phpunit/php-code-coverage", @@ -5016,9 +5016,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "phpstan/phpstan-phpunit": 0 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From e3cae8d7eca9307748946da4b702fd323c327671 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Fri, 8 Sep 2023 15:51:57 +0200 Subject: [PATCH 134/246] Fixed update PHPStan --- docs/changes/1.x/1.2.0.md | 3 ++- phpstan-baseline.neon | 17 +---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index e52771c08c..b92329adac 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -27,4 +27,5 @@ - Bump phpunit/phpunit from 9.6.8 to 9.6.10 by [@dependabot](https://github.com/dependabot) in GH-2430 - Added Coveralls.io by [@Progi1984](https://github.com/Progi1984) in GH-2452 - Added support for PHP 8.2 & PHP 8.3 by [@Progi1984](https://github.com/Progi1984) in GH-2453 -- Moved documention from ReadTheDocs to MkDocs & Github Pages by [@Progi1984](https://github.com/Progi1984) in GH-2465 \ No newline at end of file +- Moved documention from ReadTheDocs to MkDocs & Github Pages by [@Progi1984](https://github.com/Progi1984) in GH-2465 +- Bump phpstan/phpstan-phpunit from 1.3.13 to 1.3.14 by [@dependabot](https://github.com/dependabot) in [#2457](https://github.com/PHPOffice/PHPWord/pull/2457) \ No newline at end of file diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 937798bfdd..4efe5078ef 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -46,7 +46,7 @@ parameters: path: src/PhpWord/Element/Footnote.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Element\\\\Image\\:\\:getArchiveImageSize\\(\\) should return array\\|null but returns array\\|false\\|null\\.$#" + message: "#^Method PhpOffice\\\\PhpWord\\\\Element\\\\Image\\:\\:getArchiveImageSize\\(\\) should return array\\|null but returns array\\|false\\|null\\.$#" count: 1 path: src/PhpWord/Element/Image.php @@ -325,11 +325,6 @@ parameters: count: 1 path: src/PhpWord/Reader/Word2007/Settings.php - - - message: "#^Static property PhpOffice\\\\PhpWord\\\\Reader\\\\Word2007\\\\Settings\\:\\:\\$booleanProperties is never read, only written\\.$#" - count: 1 - path: src/PhpWord/Reader/Word2007/Settings.php - - message: "#^Parameter \\#1 \\$filename of function parse_ini_file expects string, string\\|false given\\.$#" count: 1 @@ -870,11 +865,6 @@ parameters: count: 1 path: src/PhpWord/Style/ListItem.php - - - message: "#^Parameter \\#2 \\$string of function explode expects string, array\\\\|string given\\.$#" - count: 1 - path: src/PhpWord/Style/ListItem.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\:\\:setStyleValue\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph but returns PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\.$#" count: 1 @@ -1265,11 +1255,6 @@ parameters: count: 1 path: src/PhpWord/Writer/ODText/Element/Text.php - - - message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Element\\\\Text\\:\\:replacetabs\\(\\) is unused\\.$#" - count: 1 - path: src/PhpWord/Writer/ODText/Element/Text.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Element\\\\Text\\:\\:writeChangeInsertion\\(\\) has parameter \\$start with no type specified\\.$#" count: 1 From b1ebbf8cdacfd76d603f07a89da58b1b975fc81a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Sep 2023 14:35:59 +0000 Subject: [PATCH 135/246] Bump symfony/process from 5.4.26 to 5.4.28 Bumps [symfony/process](https://github.com/symfony/process) from 5.4.26 to 5.4.28. - [Release notes](https://github.com/symfony/process/releases) - [Changelog](https://github.com/symfony/process/blob/6.3/CHANGELOG.md) - [Commits](https://github.com/symfony/process/compare/v5.4.26...v5.4.28) --- updated-dependencies: - dependency-name: symfony/process dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/composer.lock b/composer.lock index a1b5feff6a..cc9504298e 100644 --- a/composer.lock +++ b/composer.lock @@ -4438,16 +4438,16 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", "shasum": "" }, "require": { @@ -4456,7 +4456,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4501,7 +4501,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" }, "funding": [ { @@ -4517,7 +4517,7 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-php81", @@ -4600,16 +4600,16 @@ }, { "name": "symfony/process", - "version": "v5.4.26", + "version": "v5.4.28", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "1a44dc377ec86a50fab40d066cd061e28a6b482f" + "reference": "45261e1fccad1b5447a8d7a8e67aa7b4a9798b7b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/1a44dc377ec86a50fab40d066cd061e28a6b482f", - "reference": "1a44dc377ec86a50fab40d066cd061e28a6b482f", + "url": "https://api.github.com/repos/symfony/process/zipball/45261e1fccad1b5447a8d7a8e67aa7b4a9798b7b", + "reference": "45261e1fccad1b5447a8d7a8e67aa7b4a9798b7b", "shasum": "" }, "require": { @@ -4642,7 +4642,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com/", "support": { - "source": "https://github.com/symfony/process/tree/v5.4.26" + "source": "https://github.com/symfony/process/tree/v5.4.28" }, "funding": [ { @@ -4658,7 +4658,7 @@ "type": "tidelift" } ], - "time": "2023-07-12T15:44:31+00:00" + "time": "2023-08-07T10:36:04+00:00" }, { "name": "symfony/service-contracts", @@ -5016,7 +5016,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "phpstan/phpstan-phpunit": 0 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { From 6ad6a9bf38c5753a0a2a4eb6c326511bb8780d69 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Fri, 8 Sep 2023 16:41:57 +0200 Subject: [PATCH 136/246] Updated changelog --- docs/changes/1.x/1.2.0.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index b92329adac..0749c64598 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -28,4 +28,5 @@ - Added Coveralls.io by [@Progi1984](https://github.com/Progi1984) in GH-2452 - Added support for PHP 8.2 & PHP 8.3 by [@Progi1984](https://github.com/Progi1984) in GH-2453 - Moved documention from ReadTheDocs to MkDocs & Github Pages by [@Progi1984](https://github.com/Progi1984) in GH-2465 -- Bump phpstan/phpstan-phpunit from 1.3.13 to 1.3.14 by [@dependabot](https://github.com/dependabot) in [#2457](https://github.com/PHPOffice/PHPWord/pull/2457) \ No newline at end of file +- Bump phpstan/phpstan-phpunit from 1.3.13 to 1.3.14 by [@dependabot](https://github.com/dependabot) in [#2457](https://github.com/PHPOffice/PHPWord/pull/2457) +- Bump symfony/process from 5.4.26 to 5.4.28 by [@dependabot](https://github.com/dependabot) in [#2456](https://github.com/PHPOffice/PHPWord/pull/2456) \ No newline at end of file From f3e3d331713cc8bf05f2572455f19556aea9ee3d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Sep 2023 15:05:02 +0000 Subject: [PATCH 137/246] Bump phpunit/phpunit from 9.6.10 to 9.6.11 Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.10 to 9.6.11. - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/9.6.11/ChangeLog-9.6.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.6.10...9.6.11) --- updated-dependencies: - dependency-name: phpunit/phpunit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/composer.lock b/composer.lock index cc9504298e..a4557e01da 100644 --- a/composer.lock +++ b/composer.lock @@ -955,16 +955,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.16.0", + "version": "v4.17.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "19526a33fb561ef417e822e85f08a00db4059c17" + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", - "reference": "19526a33fb561ef417e822e85f08a00db4059c17", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", "shasum": "" }, "require": { @@ -1005,9 +1005,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" }, - "time": "2023-06-25T14:52:30+00:00" + "time": "2023-08-13T19:53:39+00:00" }, { "name": "paragonie/random_compat", @@ -1894,16 +1894,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.10", + "version": "9.6.11", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328" + "reference": "810500e92855eba8a7a5319ae913be2da6f957b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a6d351645c3fe5a30f5e86be6577d946af65a328", - "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/810500e92855eba8a7a5319ae913be2da6f957b0", + "reference": "810500e92855eba8a7a5319ae913be2da6f957b0", "shasum": "" }, "require": { @@ -1977,7 +1977,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.10" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.11" }, "funding": [ { @@ -1993,7 +1993,7 @@ "type": "tidelift" } ], - "time": "2023-07-10T04:04:23+00:00" + "time": "2023-08-19T07:10:56+00:00" }, { "name": "psr/cache", From 9678f8145b069a027157764c087d17926d30350b Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Fri, 8 Sep 2023 17:09:36 +0200 Subject: [PATCH 138/246] Updated changelog --- docs/changes/1.x/1.2.0.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index 0749c64598..41ad3e5fdd 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -29,4 +29,5 @@ - Added support for PHP 8.2 & PHP 8.3 by [@Progi1984](https://github.com/Progi1984) in GH-2453 - Moved documention from ReadTheDocs to MkDocs & Github Pages by [@Progi1984](https://github.com/Progi1984) in GH-2465 - Bump phpstan/phpstan-phpunit from 1.3.13 to 1.3.14 by [@dependabot](https://github.com/dependabot) in [#2457](https://github.com/PHPOffice/PHPWord/pull/2457) -- Bump symfony/process from 5.4.26 to 5.4.28 by [@dependabot](https://github.com/dependabot) in [#2456](https://github.com/PHPOffice/PHPWord/pull/2456) \ No newline at end of file +- Bump symfony/process from 5.4.26 to 5.4.28 by [@dependabot](https://github.com/dependabot) in [#2456](https://github.com/PHPOffice/PHPWord/pull/2456) +- Bump phpunit/phpunit from 9.6.10 to 9.6.11 by [@dependabot](https://github.com/dependabot) in [#2455](https://github.com/PHPOffice/PHPWord/pull/2455) \ No newline at end of file From 275616aaa6aa8f1a6912dc51028556301c728d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E4=BF=8A?= Date: Fri, 15 Jul 2022 18:22:20 +0800 Subject: [PATCH 139/246] PDF Writer : Add config for defining the default font --- docs/changes/1.x/1.2.0.md | 1 + docs/usage/writers.md | 18 +++++++++++++++ phpstan-baseline.neon | 14 ++++++++++-- src/PhpWord/Settings.php | 23 +++++++++++++++++++ src/PhpWord/Writer/PDF/AbstractRenderer.php | 7 ++++++ src/PhpWord/Writer/PDF/DomPDF.php | 8 ++++++- src/PhpWord/Writer/PDF/MPDF.php | 7 +++++- src/PhpWord/Writer/PDF/TCPDF.php | 8 ++++++- tests/PhpWordTests/SettingsTest.php | 24 ++++++++++++++++++++ tests/PhpWordTests/Writer/PDF/DomPDFTest.php | 17 ++++++++++++++ tests/PhpWordTests/Writer/PDF/MPDFTest.php | 15 ++++++++++++ tests/PhpWordTests/Writer/PDF/TCPDFTest.php | 15 ++++++++++++ 12 files changed, 152 insertions(+), 5 deletions(-) diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index 41ad3e5fdd..ba8e6bfb38 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -10,6 +10,7 @@ - Word2007 Reader : Added option to disable loading images by [@aelliott1485](https://github.com/aelliott1485) in GH-2450 - HTML Writer : Added border-spacing to default styles for table by [@kernusr](https://github.com/kernusr) in GH-2451 - Word2007 Reader : Support for table cell borders and margins by [@kernusr](https://github.com/kernusr) in GH-2454 +- PDF Writer : Add config for defining the default font by [@MikeMaldini](https://github.com/MikeMaldini) in [#2262](https://github.com/PHPOffice/PHPWord/pull/2262) & [#2468](https://github.com/PHPOffice/PHPWord/pull/2468) ### Bug fixes diff --git a/docs/usage/writers.md b/docs/usage/writers.md index 86458cecef..8610ef3cf0 100644 --- a/docs/usage/writers.md +++ b/docs/usage/writers.md @@ -30,6 +30,24 @@ $writer = IOFactory::createWriter($oPhpWord, 'PDF'); $writer->save(__DIR__ . '/sample.pdf'); ``` +### Options + +You can define options like : +* `font`: default font + +Options must be defined before creating the writer. + +``` php +use PhpOffice\PhpWord\Settings; + +Settings::setPdfRendererOptions([ + 'font' => 'Arial' +]); + +$writer = IOFactory::createWriter($oPhpWord, 'PDF'); +$writer->save(__DIR__ . '/sample.pdf'); +``` + ## RTF The name of the writer is `RTF`. diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 4efe5078ef..e4b89e68dd 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -2002,7 +2002,7 @@ parameters: - message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:getFont\\(\\)\\.$#" - count: 1 + count: 2 path: tests/PhpWordTests/Writer/PDF/DomPDFTest.php - @@ -2047,7 +2047,7 @@ parameters: - message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" - count: 2 + count: 3 path: tests/PhpWordTests/Writer/PDF/DomPDFTest.php - @@ -2057,6 +2057,11 @@ parameters: - message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" + count: 2 + path: tests/PhpWordTests/Writer/PDF/MPDFTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:getFont\\(\\)\\.$#" count: 1 path: tests/PhpWordTests/Writer/PDF/MPDFTest.php @@ -2067,6 +2072,11 @@ parameters: - message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" + count: 2 + path: tests/PhpWordTests/Writer/PDF/TCPDFTest.php + + - + message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:getFont\\(\\)\\.$#" count: 1 path: tests/PhpWordTests/Writer/PDF/TCPDFTest.php diff --git a/src/PhpWord/Settings.php b/src/PhpWord/Settings.php index 22d067b0b8..d79cea6795 100644 --- a/src/PhpWord/Settings.php +++ b/src/PhpWord/Settings.php @@ -89,6 +89,13 @@ class Settings */ private static $pdfRendererName; + /** + * Options used for rendering PDF files. + * + * @var array + */ + private static $pdfRendererOptions = []; + /** * Directory Path to the external Library used for rendering PDF files. * @@ -226,6 +233,22 @@ public static function getPdfRendererPath(): ?string return self::$pdfRendererPath; } + /** + * Set options of the external library for rendering PDF files. + */ + public static function setPdfRendererOptions(array $options): void + { + self::$pdfRendererOptions = $options; + } + + /** + * Return the PDF Rendering Options. + */ + public static function getPdfRendererOptions(): array + { + return self::$pdfRendererOptions; + } + /** * Location of external library to use for rendering PDF files. * diff --git a/src/PhpWord/Writer/PDF/AbstractRenderer.php b/src/PhpWord/Writer/PDF/AbstractRenderer.php index e8be7c06a5..6ab6535f4c 100644 --- a/src/PhpWord/Writer/PDF/AbstractRenderer.php +++ b/src/PhpWord/Writer/PDF/AbstractRenderer.php @@ -81,6 +81,7 @@ abstract class AbstractRenderer extends HTML public function __construct(PhpWord $phpWord) { parent::__construct($phpWord); + if ($this->includeFile != null) { $includeFile = Settings::getPdfRendererPath() . '/' . $this->includeFile; if (file_exists($includeFile)) { @@ -93,6 +94,12 @@ public function __construct(PhpWord $phpWord) // @codeCoverageIgnoreEnd } } + + // Configuration + $options = Settings::getPdfRendererOptions(); + if (!empty($options['font'])) { + $this->setFont($options['font']); + } } /** diff --git a/src/PhpWord/Writer/PDF/DomPDF.php b/src/PhpWord/Writer/PDF/DomPDF.php index 26ceb79b55..ea167b4d0a 100644 --- a/src/PhpWord/Writer/PDF/DomPDF.php +++ b/src/PhpWord/Writer/PDF/DomPDF.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWord\Writer\PDF; use Dompdf\Dompdf as DompdfLib; +use Dompdf\Options; use PhpOffice\PhpWord\Writer\WriterInterface; /** @@ -42,7 +43,12 @@ class DomPDF extends AbstractRenderer implements WriterInterface */ protected function createExternalWriterInstance() { - return new DompdfLib(); + $options = new Options(); + if ($this->getFont()) { + $options->set('defaultFont', $this->getFont()); + } + + return new DompdfLib($options); } /** diff --git a/src/PhpWord/Writer/PDF/MPDF.php b/src/PhpWord/Writer/PDF/MPDF.php index f37b615561..481d4629b3 100644 --- a/src/PhpWord/Writer/PDF/MPDF.php +++ b/src/PhpWord/Writer/PDF/MPDF.php @@ -52,7 +52,12 @@ protected function createExternalWriterInstance() { $mPdfClass = $this->getMPdfClassName(); - return new $mPdfClass(); + $options = []; + if ($this->getFont()) { + $options['default_font'] = $this->getFont(); + } + + return new $mPdfClass($options); } /** diff --git a/src/PhpWord/Writer/PDF/TCPDF.php b/src/PhpWord/Writer/PDF/TCPDF.php index 02853ed7bc..0847a0c3e8 100644 --- a/src/PhpWord/Writer/PDF/TCPDF.php +++ b/src/PhpWord/Writer/PDF/TCPDF.php @@ -46,7 +46,13 @@ class TCPDF extends AbstractRenderer implements WriterInterface */ protected function createExternalWriterInstance($orientation, $unit, $paperSize) { - return new \TCPDF($orientation, $unit, $paperSize); + $instance = new \TCPDF($orientation, $unit, $paperSize); + + if ($this->getFont()) { + $instance->setFont($this->getFont(), $instance->getFontStyle(), $instance->getFontSizePt()); + } + + return $instance; } /** diff --git a/tests/PhpWordTests/SettingsTest.php b/tests/PhpWordTests/SettingsTest.php index 58490c4a4f..3868c3d813 100644 --- a/tests/PhpWordTests/SettingsTest.php +++ b/tests/PhpWordTests/SettingsTest.php @@ -41,6 +41,11 @@ class SettingsTest extends TestCase private $pdfRendererName; + /** + * @var array + */ + private $pdfRendererOptions; + private $pdfRendererPath; private $tempDir; @@ -56,6 +61,7 @@ protected function setUp(): void $this->measurementUnit = Settings::getMeasurementUnit(); $this->outputEscapingEnabled = Settings::isOutputEscapingEnabled(); $this->pdfRendererName = Settings::getPdfRendererName(); + $this->pdfRendererOptions = Settings::getPdfRendererOptions(); $this->pdfRendererPath = Settings::getPdfRendererPath(); $this->tempDir = Settings::getTempDir(); $this->zipClass = Settings::getZipClass(); @@ -70,6 +76,7 @@ protected function tearDown(): void Settings::setMeasurementUnit($this->measurementUnit); Settings::setOutputEscapingEnabled($this->outputEscapingEnabled); Settings::setPdfRendererName($this->pdfRendererName); + Settings::setPdfRendererOptions($this->pdfRendererOptions); Settings::setPdfRendererPath($this->pdfRendererPath); Settings::setTempDir($this->tempDir); Settings::setZipClass($this->zipClass); @@ -124,6 +131,23 @@ public function testSetGetPdfRenderer(): void self::assertEquals($domPdfPath, Settings::getPdfRendererPath()); } + /** + * Test set/get PDF renderer. + */ + public function testSetGetPdfOptions(): void + { + $domPdfPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/dompdf/dompdf'); + + self::assertEquals([], Settings::getPdfRendererOptions()); + + Settings::setPdfRendererOptions([ + 'font' => 'Arial', + ]); + self::assertEquals([ + 'font' => 'Arial', + ], Settings::getPdfRendererOptions()); + } + /** * Test set/get measurement unit. */ diff --git a/tests/PhpWordTests/Writer/PDF/DomPDFTest.php b/tests/PhpWordTests/Writer/PDF/DomPDFTest.php index 5365a9dcaa..789519ded1 100644 --- a/tests/PhpWordTests/Writer/PDF/DomPDFTest.php +++ b/tests/PhpWordTests/Writer/PDF/DomPDFTest.php @@ -75,4 +75,21 @@ public function testSetGetAbstractRendererProperties(): void $writer->setTempDir(Settings::getTempDir()); self::assertEquals(Settings::getTempDir(), $writer->getTempDir()); } + + /** + * Test set/get abstract renderer options. + */ + public function testSetGetAbstractRendererOptions(): void + { + define('DOMPDF_ENABLE_AUTOLOAD', false); + + $rendererName = Settings::PDF_RENDERER_DOMPDF; + $rendererLibraryPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/dompdf/dompdf'); + Settings::setPdfRenderer($rendererName, $rendererLibraryPath); + Settings::setPdfRendererOptions([ + 'font' => 'Arial', + ]); + $writer = new PDF(new PhpWord()); + self::assertEquals('Arial', $writer->getFont()); + } } diff --git a/tests/PhpWordTests/Writer/PDF/MPDFTest.php b/tests/PhpWordTests/Writer/PDF/MPDFTest.php index 44effe3b26..5905fa4eaf 100644 --- a/tests/PhpWordTests/Writer/PDF/MPDFTest.php +++ b/tests/PhpWordTests/Writer/PDF/MPDFTest.php @@ -50,4 +50,19 @@ public function testConstruct(): void unlink($file); } + + /** + * 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/PDF/TCPDFTest.php b/tests/PhpWordTests/Writer/PDF/TCPDFTest.php index 89e6acb701..c3f05b2b16 100644 --- a/tests/PhpWordTests/Writer/PDF/TCPDFTest.php +++ b/tests/PhpWordTests/Writer/PDF/TCPDFTest.php @@ -49,4 +49,19 @@ public function testConstruct(): void unlink($file); } + + /** + * Test set/get abstract renderer options. + */ + public function testSetGetAbstractRendererOptions(): void + { + $rendererName = Settings::PDF_RENDERER_TCPDF; + $rendererLibraryPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/tecnickcom/tcpdf'); + Settings::setPdfRenderer($rendererName, $rendererLibraryPath); + Settings::setPdfRendererOptions([ + 'font' => 'Arial', + ]); + $writer = new PDF(new PhpWord()); + self::assertEquals('Arial', $writer->getFont()); + } } From 84374a5ca694f8bbee4a6877dff548a94427c954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=A4drich?= Date: Mon, 1 Nov 2021 22:50:08 +0100 Subject: [PATCH 140/246] Add support for comments to reader --- src/PhpWord/PhpWord.php | 95 +++++++++++++++- src/PhpWord/Reader/Word2007/AbstractPart.php | 18 ++- src/PhpWord/Reader/Word2007/Comments.php | 109 +++++++++++++++++++ src/PhpWord/Reader/Word2007/Document.php | 7 +- 4 files changed, 225 insertions(+), 4 deletions(-) create mode 100644 src/PhpWord/Reader/Word2007/Comments.php diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index 69efa76723..ce27ebc04a 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -18,6 +18,8 @@ namespace PhpOffice\PhpWord; use BadMethodCallException; +use InvalidArgumentException; +use PhpOffice\PhpWord\Element\AbstractElement; use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\Exception\Exception; @@ -68,7 +70,14 @@ class PhpWord private $metadata = []; /** - * Create new instance. + * Comment reference cache + * + * @var array + */ + private $commentReferenceCache = []; + + /** + * Create new instance * * Collections are created dynamically */ @@ -325,4 +334,88 @@ 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; + } + + /** + * Cache commentReference (as well as commentRangeStart and commentRangeEnd) for later use + * + * @param 'start'|'end' $type + * @param string $id, + * @param $element + * + * @return self + */ + public function cacheCommentReference(string $type, string $id, AbstractElement $element) + { + //dump('cacheCommentReference', func_get_args(), array_key_exists($id, $this->commentReferenceCache)); + if (!in_array($type, [ 'start', 'end' ])) { + throw new InvalidArgumentException('Type must be "start" or "end"'); + } + + if (!array_key_exists($id, $this->commentReferenceCache)) { + $this->commentReferenceCache[$id] = (object)[ + "start" => null, + "end" => null + ]; + } + $this->commentReferenceCache[$id]->{$type} = $element; + + return $this; + } + + public function getCommentReference(string $id) + { + if (!array_key_exists($id, $this->commentReferenceCache)) { + //dd($this->commentReferenceCache); + throw new InvalidArgumentException('Comment with id '.$id.' isn\'t referenced in document'); + } + return $this->commentReferenceCache[$id]; + } } diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 3ab8995f9e..7809628e14 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -126,6 +126,11 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par // Paragraph style $paragraphStyle = null; $headingDepth = null; + if ($xmlReader->elementExists('w:commentReference', $domNode) || $xmlReader->elementExists('w:commentRangeStart', $domNode) || $xmlReader->elementExists('w:commentRangeEnd', $domNode)) { + $nodes = $xmlReader->getElements('w:commentReference|w:commentRangeStart|w:commentRangeEnd', $domNode); + $node = current(iterator_to_array($nodes)); + $id = $node->attributes->getNamedItem('id')->value; + } if ($xmlReader->elementExists('w:pPr', $domNode)) { $paragraphStyle = $this->readParagraphStyle($xmlReader, $domNode); $headingDepth = $this->getHeadingDepth($paragraphStyle); @@ -182,7 +187,7 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par $parent->addTitle($textContent, $headingDepth); } else { // Text and TextRun - $textRunContainers = $xmlReader->countElements('w:r|w:ins|w:del|w:hyperlink|w:smartTag', $domNode); + $textRunContainers = $xmlReader->countElements('w:r|w:ins|w:del|w:hyperlink|w:smartTag|w:commentReference|w:commentRangeStart|w:commentRangeEnd', $domNode); if (0 === $textRunContainers) { $parent->addTextBreak(null, $paragraphStyle); } else { @@ -230,7 +235,7 @@ private function getHeadingDepth(?array $paragraphStyle = null) */ protected function readRun(XMLReader $xmlReader, DOMElement $domNode, $parent, $docPart, $paragraphStyle = null): void { - if (in_array($domNode->nodeName, ['w:ins', 'w:del', 'w:smartTag', 'w:hyperlink'])) { + if (in_array($domNode->nodeName, array('w:ins', 'w:del', 'w:smartTag', 'w:hyperlink', 'w:commentReference'))) { $nodes = $xmlReader->getElements('*', $domNode); foreach ($nodes as $node) { $this->readRun($xmlReader, $node, $parent, $docPart, $paragraphStyle); @@ -242,6 +247,15 @@ protected function readRun(XMLReader $xmlReader, DOMElement $domNode, $parent, $ $this->readRunChild($xmlReader, $node, $parent, $docPart, $paragraphStyle, $fontStyle); } } + + if($xmlReader->elementExists('.//*["commentReference"=local-name()]', $domNode)) { + $curEl = iterator_to_array($xmlReader->getElements('.//*["commentReference"=local-name()]', $domNode))[0]; + $id = $curEl->attributes->getNamedItem('id')->value; + //$path = './/*[("commentRangeStart"=local-name() or "commentRangeEnd"=local-name()) and @*[local-name()="id" and .="'.$id.'"]]'; + //$range = $xmlReader->getElements($path); + $this->phpWord->cacheCommentReference('start', $id, $parent->getElement($parent->countElements() - 1)); + $this->phpWord->cacheCommentReference('end', $id, $parent->getElement($parent->countElements() - 1)); + } } /** diff --git a/src/PhpWord/Reader/Word2007/Comments.php b/src/PhpWord/Reader/Word2007/Comments.php new file mode 100644 index 0000000000..18c2016bf2 --- /dev/null +++ b/src/PhpWord/Reader/Word2007/Comments.php @@ -0,0 +1,109 @@ +getDomFromZip($this->docFile, $this->xmlFile); + + //$xmlReader2 = new XMLReader(); + //$xmlReader2->getDomFromZip($this->docFile, 'word/document.xml'); + //dd($xmlReader2); + + $comments = $phpWord->getComments(); + + $nodes = $xmlReader->getElements('*'); + if ($nodes->length > 0) { + foreach ($nodes as $node) { + $name = str_replace('w:', '', $node->nodeName); + $value = $xmlReader->getAttribute('w:author', $node); + $author = $xmlReader->getAttribute('w:author', $node); + $date = $xmlReader->getAttribute('w:date', $node); + $initials = $xmlReader->getAttribute('w:initials', $node); + $id = $xmlReader->getAttribute('w:id', $node); + $element = new Comment($author, new DateTime($date), $initials);//$this->getElement($phpWord, $id); + //$element->set + // $range = $xmlReader2->getElements('.//*[("commentRangeStart"=local-name() or "commentRangeEnd"=local-name()) and @*[local-name()="id" and .="'.$id.'"]]'); + try { + unset($range); + $range = $phpWord->getCommentReference($id); + $range->start->setCommentRangeStart($element); + $range->end->setCommentRangeEnd($element); + } catch(\Exception $e) { + //dd('range', [$element, $id, $node, $node->C14N(), $range ?? null, $e]); + } + //dd($startElement, $endElement, current(current($phpWord->getSections())->getElements())); + //dump($element, $range); + //dd($element, $node, $id, $node->C14N()); + $method = 'set' . $name; + //dump([$element, $id, $name, $value, $author, $date, $initials, $method, $xmlReader->getElements('w:p/w:r/w:t', $node)]); + //dd('dsf'); + $pNodes = $xmlReader->getElements('w:p/w:r', $node); + foreach ($pNodes as $pNode) { + //dump(['>', $xmlReader, $pNode, $node, $this->collection, '<']); + $this->readRun($xmlReader, $pNode, $element, $this->collection); + } + + /*if (in_array($name, $this::$booleanProperties)) { + if ($value == 'false') { + $comments->$method(false); + } else { + $comments->$method(true); + } + } else*/if (method_exists($this, $method)) { + $this->$method($xmlReader, $phpWord, $node); + } elseif (method_exists($comments, $method)) { + $comments->$method($value); + } elseif (method_exists($phpWord, $method)) { + $phpWord->$method($value); + } elseif (method_exists($comments, 'addItem')) { + $comments->addItem($element); + } + } + } + } + + /** + * Searches for the element with the given relationId + * + * @param PhpWord $phpWord + * @param int $relationId + * @return \PhpOffice\PhpWord\Element\AbstractContainer|null + */ + private function getElement(PhpWord $phpWord, $relationId) + { + $getMethod = "get{$this->collection}"; + //$getMethod = "getTrackChange"; + $collection = $phpWord->$getMethod();//->getItems(); + + //not found by key, looping to search by relationId + foreach ($collection as $collectionElement) { + if ($collectionElement->getRelationId() == $relationId) { + return $collectionElement; + } + } + + return null; + } +} diff --git a/src/PhpWord/Reader/Word2007/Document.php b/src/PhpWord/Reader/Word2007/Document.php index da42bddc9e..55d9d3a4eb 100644 --- a/src/PhpWord/Reader/Word2007/Document.php +++ b/src/PhpWord/Reader/Word2007/Document.php @@ -36,7 +36,7 @@ class Document extends AbstractPart * * @var \PhpOffice\PhpWord\PhpWord */ - private $phpWord; + protected $phpWord; /** * Read document.xml. @@ -170,4 +170,9 @@ private function readWSectPrNode(XMLReader $xmlReader, DOMElement $node, Section $section->setStyle($style); $this->readHeaderFooter($style, $section); } + + protected function cacheCommentReference(string $type, string $id, $element) + { + $this->phpWord->cacheCommentReference($type, $id, $element); + } } From 7222e6ce2f36347c1a101c3438e3b71b529a9384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=A4drich?= Date: Tue, 2 Nov 2021 19:13:43 +0100 Subject: [PATCH 141/246] Add test for comments in reader --- tests/PhpWord/Reader/Word2007Test.php | 97 ++++++++++++++++++ .../documents/reader-ooxml-comments.docx | Bin 0 -> 12895 bytes 2 files changed, 97 insertions(+) create mode 100644 tests/PhpWord/Reader/Word2007Test.php create mode 100644 tests/PhpWord/_files/documents/reader-ooxml-comments.docx diff --git a/tests/PhpWord/Reader/Word2007Test.php b/tests/PhpWord/Reader/Word2007Test.php new file mode 100644 index 0000000000..543bd80de9 --- /dev/null +++ b/tests/PhpWord/Reader/Word2007Test.php @@ -0,0 +1,97 @@ +assertTrue($object->canRead($filename)); + } + + /** + * Can read exception + */ + public function testCanReadFailed() + { + $object = new Word2007(); + $filename = __DIR__ . '/../_files/documents/foo.docx'; + $this->assertFalse($object->canRead($filename)); + } + + /** + * Load + */ + public function testLoad() + { + $filename = __DIR__ . '/../_files/documents/reader.docx'; + $phpWord = IOFactory::load($filename); + + $this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); + $this->assertTrue($phpWord->getSettings()->hasDoNotTrackMoves()); + $this->assertFalse($phpWord->getSettings()->hasDoNotTrackFormatting()); + $this->assertEquals(100, $phpWord->getSettings()->getZoom()); + + $doc = TestHelperDOCX::getDocument($phpWord); + $this->assertEquals('0', $doc->getElementAttribute('/w:document/w:body/w:p/w:r[w:t/node()="italics"]/w:rPr/w:b', 'w:val')); + } + + /** + * Load a Word 2011 file + */ + public function testLoadWord2011() + { + $filename = __DIR__ . '/../_files/documents/reader-2011.docx'; + $phpWord = IOFactory::load($filename); + + $this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); + + $doc = TestHelperDOCX::getDocument($phpWord); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[3]/w:r/w:pict/v:shape/v:imagedata')); + } + + public function testLoadComments() + { + $filename = __DIR__ . '/../_files/documents/reader-ooxml-comments.docx'; + $phpWord = IOFactory::load($filename); + + $this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); + + //$doc = TestHelperDOCX::getDocument($phpWord); + $comment = new Comment('shaedrich', new DateTime('2021-10-28T13:56:00Z'), 'SH'); + $comment2 = $phpWord->getComments()[0]; + $this->assertEquals($comment->getAuthor(), $comment2->getAuthor()); + $this->assertEquals($comment->getInitials(), $comment2->getInitials()); + } +} diff --git a/tests/PhpWord/_files/documents/reader-ooxml-comments.docx b/tests/PhpWord/_files/documents/reader-ooxml-comments.docx new file mode 100644 index 0000000000000000000000000000000000000000..4748da68386adcf536f0657f5462ef6e40f20795 GIT binary patch literal 12895 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 literal 0 HcmV?d00001 From 400ea8cc2a67d6b4b9b6ed1dfc12feb0074a0a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=A4drich?= Date: Thu, 4 Nov 2021 15:24:14 +0100 Subject: [PATCH 142/246] Add comments step part to reader --- src/PhpWord/Reader/Word2007.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/PhpWord/Reader/Word2007.php b/src/PhpWord/Reader/Word2007.php index 1febe0ff0a..f7c11c2868 100644 --- a/src/PhpWord/Reader/Word2007.php +++ b/src/PhpWord/Reader/Word2007.php @@ -57,7 +57,8 @@ public function load($docFile) ['stepPart' => 'document', 'stepItems' => [ 'endnotes' => 'Endnotes', 'footnotes' => 'Footnotes', - 'settings' => 'Settings', + 'settings' => 'Settings', + 'comments' => 'Comments' ]], ]; From 34db7cf3842c064963c522d6b22bbe969e159cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=A4drich?= Date: Sun, 7 Nov 2021 02:45:11 +0100 Subject: [PATCH 143/246] Fix wrong testing namespace --- src/PhpWord/Reader/Word2007/Comments.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Reader/Word2007/Comments.php b/src/PhpWord/Reader/Word2007/Comments.php index 18c2016bf2..4851e57938 100644 --- a/src/PhpWord/Reader/Word2007/Comments.php +++ b/src/PhpWord/Reader/Word2007/Comments.php @@ -1,6 +1,6 @@ Date: Wed, 13 Sep 2023 17:38:56 +0200 Subject: [PATCH 144/246] Word2007 Reader : Added support for Comments --- docs/changes/1.x/1.2.0.md | 1 + docs/index.md | 2 +- phpstan-baseline.neon | 10 -- src/PhpWord/Collection/AbstractCollection.php | 2 +- src/PhpWord/PhpWord.php | 53 +--------- src/PhpWord/Reader/Word2007.php | 72 ++++++++----- src/PhpWord/Reader/Word2007/AbstractPart.php | 96 +++++++++++++++-- src/PhpWord/Reader/Word2007/Comments.php | 97 ++++-------------- src/PhpWord/Reader/Word2007/Document.php | 7 +- tests/PhpWord/Reader/Word2007Test.php | 97 ------------------ .../Collection/CollectionTest.php | 17 ++- tests/PhpWordTests/Reader/Word2007Test.php | 41 ++++++++ .../_files/documents/reader-comments.docx} | Bin 13 files changed, 216 insertions(+), 279 deletions(-) delete mode 100644 tests/PhpWord/Reader/Word2007Test.php rename tests/{PhpWord/_files/documents/reader-ooxml-comments.docx => PhpWordTests/_files/documents/reader-comments.docx} (100%) diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index ba8e6bfb38..5b055ca7c0 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -11,6 +11,7 @@ - HTML Writer : Added border-spacing to default styles for table by [@kernusr](https://github.com/kernusr) in GH-2451 - Word2007 Reader : Support for table cell borders and margins by [@kernusr](https://github.com/kernusr) in GH-2454 - PDF Writer : Add config for defining the default font by [@MikeMaldini](https://github.com/MikeMaldini) in [#2262](https://github.com/PHPOffice/PHPWord/pull/2262) & [#2468](https://github.com/PHPOffice/PHPWord/pull/2468) +- Word2007 Reader : Added support for Comments by [@shaedrich](https://github.com/shaedrich) in [#2161](https://github.com/PHPOffice/PHPWord/pull/2161) & [#2469](https://github.com/PHPOffice/PHPWord/pull/2469) ### Bug fixes diff --git a/docs/index.md b/docs/index.md index 1398fd90c4..bd38dd3238 100644 --- a/docs/index.md +++ b/docs/index.md @@ -95,7 +95,7 @@ Below are the supported features for each file formats. | | Footer | :material-check: | | | | | | | Footnote | :material-check: | | | | | | | Endnote | :material-check: | | | | | -| | Comments | | | | | | +| | Comments | :material-check: | | | | | | **Graphs** | 2D basic graphs | | | | | | | | 2D advanced graphs | | | | | | | | 3D graphs | | | | | | diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index e4b89e68dd..9d6e6366d4 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -230,11 +230,6 @@ parameters: count: 2 path: src/PhpWord/Reader/Word2007/AbstractPart.php - - - message: "#^Call to method setChangeInfo\\(\\) on an unknown class PhpOffice\\\\PhpWord\\\\Reader\\\\Word2007\\\\AbstractElement\\.$#" - count: 1 - path: src/PhpWord/Reader/Word2007/AbstractPart.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Reader\\\\Word2007\\\\AbstractPart\\:\\:getHeadingDepth\\(\\) never returns float so it can be removed from the return type\\.$#" count: 1 @@ -250,11 +245,6 @@ parameters: count: 1 path: src/PhpWord/Reader/Word2007/AbstractPart.php - - - message: "#^PHPDoc tag @var for variable \\$element contains unknown class PhpOffice\\\\PhpWord\\\\Reader\\\\Word2007\\\\AbstractElement\\.$#" - count: 1 - path: src/PhpWord/Reader/Word2007/AbstractPart.php - - message: "#^Parameter \\#1 \\$count of method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractContainer\\:\\:addTextBreak\\(\\) expects int, null given\\.$#" count: 1 diff --git a/src/PhpWord/Collection/AbstractCollection.php b/src/PhpWord/Collection/AbstractCollection.php index 70c92689b8..78b5b891b8 100644 --- a/src/PhpWord/Collection/AbstractCollection.php +++ b/src/PhpWord/Collection/AbstractCollection.php @@ -79,7 +79,7 @@ public function setItem($index, $item): void */ public function addItem($item) { - $index = $this->countItems() + 1; + $index = $this->countItems(); $this->items[$index] = $item; return $index; diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index ce27ebc04a..da57f38d29 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -18,8 +18,6 @@ namespace PhpOffice\PhpWord; use BadMethodCallException; -use InvalidArgumentException; -use PhpOffice\PhpWord\Element\AbstractElement; use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\Exception\Exception; @@ -70,14 +68,7 @@ class PhpWord private $metadata = []; /** - * Comment reference cache - * - * @var array - */ - private $commentReferenceCache = []; - - /** - * Create new instance + * Create new instance. * * Collections are created dynamically */ @@ -336,7 +327,7 @@ public function save($filename, $format = 'Word2007', $download = false) } /** - * Create new section + * Create new section. * * @deprecated 0.10.0 * @@ -352,7 +343,7 @@ public function createSection($settings = null) } /** - * Get document properties object + * Get document properties object. * * @deprecated 0.12.0 * @@ -366,7 +357,7 @@ public function getDocumentProperties() } /** - * Set document properties object + * Set document properties object. * * @deprecated 0.12.0 * @@ -382,40 +373,4 @@ public function setDocumentProperties($documentProperties) return $this; } - - /** - * Cache commentReference (as well as commentRangeStart and commentRangeEnd) for later use - * - * @param 'start'|'end' $type - * @param string $id, - * @param $element - * - * @return self - */ - public function cacheCommentReference(string $type, string $id, AbstractElement $element) - { - //dump('cacheCommentReference', func_get_args(), array_key_exists($id, $this->commentReferenceCache)); - if (!in_array($type, [ 'start', 'end' ])) { - throw new InvalidArgumentException('Type must be "start" or "end"'); - } - - if (!array_key_exists($id, $this->commentReferenceCache)) { - $this->commentReferenceCache[$id] = (object)[ - "start" => null, - "end" => null - ]; - } - $this->commentReferenceCache[$id]->{$type} = $element; - - return $this; - } - - public function getCommentReference(string $id) - { - if (!array_key_exists($id, $this->commentReferenceCache)) { - //dd($this->commentReferenceCache); - throw new InvalidArgumentException('Comment with id '.$id.' isn\'t referenced in document'); - } - return $this->commentReferenceCache[$id]; - } } diff --git a/src/PhpWord/Reader/Word2007.php b/src/PhpWord/Reader/Word2007.php index f7c11c2868..bb20a8fed2 100644 --- a/src/PhpWord/Reader/Word2007.php +++ b/src/PhpWord/Reader/Word2007.php @@ -17,7 +17,10 @@ namespace PhpOffice\PhpWord\Reader; +use Exception; +use PhpOffice\PhpWord\Element\AbstractElement; use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Reader\Word2007\AbstractPart; use PhpOffice\PhpWord\Shared\XMLReader; use PhpOffice\PhpWord\Shared\ZipArchive; @@ -42,24 +45,34 @@ public function load($docFile) { $phpWord = new PhpWord(); $relationships = $this->readRelationships($docFile); + $commentRefs = []; $steps = [ - ['stepPart' => 'document', 'stepItems' => [ - 'styles' => 'Styles', - 'numbering' => 'Numbering', - ]], - ['stepPart' => 'main', 'stepItems' => [ - 'officeDocument' => 'Document', - 'core-properties' => 'DocPropsCore', - 'extended-properties' => 'DocPropsApp', - 'custom-properties' => 'DocPropsCustom', - ]], - ['stepPart' => 'document', 'stepItems' => [ - 'endnotes' => 'Endnotes', - 'footnotes' => 'Footnotes', - 'settings' => 'Settings', - 'comments' => 'Comments' - ]], + [ + 'stepPart' => 'document', + 'stepItems' => [ + 'styles' => 'Styles', + 'numbering' => 'Numbering', + ], + ], + [ + 'stepPart' => 'main', + 'stepItems' => [ + 'officeDocument' => 'Document', + 'core-properties' => 'DocPropsCore', + 'extended-properties' => 'DocPropsApp', + 'custom-properties' => 'DocPropsCustom', + ], + ], + [ + 'stepPart' => 'document', + 'stepItems' => [ + 'endnotes' => 'Endnotes', + 'footnotes' => 'Footnotes', + 'settings' => 'Settings', + 'comments' => 'Comments', + ], + ], ]; foreach ($steps as $step) { @@ -73,7 +86,8 @@ public function load($docFile) if (isset($stepItems[$relType])) { $partName = $stepItems[$relType]; $xmlFile = $relItem['target']; - $this->readPart($phpWord, $relationships, $partName, $docFile, $xmlFile); + $part = $this->readPart($phpWord, $relationships, $commentRefs, $partName, $docFile, $xmlFile); + $commentRefs = $part->getCommentReferences(); } } } @@ -84,21 +98,23 @@ public function load($docFile) /** * Read document part. * - * @param array $relationships - * @param string $partName - * @param string $docFile - * @param string $xmlFile + * @param array> $commentRefs */ - private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile, $xmlFile): void + private function readPart(PhpWord $phpWord, array $relationships, array $commentRefs, string $partName, string $docFile, string $xmlFile): AbstractPart { $partClass = "PhpOffice\\PhpWord\\Reader\\Word2007\\{$partName}"; - if (class_exists($partClass)) { - /** @var \PhpOffice\PhpWord\Reader\Word2007\AbstractPart $part Type hint */ - $part = new $partClass($docFile, $xmlFile); - $part->setImageLoading($this->hasImageLoading()); - $part->setRels($relationships); - $part->read($phpWord); + if (!class_exists($partClass)) { + throw new Exception(sprintf('The part "%s" doesn\'t exist', $partClass)); } + + /** @var AbstractPart $part Type hint */ + $part = new $partClass($docFile, $xmlFile); + $part->setImageLoading($this->hasImageLoading()); + $part->setRels($relationships); + $part->setCommentReferences($commentRefs); + $part->read($phpWord); + + return $part; } /** diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 7809628e14..dc61b09356 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -19,8 +19,10 @@ use DateTime; use DOMElement; +use InvalidArgumentException; use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType; use PhpOffice\PhpWord\Element\AbstractContainer; +use PhpOffice\PhpWord\Element\AbstractElement; use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\PhpWord; @@ -67,6 +69,13 @@ abstract class AbstractPart */ protected $rels = []; + /** + * Comment references. + * + * @var array> + */ + protected $commentRefs = []; + /** * Image Loading. * @@ -113,6 +122,62 @@ public function hasImageLoading(): bool return $this->imageLoading; } + /** + * Get comment references. + * + * @return array> + */ + public function getCommentReferences(): array + { + return $this->commentRefs; + } + + /** + * Set comment references. + * + * @param array> $commentRefs + */ + public function setCommentReferences(array $commentRefs): self + { + $this->commentRefs = $commentRefs; + + return $this; + } + + /** + * Set comment reference. + */ + private function setCommentReference(string $type, string $id, AbstractElement $element): self + { + if (!in_array($type, ['start', 'end'])) { + throw new InvalidArgumentException('Type must be "start" or "end"'); + } + + if (!array_key_exists($id, $this->commentRefs)) { + $this->commentRefs[$id] = [ + 'start' => null, + 'end' => null, + ]; + } + $this->commentRefs[$id][$type] = $element; + + return $this; + } + + /** + * Get comment reference. + * + * @return array + */ + protected function getCommentReference(string $id): array + { + if (!array_key_exists($id, $this->commentRefs)) { + throw new InvalidArgumentException(sprintf('Comment with id %s isn\'t referenced in document', $id)); + } + + return $this->commentRefs[$id]; + } + /** * Read w:p. * @@ -126,10 +191,18 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par // Paragraph style $paragraphStyle = null; $headingDepth = null; - if ($xmlReader->elementExists('w:commentReference', $domNode) || $xmlReader->elementExists('w:commentRangeStart', $domNode) || $xmlReader->elementExists('w:commentRangeEnd', $domNode)) { + if ($xmlReader->elementExists('w:commentReference', $domNode) + || $xmlReader->elementExists('w:commentRangeStart', $domNode) + || $xmlReader->elementExists('w:commentRangeEnd', $domNode) + ) { $nodes = $xmlReader->getElements('w:commentReference|w:commentRangeStart|w:commentRangeEnd', $domNode); $node = current(iterator_to_array($nodes)); - $id = $node->attributes->getNamedItem('id')->value; + if ($node) { + $attributeIdentifier = $node->attributes->getNamedItem('id'); + if ($attributeIdentifier) { + $id = $attributeIdentifier->nodeValue; + } + } } if ($xmlReader->elementExists('w:pPr', $domNode)) { $paragraphStyle = $this->readParagraphStyle($xmlReader, $domNode); @@ -235,7 +308,7 @@ private function getHeadingDepth(?array $paragraphStyle = null) */ protected function readRun(XMLReader $xmlReader, DOMElement $domNode, $parent, $docPart, $paragraphStyle = null): void { - if (in_array($domNode->nodeName, array('w:ins', 'w:del', 'w:smartTag', 'w:hyperlink', 'w:commentReference'))) { + if (in_array($domNode->nodeName, ['w:ins', 'w:del', 'w:smartTag', 'w:hyperlink', 'w:commentReference'])) { $nodes = $xmlReader->getElements('*', $domNode); foreach ($nodes as $node) { $this->readRun($xmlReader, $node, $parent, $docPart, $paragraphStyle); @@ -248,13 +321,15 @@ protected function readRun(XMLReader $xmlReader, DOMElement $domNode, $parent, $ } } - if($xmlReader->elementExists('.//*["commentReference"=local-name()]', $domNode)) { - $curEl = iterator_to_array($xmlReader->getElements('.//*["commentReference"=local-name()]', $domNode))[0]; - $id = $curEl->attributes->getNamedItem('id')->value; - //$path = './/*[("commentRangeStart"=local-name() or "commentRangeEnd"=local-name()) and @*[local-name()="id" and .="'.$id.'"]]'; - //$range = $xmlReader->getElements($path); - $this->phpWord->cacheCommentReference('start', $id, $parent->getElement($parent->countElements() - 1)); - $this->phpWord->cacheCommentReference('end', $id, $parent->getElement($parent->countElements() - 1)); + if ($xmlReader->elementExists('.//*["commentReference"=local-name()]', $domNode)) { + $node = iterator_to_array($xmlReader->getElements('.//*["commentReference"=local-name()]', $domNode))[0]; + $attributeIdentifier = $node->attributes->getNamedItem('id'); + if ($attributeIdentifier) { + $id = $attributeIdentifier->nodeValue; + + $this->setCommentReference('start', $id, $parent->getElement($parent->countElements() - 1)); + $this->setCommentReference('end', $id, $parent->getElement($parent->countElements() - 1)); + } } } @@ -353,6 +428,7 @@ protected function readRunChild(XMLReader $xmlReader, DOMElement $node, Abstract $type = ($runParent->nodeName == 'w:del') ? TrackChange::DELETED : TrackChange::INSERTED; $author = $runParent->getAttribute('w:author'); $date = DateTime::createFromFormat('Y-m-d\TH:i:s\Z', $runParent->getAttribute('w:date')); + $date = $date instanceof DateTime ? $date : null; $element->setChangeInfo($type, $author, $date); } } diff --git a/src/PhpWord/Reader/Word2007/Comments.php b/src/PhpWord/Reader/Word2007/Comments.php index 4851e57938..61b31713b5 100644 --- a/src/PhpWord/Reader/Word2007/Comments.php +++ b/src/PhpWord/Reader/Word2007/Comments.php @@ -5,13 +5,12 @@ use DateTime; use PhpOffice\PhpWord\Element\Comment; use PhpOffice\PhpWord\PhpWord; -use PhpOffice\PhpWord\Reader\Word2007\AbstractPart; use PhpOffice\PhpWord\Shared\XMLReader; class Comments extends AbstractPart { /** - * Collection name comments + * Collection name comments. * * @var string */ @@ -19,91 +18,39 @@ class Comments extends AbstractPart /** * Read settings.xml. - * - * @param \PhpOffice\PhpWord\PhpWord $phpWord */ - public function read(PhpWord $phpWord) + public function read(PhpWord $phpWord): void { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); - //$xmlReader2 = new XMLReader(); - //$xmlReader2->getDomFromZip($this->docFile, 'word/document.xml'); - //dd($xmlReader2); - $comments = $phpWord->getComments(); $nodes = $xmlReader->getElements('*'); - if ($nodes->length > 0) { - foreach ($nodes as $node) { - $name = str_replace('w:', '', $node->nodeName); - $value = $xmlReader->getAttribute('w:author', $node); - $author = $xmlReader->getAttribute('w:author', $node); - $date = $xmlReader->getAttribute('w:date', $node); - $initials = $xmlReader->getAttribute('w:initials', $node); - $id = $xmlReader->getAttribute('w:id', $node); - $element = new Comment($author, new DateTime($date), $initials);//$this->getElement($phpWord, $id); - //$element->set - // $range = $xmlReader2->getElements('.//*[("commentRangeStart"=local-name() or "commentRangeEnd"=local-name()) and @*[local-name()="id" and .="'.$id.'"]]'); - try { - unset($range); - $range = $phpWord->getCommentReference($id); - $range->start->setCommentRangeStart($element); - $range->end->setCommentRangeEnd($element); - } catch(\Exception $e) { - //dd('range', [$element, $id, $node, $node->C14N(), $range ?? null, $e]); - } - //dd($startElement, $endElement, current(current($phpWord->getSections())->getElements())); - //dump($element, $range); - //dd($element, $node, $id, $node->C14N()); - $method = 'set' . $name; - //dump([$element, $id, $name, $value, $author, $date, $initials, $method, $xmlReader->getElements('w:p/w:r/w:t', $node)]); - //dd('dsf'); - $pNodes = $xmlReader->getElements('w:p/w:r', $node); - foreach ($pNodes as $pNode) { - //dump(['>', $xmlReader, $pNode, $node, $this->collection, '<']); - $this->readRun($xmlReader, $pNode, $element, $this->collection); - } - /*if (in_array($name, $this::$booleanProperties)) { - if ($value == 'false') { - $comments->$method(false); - } else { - $comments->$method(true); - } - } else*/if (method_exists($this, $method)) { - $this->$method($xmlReader, $phpWord, $node); - } elseif (method_exists($comments, $method)) { - $comments->$method($value); - } elseif (method_exists($phpWord, $method)) { - $phpWord->$method($value); - } elseif (method_exists($comments, 'addItem')) { - $comments->addItem($element); - } - } - } - } + foreach ($nodes as $node) { + $name = str_replace('w:', '', $node->nodeName); - /** - * Searches for the element with the given relationId - * - * @param PhpWord $phpWord - * @param int $relationId - * @return \PhpOffice\PhpWord\Element\AbstractContainer|null - */ - private function getElement(PhpWord $phpWord, $relationId) - { - $getMethod = "get{$this->collection}"; - //$getMethod = "getTrackChange"; - $collection = $phpWord->$getMethod();//->getItems(); + $author = $xmlReader->getAttribute('w:author', $node); + $date = $xmlReader->getAttribute('w:date', $node); + $initials = $xmlReader->getAttribute('w:initials', $node); + + $element = new Comment($author, new DateTime($date), $initials); - //not found by key, looping to search by relationId - foreach ($collection as $collectionElement) { - if ($collectionElement->getRelationId() == $relationId) { - return $collectionElement; + $range = $this->getCommentReference($xmlReader->getAttribute('w:id', $node)); + if ($range['start']) { + $range['start']->setCommentRangeStart($element); + } + if ($range['end']) { + $range['end']->setCommentRangeEnd($element); } - } - return null; + $pNodes = $xmlReader->getElements('w:p/w:r', $node); + foreach ($pNodes as $pNode) { + $this->readRun($xmlReader, $pNode, $element, $this->collection); + } + + $phpWord->getComments()->addItem($element); + } } } diff --git a/src/PhpWord/Reader/Word2007/Document.php b/src/PhpWord/Reader/Word2007/Document.php index 55d9d3a4eb..da42bddc9e 100644 --- a/src/PhpWord/Reader/Word2007/Document.php +++ b/src/PhpWord/Reader/Word2007/Document.php @@ -36,7 +36,7 @@ class Document extends AbstractPart * * @var \PhpOffice\PhpWord\PhpWord */ - protected $phpWord; + private $phpWord; /** * Read document.xml. @@ -170,9 +170,4 @@ private function readWSectPrNode(XMLReader $xmlReader, DOMElement $node, Section $section->setStyle($style); $this->readHeaderFooter($style, $section); } - - protected function cacheCommentReference(string $type, string $id, $element) - { - $this->phpWord->cacheCommentReference($type, $id, $element); - } } diff --git a/tests/PhpWord/Reader/Word2007Test.php b/tests/PhpWord/Reader/Word2007Test.php deleted file mode 100644 index 543bd80de9..0000000000 --- a/tests/PhpWord/Reader/Word2007Test.php +++ /dev/null @@ -1,97 +0,0 @@ -assertTrue($object->canRead($filename)); - } - - /** - * Can read exception - */ - public function testCanReadFailed() - { - $object = new Word2007(); - $filename = __DIR__ . '/../_files/documents/foo.docx'; - $this->assertFalse($object->canRead($filename)); - } - - /** - * Load - */ - public function testLoad() - { - $filename = __DIR__ . '/../_files/documents/reader.docx'; - $phpWord = IOFactory::load($filename); - - $this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); - $this->assertTrue($phpWord->getSettings()->hasDoNotTrackMoves()); - $this->assertFalse($phpWord->getSettings()->hasDoNotTrackFormatting()); - $this->assertEquals(100, $phpWord->getSettings()->getZoom()); - - $doc = TestHelperDOCX::getDocument($phpWord); - $this->assertEquals('0', $doc->getElementAttribute('/w:document/w:body/w:p/w:r[w:t/node()="italics"]/w:rPr/w:b', 'w:val')); - } - - /** - * Load a Word 2011 file - */ - public function testLoadWord2011() - { - $filename = __DIR__ . '/../_files/documents/reader-2011.docx'; - $phpWord = IOFactory::load($filename); - - $this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); - - $doc = TestHelperDOCX::getDocument($phpWord); - $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[3]/w:r/w:pict/v:shape/v:imagedata')); - } - - public function testLoadComments() - { - $filename = __DIR__ . '/../_files/documents/reader-ooxml-comments.docx'; - $phpWord = IOFactory::load($filename); - - $this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); - - //$doc = TestHelperDOCX::getDocument($phpWord); - $comment = new Comment('shaedrich', new DateTime('2021-10-28T13:56:00Z'), 'SH'); - $comment2 = $phpWord->getComments()[0]; - $this->assertEquals($comment->getAuthor(), $comment2->getAuthor()); - $this->assertEquals($comment->getInitials(), $comment2->getInitials()); - } -} diff --git a/tests/PhpWordTests/Collection/CollectionTest.php b/tests/PhpWordTests/Collection/CollectionTest.php index 8f7e3c2ebf..9a18a2a75f 100644 --- a/tests/PhpWordTests/Collection/CollectionTest.php +++ b/tests/PhpWordTests/Collection/CollectionTest.php @@ -35,13 +35,26 @@ public function testCollection(): void $object = new Footnotes(); $object->addItem(new Footnote()); // addItem #1 - self::assertEquals(2, $object->addItem(new Footnote())); // addItem #2. Should returns new item index + self::assertEquals(1, $object->addItem(new Footnote())); // addItem #2. Should returns new item index self::assertCount(2, $object->getItems()); // getItems returns array - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Footnote', $object->getItem(1)); // getItem returns object + self::assertInstanceOf(Footnote::class, $object->getItem(1)); // getItem returns object self::assertNull($object->getItem(3)); // getItem returns null when invalid index is referenced $object->setItem(2, null); // Set item #2 to null self::assertNull($object->getItem(2)); // Check if it's null } + + /** + * @covers ::setItem + */ + public function testCollectionSetItem(): void + { + $object = new Footnotes(); + $object->addItem(new Footnote()); + self::assertCount(1, $object->getItems()); + + $object->setItem(0, new Footnote()); + self::assertCount(1, $object->getItems()); + } } diff --git a/tests/PhpWordTests/Reader/Word2007Test.php b/tests/PhpWordTests/Reader/Word2007Test.php index 883dc84d53..e42f0110d5 100644 --- a/tests/PhpWordTests/Reader/Word2007Test.php +++ b/tests/PhpWordTests/Reader/Word2007Test.php @@ -17,11 +17,15 @@ namespace PhpOffice\PhpWordTests\Reader; +use DateTime; +use PhpOffice\PhpWord\Element\Comment; use PhpOffice\PhpWord\Element\Image; +use PhpOffice\PhpWord\Element\Text; use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\IOFactory; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Reader\Word2007; +use PhpOffice\PhpWord\Style\Font; use PhpOffice\PhpWordTests\TestHelperDOCX; /** @@ -118,4 +122,41 @@ public function providerSettingsImageLoading(): iterable [false], ]; } + + public function testLoadComments(): void + { + $phpWord = IOFactory::load(dirname(__DIR__, 1) . '/_files/documents/reader-comments.docx'); + + self::assertInstanceOf(PhpWord::class, $phpWord); + + self::assertEquals(2, $phpWord->getComments()->countItems()); + + /** @var Comment $comment */ + $comment = $phpWord->getComments()->getItem(0); + self::assertInstanceOf(Comment::class, $comment); + self::assertEquals('shaedrich', $comment->getAuthor()); + self::assertEquals(new DateTime('2021-10-28T13:56:55Z'), $comment->getDate()); + self::assertEquals('SH', $comment->getInitials()); + self::assertCount(1, $comment->getElements()); + self::assertInstanceOf(Text::class, $comment->getElement(0)); + self::assertEquals('This this be lowercase', $comment->getElement(0)->getText()); + /** @var Font $fontStyle */ + $fontStyle = $comment->getElement(0)->getFontStyle(); + self::assertInstanceOf(Font::class, $fontStyle); + self::assertEquals('de-DE', $fontStyle->getLang()->getLatin()); + + /** @var Comment $comment */ + $comment = $phpWord->getComments()->getItem(1); + self::assertInstanceOf(Comment::class, $comment); + self::assertEquals('shaedrich', $comment->getAuthor()); + self::assertEquals(new DateTime('2021-11-02T19:10:00Z'), $comment->getDate()); + self::assertEquals('SH', $comment->getInitials()); + self::assertCount(1, $comment->getElements()); + self::assertInstanceOf(Text::class, $comment->getElement(0)); + self::assertEquals('But this should be uppercase', $comment->getElement(0)->getText()); + /** @var Font $fontStyle */ + $fontStyle = $comment->getElement(0)->getFontStyle(); + self::assertInstanceOf(Font::class, $fontStyle); + self::assertEquals('de-DE', $fontStyle->getLang()->getLatin()); + } } diff --git a/tests/PhpWord/_files/documents/reader-ooxml-comments.docx b/tests/PhpWordTests/_files/documents/reader-comments.docx similarity index 100% rename from tests/PhpWord/_files/documents/reader-ooxml-comments.docx rename to tests/PhpWordTests/_files/documents/reader-comments.docx From 5d3ca3bb278fa3ca53906be7695e946c53dced38 Mon Sep 17 00:00:00 2001 From: Christoph Fischer Date: Thu, 12 May 2022 20:19:44 +0200 Subject: [PATCH 145/246] Word2007 Reader/Writer: Permit book-fold printing --- docs/changes/1.x/1.2.0.md | 1 + docs/usage/introduction.md | 28 +++++++++++++++++++ docs/usage/writers.md | 2 ++ phpstan-baseline.neon | 5 ---- src/PhpWord/Metadata/Settings.php | 19 +++++++++++++ src/PhpWord/Reader/Word2007/Settings.php | 14 +++++----- src/PhpWord/Writer/Word2007/Part/Settings.php | 1 + tests/PhpWordTests/Metadata/SettingsTest.php | 15 ++++++++++ .../Writer/Word2007/Part/SettingsTest.php | 16 +++++++++++ 9 files changed, 89 insertions(+), 12 deletions(-) diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index 5b055ca7c0..a6b88ca93c 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -12,6 +12,7 @@ - Word2007 Reader : Support for table cell borders and margins by [@kernusr](https://github.com/kernusr) in GH-2454 - PDF Writer : Add config for defining the default font by [@MikeMaldini](https://github.com/MikeMaldini) in [#2262](https://github.com/PHPOffice/PHPWord/pull/2262) & [#2468](https://github.com/PHPOffice/PHPWord/pull/2468) - Word2007 Reader : Added support for Comments by [@shaedrich](https://github.com/shaedrich) in [#2161](https://github.com/PHPOffice/PHPWord/pull/2161) & [#2469](https://github.com/PHPOffice/PHPWord/pull/2469) +- 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) ### Bug fixes diff --git a/docs/usage/introduction.md b/docs/usage/introduction.md index 94a6fd915d..b3a101ab0d 100644 --- a/docs/usage/introduction.md +++ b/docs/usage/introduction.md @@ -170,6 +170,34 @@ Use mirror margins to set up facing pages for double-sided documents, such as bo $phpWord->getSettings()->setMirrorMargins(true); ``` +!!! note annotate "Don't forget to set both paper size and page size" + + For example, to print a document on A4 paper (landscape) and fold it into A5 pages (portrait), use this section style: + + ``` php + getSettings()->setMirrorMargins(true); + $phpWord->addSection([ + 'paperSize' => 'A4', + 'orientation' => 'landscape', + 'pageSizeW' => Converter::cmToTwip(14.85), + 'pageSizeH' => Converter::cmToTwip(21), + ]); + ``` + +### Printing as folded booklet + +Use book-fold printing to set up documents to be printed as foldable pages. + +``` php +getSettings()->setBookFoldPrinting(true); +``` + ### Spelling and grammatical checks By default spelling and grammatical errors are shown as soon as you open a word document. diff --git a/docs/usage/writers.md b/docs/usage/writers.md index 8610ef3cf0..684abeeeac 100644 --- a/docs/usage/writers.md +++ b/docs/usage/writers.md @@ -38,6 +38,8 @@ You can define options like : Options must be defined before creating the writer. ``` php +doNotHyphenateCaps = (bool) $doNotHyphenateCaps; } + + public function hasBookFoldPrinting(): bool + { + return $this->bookFoldPrinting; + } + + public function setBookFoldPrinting(bool $bookFoldPrinting): self + { + $this->bookFoldPrinting = $bookFoldPrinting; + + return $this; + } } diff --git a/src/PhpWord/Reader/Word2007/Settings.php b/src/PhpWord/Reader/Word2007/Settings.php index 63578595f5..7466008d49 100644 --- a/src/PhpWord/Reader/Word2007/Settings.php +++ b/src/PhpWord/Reader/Word2007/Settings.php @@ -30,7 +30,10 @@ */ class Settings extends AbstractPart { - private static $booleanProperties = [ + /** + * @var array + */ + private $booleanProperties = [ 'mirrorMargins', 'hideSpellingErrors', 'hideGrammaticalErrors', @@ -41,6 +44,7 @@ class Settings extends AbstractPart 'updateFields', 'autoHyphenation', 'doNotHyphenateCaps', + 'bookFoldPrinting', ]; /** @@ -60,12 +64,8 @@ public function read(PhpWord $phpWord): void $value = $xmlReader->getAttribute('w:val', $node); $method = 'set' . $name; - if (in_array($name, $this::$booleanProperties)) { - if ($value == 'false') { - $docSettings->$method(false); - } else { - $docSettings->$method(true); - } + if (in_array($name, $this->booleanProperties)) { + $docSettings->$method($value !== 'false'); } elseif (method_exists($this, $method)) { $this->$method($xmlReader, $phpWord, $node); } elseif (method_exists($docSettings, $method)) { diff --git a/src/PhpWord/Writer/Word2007/Part/Settings.php b/src/PhpWord/Writer/Word2007/Part/Settings.php index 2b126bb0fb..d1f6296912 100644 --- a/src/PhpWord/Writer/Word2007/Part/Settings.php +++ b/src/PhpWord/Writer/Word2007/Part/Settings.php @@ -151,6 +151,7 @@ private function getSettings(): void $this->setOnOffValue('w:updateFields', $documentSettings->hasUpdateFields()); $this->setOnOffValue('w:autoHyphenation', $documentSettings->hasAutoHyphenation()); $this->setOnOffValue('w:doNotHyphenateCaps', $documentSettings->hasDoNotHyphenateCaps()); + $this->setOnOffValue('w:bookFoldPrinting', $documentSettings->hasBookFoldPrinting()); $this->setThemeFontLang($documentSettings->getThemeFontLang()); $this->setRevisionView($documentSettings->getRevisionView()); diff --git a/tests/PhpWordTests/Metadata/SettingsTest.php b/tests/PhpWordTests/Metadata/SettingsTest.php index 48af68eab8..14f19f318d 100644 --- a/tests/PhpWordTests/Metadata/SettingsTest.php +++ b/tests/PhpWordTests/Metadata/SettingsTest.php @@ -225,4 +225,19 @@ public function testDefaultDoNotHyphenateCaps(): void $oSettings = new Settings(); self::assertNull($oSettings->hasDoNotHyphenateCaps()); } + + public function testBookFoldPrinting(): void + { + $oSettings = new Settings(); + self::assertInstanceOf(Settings::class, $oSettings->setBookFoldPrinting(true)); + self::assertTrue($oSettings->hasBookFoldPrinting()); + self::assertInstanceOf(Settings::class, $oSettings->setBookFoldPrinting(false)); + self::assertFalse($oSettings->hasBookFoldPrinting()); + } + + public function testDefaultBookFoldPrinting(): void + { + $oSettings = new Settings(); + self::assertFalse($oSettings->hasBookFoldPrinting()); + } } diff --git a/tests/PhpWordTests/Writer/Word2007/Part/SettingsTest.php b/tests/PhpWordTests/Writer/Word2007/Part/SettingsTest.php index e60e03f74f..db8f5198a4 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/SettingsTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/SettingsTest.php @@ -468,4 +468,20 @@ public function testDoNotHyphenateCaps(): void $element = $doc->getElement($path, $file); self::assertSame('true', $element->getAttribute('w:val')); } + + public function testBookFoldPrinting(): void + { + $phpWord = new PhpWord(); + $phpWord->getSettings()->setBookFoldPrinting(true); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $file = 'word/settings.xml'; + + $path = '/w:settings/w:bookFoldPrinting'; + self::assertTrue($doc->elementExists($path, $file)); + + $element = $doc->getElement($path, $file); + self::assertSame('true', $element->getAttribute('w:val')); + } } From 338fcc170bb74e8e8bbc84c36fffd89533a5c354 Mon Sep 17 00:00:00 2001 From: Kozin Yuriy Date: Tue, 9 Jul 2019 15:24:33 +0300 Subject: [PATCH 146/246] Word2007 Writer : Add PageNumber to TOC --- docs/changes/1.x/1.2.0.md | 1 + docs/usage/elements/title.md | 13 ++- src/PhpWord/Element/AbstractContainer.php | 2 +- src/PhpWord/Element/Title.php | 21 +++- src/PhpWord/Writer/Word2007/Element/TOC.php | 24 +++-- tests/PhpWordTests/Element/TitleTest.php | 47 +++++---- .../Writer/Word2007/Element/TOCTest.php | 56 +++++++++++ .../Writer/Word2007/Element/TitleTest.php | 96 +++++++++++++++++++ .../Writer/Word2007/ElementTest.php | 26 ----- .../Writer/Word2007/Part/DocumentTest.php | 14 --- 10 files changed, 227 insertions(+), 73 deletions(-) create mode 100644 tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php create mode 100644 tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index a6b88ca93c..83b20af735 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -13,6 +13,7 @@ - PDF Writer : Add config for defining the default font by [@MikeMaldini](https://github.com/MikeMaldini) in [#2262](https://github.com/PHPOffice/PHPWord/pull/2262) & [#2468](https://github.com/PHPOffice/PHPWord/pull/2468) - Word2007 Reader : Added support for Comments by [@shaedrich](https://github.com/shaedrich) in [#2161](https://github.com/PHPOffice/PHPWord/pull/2161) & [#2469](https://github.com/PHPOffice/PHPWord/pull/2469) - 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) ### Bug fixes diff --git a/docs/usage/elements/title.md b/docs/usage/elements/title.md index f778d6ddb7..fba78ef645 100644 --- a/docs/usage/elements/title.md +++ b/docs/usage/elements/title.md @@ -8,12 +8,17 @@ If `depth` is 0, a Title will be inserted, otherwise a Heading1, Heading2, ... addTitleStyle($depth, [$fontStyle], [$paragraphStyle]); -$section->addTitle($text, [$depth]); +$section->addTitle($text, $depth, $pageNumber); ``` -- ``depth``. -- ``$fontStyle``. See [`Styles > Font`](../styles/font.md). -- ``$paragraphStyle``. See [`Styles > Paragraph`](../styles/paragraph.md). +`addTitleStyle` : +- ``$depth`` +- ``$fontStyle``: See [`Styles > Font`](../styles/font.md). +- ``$paragraphStyle``: See [`Styles > Paragraph`](../styles/paragraph.md). + +`addTitle` : - ``$text``. Text to be displayed in the document. This can be `string` or a `\PhpOffice\PhpWord\Element\TextRun` +- ``$depth`` +- ``$pageNumber`` : Number of the page It's necessary to add a title style to your document because otherwise the title won't be detected as a real title. \ No newline at end of file diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index 726e204d00..884ec29385 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -34,7 +34,7 @@ * @method Footnote addFootnote(mixed $pStyle = null) * @method Endnote addEndnote(mixed $pStyle = null) * @method CheckBox addCheckBox(string $name, $text, mixed $fStyle = null, mixed $pStyle = null) - * @method Title addTitle(mixed $text, int $depth = 1) + * @method Title addTitle(mixed $text, int $depth = 1, int $pageNumber = null) * @method TOC addTOC(mixed $fontStyle = null, mixed $tocStyle = null, int $minDepth = 1, int $maxDepth = 9) * @method PageBreak addPageBreak() * @method Table addTable(mixed $style = null) diff --git a/src/PhpWord/Element/Title.php b/src/PhpWord/Element/Title.php index 461a03fc5a..8fd5b21b1d 100644 --- a/src/PhpWord/Element/Title.php +++ b/src/PhpWord/Element/Title.php @@ -54,13 +54,20 @@ class Title extends AbstractElement */ protected $collectionRelation = true; + /** + * Page number. + * + * @var int + */ + private $pageNumber; + /** * Create a new Title Element. * * @param string|TextRun $text * @param int $depth */ - public function __construct($text, $depth = 1) + public function __construct($text, $depth = 1, ?int $pageNumber = null) { if (is_string($text)) { $this->text = SharedText::toUTF8($text); @@ -75,6 +82,10 @@ public function __construct($text, $depth = 1) if (array_key_exists($styleName, Style::getStyles())) { $this->style = str_replace('_', '', $styleName); } + + if ($pageNumber !== null) { + $this->pageNumber = $pageNumber; + } } /** @@ -106,4 +117,12 @@ public function getStyle() { return $this->style; } + + /** + * Get page number. + */ + public function getPageNumber(): ?int + { + return $this->pageNumber; + } } diff --git a/src/PhpWord/Writer/Word2007/Element/TOC.php b/src/PhpWord/Writer/Word2007/Element/TOC.php index 90b4ce3d9e..7c5d089775 100644 --- a/src/PhpWord/Writer/Word2007/Element/TOC.php +++ b/src/PhpWord/Writer/Word2007/Element/TOC.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; +use PhpOffice\PhpWord\Element\Title; use PhpOffice\PhpWord\Element\TOC as TOCElement; use PhpOffice\PhpWord\Shared\XMLWriter; use PhpOffice\PhpWord\Style\Font; @@ -63,11 +64,8 @@ public function write(): void /** * Write title. - * - * @param \PhpOffice\PhpWord\Element\Title $title - * @param bool $writeFieldMark */ - private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, $title, $writeFieldMark): void + private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, Title $title, bool $writeFieldMark): void { $tocStyle = $element->getStyleTOC(); $fontStyle = $element->getStyleFont(); @@ -116,6 +114,20 @@ private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, $title, $ $xmlWriter->endElement(); $xmlWriter->endElement(); + if ($title->getPageNumber() !== null) { + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'separate'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:t'); + $xmlWriter->text((string) $title->getPageNumber()); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + $xmlWriter->startElement('w:r'); $xmlWriter->startElement('w:fldChar'); $xmlWriter->writeAttribute('w:fldCharType', 'end'); @@ -129,10 +141,8 @@ private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, $title, $ /** * Write style. - * - * @param 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/tests/PhpWordTests/Element/TitleTest.php b/tests/PhpWordTests/Element/TitleTest.php index 0e3e481510..e48a163721 100644 --- a/tests/PhpWordTests/Element/TitleTest.php +++ b/tests/PhpWordTests/Element/TitleTest.php @@ -14,6 +14,7 @@ * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ +declare(strict_types=1); namespace PhpOffice\PhpWordTests\Element; @@ -32,24 +33,17 @@ class TitleTest extends \PHPUnit\Framework\TestCase { /** - * Create new instance. + * Create new instance with string. */ public function testConstruct(): void { - $oTitle = new Title('text'); + $title = new Title('text'); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Title', $oTitle); - self::assertEquals('text', $oTitle->getText()); - } - - /** - * Get style null. - */ - public function testStyleNull(): void - { - $oTitle = new Title('text'); - - self::assertNull($oTitle->getStyle()); + self::assertInstanceOf(Title::class, $title); + self::assertEquals('text', $title->getText()); + self::assertEquals(1, $title->getDepth()); + self::assertNull($title->getPageNumber()); + self::assertNull($title->getStyle()); } /** @@ -57,17 +51,30 @@ public function testStyleNull(): void */ public function testConstructWithTextRun(): void { - $oTextRun = new TextRun(); - $oTextRun->addText('text'); - $oTitle = new Title($oTextRun); + $textRun = new TextRun(); + $textRun->addText('text'); + $title = new Title($textRun); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $oTitle->getText()); + self::assertInstanceOf(TextRun::class, $title->getText()); + self::assertEquals(1, $title->getDepth()); + self::assertNull($title->getPageNumber()); + self::assertNull($title->getStyle()); } public function testConstructWithInvalidArgument(): void { $this->expectException(InvalidArgumentException::class); - $oPageBreak = new PageBreak(); - new Title($oPageBreak); + + new Title(new PageBreak()); + } + + public function testConstructWithPageNumber(): void + { + $title = new Title('text', 1, 0); + + self::assertInstanceOf(Title::class, $title); + self::assertEquals('text', $title->getText()); + self::assertEquals(0, $title->getPageNumber()); + self::assertNull($title->getStyle()); } } diff --git a/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php b/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php new file mode 100644 index 0000000000..537fb93d1a --- /dev/null +++ b/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php @@ -0,0 +1,56 @@ +addSection(); + $section->addTOC(); + $section->addTitle('TestTitle 1', 1, $expectedPageNum); + + $doc = TestHelperDOCX::getDocument($phpWord); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:hyperlink/w:r[1]/w:t')); + self::assertEquals('TestTitle 1', $doc->getElement('/w:document/w:body/w:p[1]/w:hyperlink/w:r[1]/w:t')->textContent); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:hyperlink/w:r[5]/w:fldChar')); + self::assertEquals('separate', $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:hyperlink/w:r[5]/w:fldChar', 'w:fldCharType')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:hyperlink/w:r[6]/w:t')); + self::assertEquals($expectedPageNum, $doc->getElement('/w:document/w:body/w:p[1]/w:hyperlink/w:r[6]/w:t')->textContent); + } +} diff --git a/tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php b/tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php new file mode 100644 index 0000000000..180a319eb1 --- /dev/null +++ b/tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php @@ -0,0 +1,96 @@ +addTitleStyle(0, ['size' => 14, 'italic' => true]); + + $section = $phpWord->addSection(); + $section->addTitle('Test Title0', 0); + + $doc = TestHelperDOCX::getDocument($phpWord); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:r/w:t')); + self::assertEquals('Test Title0', $doc->getElement('/w:document/w:body/w:p[1]/w:r/w:t')->textContent); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr/w:pStyle')); + self::assertEquals('Title', $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:pPr/w:pStyle', 'w:val')); + } + + public function testWriteTitleWithoutStyle(): void + { + $phpWord = new PhpWord(); + + $section = $phpWord->addSection(); + $section->addTitle('Test Title0', 0); + + $doc = TestHelperDOCX::getDocument($phpWord); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:r/w:t')); + self::assertEquals('Test Title0', $doc->getElement('/w:document/w:body/w:p[1]/w:r/w:t')->textContent); + self::assertFalse($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr')); + } + + public function testWriteHeadingWithStyle(): void + { + $phpWord = new PhpWord(); + $phpWord->addTitleStyle(1, ['bold' => true], ['spaceAfter' => 240]); + + $section = $phpWord->addSection(); + $section->addTitle('TestHeading 1', 1); + + $doc = TestHelperDOCX::getDocument($phpWord); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:r/w:t')); + self::assertEquals('TestHeading 1', $doc->getElement('/w:document/w:body/w:p[1]/w:r/w:t')->textContent); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr/w:pStyle')); + self::assertEquals('Heading1', $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:pPr/w:pStyle', 'w:val')); + } + + public function testWriteHeadingWithoutStyle(): void + { + $phpWord = new PhpWord(); + + $section = $phpWord->addSection(); + $section->addTitle('TestHeading 1', 1); + + $doc = TestHelperDOCX::getDocument($phpWord); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:r/w:t')); + self::assertEquals('TestHeading 1', $doc->getElement('/w:document/w:body/w:p[1]/w:r/w:t')->textContent); + self::assertFalse($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr')); + } +} diff --git a/tests/PhpWordTests/Writer/Word2007/ElementTest.php b/tests/PhpWordTests/Writer/Word2007/ElementTest.php index 41c86f6b84..3bcd842fbd 100644 --- a/tests/PhpWordTests/Writer/Word2007/ElementTest.php +++ b/tests/PhpWordTests/Writer/Word2007/ElementTest.php @@ -460,32 +460,6 @@ public function testTrackChange(): void self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:del/w:r/w:delText')); } - /** - * Test Title and Headings. - */ - public function testTitleAndHeading(): void - { - $phpWord = new PhpWord(); - $phpWord->addTitleStyle(0, ['size' => 14, 'italic' => true]); - $phpWord->addTitleStyle(1, ['size' => 20, 'color' => '333333', 'bold' => true]); - - $section = $phpWord->addSection(); - $section->addTitle('This is a title', 0); - $section->addTitle('Heading 1', 1); - - $doc = TestHelperDOCX::getDocument($phpWord); - - self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:r/w:t')); - self::assertEquals('This is a title', $doc->getElement('/w:document/w:body/w:p[1]/w:r/w:t')->textContent); - self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr/w:pStyle')); - self::assertEquals('Title', $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:pPr/w:pStyle', 'w:val')); - - self::assertTrue($doc->elementExists('/w:document/w:body/w:p[2]/w:r/w:t')); - self::assertEquals('Heading 1', $doc->getElement('/w:document/w:body/w:p[2]/w:r/w:t')->textContent); - self::assertTrue($doc->elementExists('/w:document/w:body/w:p[2]/w:pPr/w:pStyle')); - self::assertEquals('Heading1', $doc->getElementAttribute('/w:document/w:body/w:p[2]/w:pPr/w:pStyle', 'w:val')); - } - /** * Test correct writing of text with ampersant in it. */ diff --git a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php index 04bdb54ed7..108142d6f2 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php @@ -436,20 +436,6 @@ public function testWriteWatermark(): void self::assertStringStartsWith('rId', $element->getAttribute('r:id')); } - /** - * covers ::_writeTitle. - */ - public function testWriteTitle(): void - { - $phpWord = new PhpWord(); - $phpWord->addTitleStyle(1, ['bold' => true], ['spaceAfter' => 240]); - $phpWord->addSection()->addTitle('Test', 1); - $doc = TestHelperDOCX::getDocument($phpWord); - - $element = '/w:document/w:body/w:p/w:pPr/w:pStyle'; - self::assertEquals('Heading1', $doc->getElementAttribute($element, 'w:val')); - } - /** * covers ::_writeCheckbox. */ From 9dfe0b0b5bf3930bc0ca89023e5fbab02f27d504 Mon Sep 17 00:00:00 2001 From: mhcwebdesign Date: Mon, 28 Aug 2023 21:32:25 +0100 Subject: [PATCH 147/246] Remove deprecated utf8_encode in PHP 8.2 --- docs/changes/1.x/1.2.0.md | 3 ++- src/PhpWord/Shared/Text.php | 6 +++++- src/PhpWord/TemplateProcessor.php | 6 +++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index 83b20af735..70172884f7 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -34,4 +34,5 @@ - Moved documention from ReadTheDocs to MkDocs & Github Pages by [@Progi1984](https://github.com/Progi1984) in GH-2465 - Bump phpstan/phpstan-phpunit from 1.3.13 to 1.3.14 by [@dependabot](https://github.com/dependabot) in [#2457](https://github.com/PHPOffice/PHPWord/pull/2457) - Bump symfony/process from 5.4.26 to 5.4.28 by [@dependabot](https://github.com/dependabot) in [#2456](https://github.com/PHPOffice/PHPWord/pull/2456) -- Bump phpunit/phpunit from 9.6.10 to 9.6.11 by [@dependabot](https://github.com/dependabot) in [#2455](https://github.com/PHPOffice/PHPWord/pull/2455) \ No newline at end of file +- Bump phpunit/phpunit from 9.6.10 to 9.6.11 by [@dependabot](https://github.com/dependabot) in [#2455](https://github.com/PHPOffice/PHPWord/pull/2455) +- Remove deprecated utf8_encode in PHP 8.2 by [@mhcwebdesign](https://github.com/mhcwebdesign) in [#2447](https://github.com/PHPOffice/PHPWord/pull/2447) & [#2472](https://github.com/PHPOffice/PHPWord/pull/2472) \ No newline at end of file diff --git a/src/PhpWord/Shared/Text.php b/src/PhpWord/Shared/Text.php index 667d67ab4a..4a530b2e10 100644 --- a/src/PhpWord/Shared/Text.php +++ b/src/PhpWord/Shared/Text.php @@ -145,7 +145,11 @@ public static function isUTF8($value = '') public static function toUTF8($value = '') { if (null !== $value && !self::isUTF8($value)) { - $value = utf8_encode($value); + if (PHP_VERSION_ID < 80200) { + $value = utf8_encode($value); + } else { + $value = mb_convert_encoding($value, 'UTF-8', mb_list_encodings()); + } } return $value; diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 3433287e19..ea90ef1d5e 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -257,7 +257,11 @@ protected static function ensureMacroCompleted($macro) protected static function ensureUtf8Encoded($subject) { if (!Text::isUTF8($subject) && null !== $subject) { - $subject = utf8_encode($subject); + if (PHP_VERSION_ID < 80200) { + $subject = utf8_encode($subject); + } else { + $subject = mb_convert_encoding($subject, 'UTF-8', mb_list_encodings()); + } } return (null !== $subject) ? $subject : ''; From 090e6b3d32b603f09264f65b71005abb9f984305 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Thu, 21 Sep 2023 20:10:24 +0200 Subject: [PATCH 148/246] Formula : Add Element (& Writer/Reader Word2007/ODText) --- .github/workflows/php.yml | 6 +- composer.json | 3 +- composer.lock | 55 ++++++++- docs/changes/1.x/1.2.0.md | 1 + docs/index.md | 8 +- docs/usage/elements/formula.md | 21 ++++ src/PhpWord/Element/AbstractContainer.php | 3 + src/PhpWord/Element/Formula.php | 53 ++++++++ src/PhpWord/Reader/ODText.php | 13 +- src/PhpWord/Reader/ODText/Content.php | 71 +++++++---- src/PhpWord/Reader/Word2007/AbstractPart.php | 75 +++++++----- src/PhpWord/Writer/ODText.php | 33 ++++- src/PhpWord/Writer/ODText/Element/Formula.php | 74 ++++++++++++ .../Writer/ODText/Part/AbstractPart.php | 31 +++++ src/PhpWord/Writer/ODText/Part/Content.php | 3 + src/PhpWord/Writer/ODText/Part/Manifest.php | 19 ++- .../Word2007/Element/AbstractElement.php | 18 +++ .../Writer/Word2007/Element/Container.php | 1 + .../Writer/Word2007/Element/Formula.php | 50 ++++++++ .../Element/AbstractElementTest.php | 6 +- tests/PhpWordTests/Element/FormulaTest.php | 64 ++++++++++ tests/PhpWordTests/Reader/ODTextTest.php | 33 ++++- tests/PhpWordTests/Reader/Word2007Test.php | 57 +++++++++ .../Writer/ODText/Element/FormulaTest.php | 71 +++++++++++ .../Writer/ODText/Part/ManifestTest.php | 100 ++++++++++++++++ .../Writer/Word2007/Element/FormulaTest.php | 72 +++++++++++ .../Writer/Word2007/Part/DocumentTest.php | 6 +- tests/PhpWordTests/XmlDocument.php | 113 +++++------------- .../_files/documents/reader-formula.docx | Bin 0 -> 4292 bytes .../_files/documents/reader-formula.odt | Bin 0 -> 10565 bytes 30 files changed, 888 insertions(+), 172 deletions(-) create mode 100644 docs/usage/elements/formula.md create mode 100644 src/PhpWord/Element/Formula.php create mode 100644 src/PhpWord/Writer/ODText/Element/Formula.php create mode 100644 src/PhpWord/Writer/Word2007/Element/Formula.php create mode 100644 tests/PhpWordTests/Element/FormulaTest.php create mode 100644 tests/PhpWordTests/Writer/ODText/Element/FormulaTest.php create mode 100644 tests/PhpWordTests/Writer/ODText/Part/ManifestTest.php create mode 100644 tests/PhpWordTests/Writer/Word2007/Element/FormulaTest.php create mode 100644 tests/PhpWordTests/_files/documents/reader-formula.docx create mode 100644 tests/PhpWordTests/_files/documents/reader-formula.odt diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 46c539dcc3..ed772171e7 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -1,7 +1,9 @@ name: CI on: - - push - - pull_request + pull_request: + push: + branches: + - master jobs: test: runs-on: ubuntu-latest diff --git a/composer.json b/composer.json index 6890bf6d9f..4a0a5789f1 100644 --- a/composer.json +++ b/composer.json @@ -68,7 +68,8 @@ "ext-dom": "*", "ext-json": "*", "ext-xml": "*", - "laminas/laminas-escaper": ">=2.6" + "laminas/laminas-escaper": ">=2.6", + "phpoffice/math": "^0.1" }, "require-dev": { "ext-zip": "*", diff --git a/composer.lock b/composer.lock index a4557e01da..76d598a86f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2d45739d1122eb36186b5cfe7cd6d6ab", + "content-hash": "23680170abecc52de95d0833296ced64", "packages": [ { "name": "laminas/laminas-escaper", @@ -67,6 +67,59 @@ } ], "time": "2022-10-10T10:11:09+00:00" + }, + { + "name": "phpoffice/math", + "version": "0.1.0", + "source": { + "type": "git", + "url": "https://github.com/PHPOffice/Math.git", + "reference": "f0f8cad98624459c540cdd61d2a174d834471773" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPOffice/Math/zipball/f0f8cad98624459c540cdd61d2a174d834471773", + "reference": "f0f8cad98624459c540cdd61d2a174d834471773", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xml": "*", + "php": "^7.1|^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.88 || ^1.0.0", + "phpunit/phpunit": "^7.0 || ^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpOffice\\Math\\": "src/Math/", + "Tests\\PhpOffice\\Math\\": "tests/Math/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Progi1984", + "homepage": "https://lefevre.dev/" + } + ], + "description": "Math - Manipulate Math Formula", + "homepage": "https://phpoffice.github.io/Math/", + "keywords": [ + "MathML", + "officemathml", + "php" + ], + "support": { + "issues": "https://github.com/PHPOffice/Math/issues", + "source": "https://github.com/PHPOffice/Math/tree/0.1.0" + }, + "time": "2023-09-25T12:08:20+00:00" } ], "packages-dev": [ diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index 70172884f7..40becc441d 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -14,6 +14,7 @@ - Word2007 Reader : Added support for Comments by [@shaedrich](https://github.com/shaedrich) in [#2161](https://github.com/PHPOffice/PHPWord/pull/2161) & [#2469](https://github.com/PHPOffice/PHPWord/pull/2469) - 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) ### Bug fixes diff --git a/docs/index.md b/docs/index.md index bd38dd3238..dd600689d7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -66,8 +66,8 @@ Below are the supported features for each file formats. | **Graphs** | 2D basic graphs | :material-check: | | | | | | | 2D advanced graphs | | | | | | | | 3D graphs | :material-check: | | | | | -| **Math** | OMML support | | | | | | -| | MathML support | | | | | | +| **Math** | OMML support | :material-check: | | | | | +| | MathML support | | :material-check: | | | | | **Bonus** | Encryption | | | | | | | | Protection | | | | | | @@ -99,8 +99,8 @@ Below are the supported features for each file formats. | **Graphs** | 2D basic graphs | | | | | | | | 2D advanced graphs | | | | | | | | 3D graphs | | | | | | -| **Math** | OMML support | | | | | | -| | MathML support | | | | | | +| **Math** | OMML support | :material-check: | | | | | +| | MathML support | | :material-check: | | | | | **Bonus** | Encryption | | | | | | | | Protection | | | | | | diff --git a/docs/usage/elements/formula.md b/docs/usage/elements/formula.md new file mode 100644 index 0000000000..a114b73e38 --- /dev/null +++ b/docs/usage/elements/formula.md @@ -0,0 +1,21 @@ +# Formula + +Formula can be added using + +``` php +setDenominator(new Element\Numeric(2)) + ->setNumerator(new Element\Identifier('π')) +; + +$math = new Math(); +$math->add($fraction); + +$formula = $section->addFormula($math); +``` \ No newline at end of file diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index 884ec29385..f9b2822a12 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWord\Element; use BadMethodCallException; +use PhpOffice\Math\Math; use ReflectionClass; /** @@ -47,6 +48,7 @@ * @method Chart addChart(string $type, array $categories, array $values, array $style = null, $seriesName = null) * @method FormField addFormField(string $type, mixed $fStyle = null, mixed $pStyle = null) * @method SDT addSDT(string $type) + * @method Formula addFormula(Math $math) * @method \PhpOffice\PhpWord\Element\OLEObject addObject(string $source, mixed $style = null) deprecated, use addOLEObject instead * * @since 0.10.0 @@ -88,6 +90,7 @@ public function __call($function, $args) 'Footnote', 'Endnote', 'CheckBox', 'TextBox', 'Field', 'Line', 'Shape', 'Title', 'TOC', 'PageBreak', 'Chart', 'FormField', 'SDT', 'Comment', + 'Formula', ]; $functions = []; foreach ($elements as $element) { diff --git a/src/PhpWord/Element/Formula.php b/src/PhpWord/Element/Formula.php new file mode 100644 index 0000000000..ca9f5d6b4b --- /dev/null +++ b/src/PhpWord/Element/Formula.php @@ -0,0 +1,53 @@ +setMath($math); + } + + public function setMath(Math $math): self + { + $this->math = $math; + + return $this; + } + + public function getMath(): Math + { + return $this->math; + } +} diff --git a/src/PhpWord/Reader/ODText.php b/src/PhpWord/Reader/ODText.php index aba280db01..d7f8344443 100644 --- a/src/PhpWord/Reader/ODText.php +++ b/src/PhpWord/Reader/ODText.php @@ -53,13 +53,8 @@ public function load($docFile) /** * Read document part. - * - * @param array $relationships - * @param string $partName - * @param string $docFile - * @param string $xmlFile */ - private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile, $xmlFile): void + private function readPart(PhpWord $phpWord, array $relationships, string $partName, string $docFile, string $xmlFile): void { $partClass = "PhpOffice\\PhpWord\\Reader\\ODText\\{$partName}"; if (class_exists($partClass)) { @@ -72,12 +67,8 @@ private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile, /** * Read all relationship files. - * - * @param string $docFile - * - * @return array */ - private function readRelationships($docFile) + private function readRelationships(string $docFile): array { $rels = []; $xmlFile = 'META-INF/manifest.xml'; diff --git a/src/PhpWord/Reader/ODText/Content.php b/src/PhpWord/Reader/ODText/Content.php index ccbc5eec96..45cb0704db 100644 --- a/src/PhpWord/Reader/ODText/Content.php +++ b/src/PhpWord/Reader/ODText/Content.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWord\Reader\ODText; use DateTime; +use PhpOffice\Math\Reader\MathML; use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Shared\XMLReader; @@ -51,37 +52,55 @@ public function read(PhpWord $phpWord): void break; case 'text:p': // Paragraph - $children = $node->childNodes; - foreach ($children as $child) { - switch ($child->nodeName) { - case 'text:change-start': - $changeId = $child->getAttribute('text:change-id'); - if (isset($trackedChanges[$changeId])) { - $changed = $trackedChanges[$changeId]; - } + $element = $xmlReader->getElement('draw:frame/draw:object', $node); + if ($element) { + $mathFile = str_replace('./', '', $element->getAttribute('xlink:href')) . '/content.xml'; - break; - case 'text:change-end': - unset($changed); + $xmlReaderObject = new XMLReader(); + $mathElement = $xmlReaderObject->getDomFromZip($this->docFile, $mathFile); + if ($mathElement) { + $mathXML = $mathElement->saveXML($mathElement); - break; - case 'text:change': - $changeId = $child->getAttribute('text:change-id'); - if (isset($trackedChanges[$changeId])) { - $changed = $trackedChanges[$changeId]; - } + if (is_string($mathXML)) { + $reader = new MathML(); + $math = $reader->read($mathXML); - break; + $section->addFormula($math); + } } - } + } else { + $children = $node->childNodes; + foreach ($children as $child) { + switch ($child->nodeName) { + case 'text:change-start': + $changeId = $child->getAttribute('text:change-id'); + if (isset($trackedChanges[$changeId])) { + $changed = $trackedChanges[$changeId]; + } + + break; + case 'text:change-end': + unset($changed); - $element = $section->addText($node->nodeValue); - if (isset($changed) && is_array($changed)) { - $element->setTrackChange($changed['changed']); - if (isset($changed['textNodes'])) { - foreach ($changed['textNodes'] as $changedNode) { - $element = $section->addText($changedNode->nodeValue); - $element->setTrackChange($changed['changed']); + break; + case 'text:change': + $changeId = $child->getAttribute('text:change-id'); + if (isset($trackedChanges[$changeId])) { + $changed = $trackedChanges[$changeId]; + } + + break; + } + } + + $element = $section->addText($node->nodeValue); + if (isset($changed) && is_array($changed)) { + $element->setTrackChange($changed['changed']); + if (isset($changed['textNodes'])) { + foreach ($changed['textNodes'] as $changedNode) { + $element = $section->addText($changedNode->nodeValue); + $element->setTrackChange($changed['changed']); + } } } } diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index dc61b09356..e9272ae71d 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -20,6 +20,7 @@ use DateTime; use DOMElement; use InvalidArgumentException; +use PhpOffice\Math\Reader\OfficeMathML; use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType; use PhpOffice\PhpWord\Element\AbstractContainer; use PhpOffice\PhpWord\Element\AbstractElement; @@ -189,25 +190,7 @@ protected function getCommentReference(string $id): array protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $parent, $docPart = 'document'): void { // Paragraph style - $paragraphStyle = null; - $headingDepth = null; - if ($xmlReader->elementExists('w:commentReference', $domNode) - || $xmlReader->elementExists('w:commentRangeStart', $domNode) - || $xmlReader->elementExists('w:commentRangeEnd', $domNode) - ) { - $nodes = $xmlReader->getElements('w:commentReference|w:commentRangeStart|w:commentRangeEnd', $domNode); - $node = current(iterator_to_array($nodes)); - if ($node) { - $attributeIdentifier = $node->attributes->getNamedItem('id'); - if ($attributeIdentifier) { - $id = $attributeIdentifier->nodeValue; - } - } - } - if ($xmlReader->elementExists('w:pPr', $domNode)) { - $paragraphStyle = $this->readParagraphStyle($xmlReader, $domNode); - $headingDepth = $this->getHeadingDepth($paragraphStyle); - } + $paragraphStyle = $xmlReader->elementExists('w:pPr', $domNode) ? $this->readParagraphStyle($xmlReader, $domNode) : null; // PreserveText if ($xmlReader->elementExists('w:r/w:instrText', $domNode)) { @@ -234,8 +217,27 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par } } $parent->addPreserveText(htmlspecialchars($textContent, ENT_QUOTES, 'UTF-8'), $fontStyle, $paragraphStyle); - } elseif ($xmlReader->elementExists('w:pPr/w:numPr', $domNode)) { - // List item + + return; + } + + // Formula + $xmlReader->registerNamespace('m', 'http://schemas.openxmlformats.org/officeDocument/2006/math'); + if ($xmlReader->elementExists('m:oMath', $domNode)) { + $mathElement = $xmlReader->getElement('m:oMath', $domNode); + $mathXML = $mathElement->ownerDocument->saveXML($mathElement); + if (is_string($mathXML)) { + $reader = new OfficeMathML(); + $math = $reader->read($mathXML); + + $parent->addFormula($math); + } + + return; + } + + // List item + if ($xmlReader->elementExists('w:pPr/w:numPr', $domNode)) { $numId = $xmlReader->getAttribute('w:val', $domNode, 'w:pPr/w:numPr/w:numId'); $levelId = $xmlReader->getAttribute('w:val', $domNode, 'w:pPr/w:numPr/w:ilvl'); $nodes = $xmlReader->getElements('*', $domNode); @@ -245,8 +247,13 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par foreach ($nodes as $node) { $this->readRun($xmlReader, $node, $listItemRun, $docPart, $paragraphStyle); } - } elseif ($headingDepth !== null) { - // Heading or Title + + return; + } + + // Heading or Title + $headingDepth = $xmlReader->elementExists('w:pPr', $domNode) ? $this->getHeadingDepth($paragraphStyle) : null; + if ($headingDepth !== null) { $textContent = null; $nodes = $xmlReader->getElements('w:r|w:hyperlink', $domNode); if ($nodes->length === 1) { @@ -258,17 +265,19 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par } } $parent->addTitle($textContent, $headingDepth); + + return; + } + + // Text and TextRun + $textRunContainers = $xmlReader->countElements('w:r|w:ins|w:del|w:hyperlink|w:smartTag|w:commentReference|w:commentRangeStart|w:commentRangeEnd', $domNode); + if (0 === $textRunContainers) { + $parent->addTextBreak(null, $paragraphStyle); } else { - // Text and TextRun - $textRunContainers = $xmlReader->countElements('w:r|w:ins|w:del|w:hyperlink|w:smartTag|w:commentReference|w:commentRangeStart|w:commentRangeEnd', $domNode); - if (0 === $textRunContainers) { - $parent->addTextBreak(null, $paragraphStyle); - } else { - $nodes = $xmlReader->getElements('*', $domNode); - $paragraph = $parent->addTextRun($paragraphStyle); - foreach ($nodes as $node) { - $this->readRun($xmlReader, $node, $paragraph, $docPart, $paragraphStyle); - } + $nodes = $xmlReader->getElements('*', $domNode); + $paragraph = $parent->addTextRun($paragraphStyle); + foreach ($nodes as $node) { + $this->readRun($xmlReader, $node, $paragraph, $docPart, $paragraphStyle); } } } diff --git a/src/PhpWord/Writer/ODText.php b/src/PhpWord/Writer/ODText.php index 10d9d701fa..6d54706c8e 100644 --- a/src/PhpWord/Writer/ODText.php +++ b/src/PhpWord/Writer/ODText.php @@ -17,8 +17,12 @@ namespace PhpOffice\PhpWord\Writer; +use PhpOffice\Math\Writer\MathML; +use PhpOffice\PhpWord\Element\AbstractElement; +use PhpOffice\PhpWord\Element\Formula; use PhpOffice\PhpWord\Media; use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Writer\ODText\Part\AbstractPart; /** * ODText writer. @@ -27,6 +31,11 @@ */ class ODText extends AbstractWriter implements WriterInterface { + /** + * @var AbstractElement[] + */ + protected $objects = []; + /** * Create new ODText writer. * @@ -77,8 +86,28 @@ public function save($filename = null): void // Write parts foreach ($this->parts as $partName => $fileName) { - if ($fileName != '') { - $zip->addFromString($fileName, $this->getWriterPart($partName)->write()); + if ($fileName === '') { + continue; + } + $part = $this->getWriterPart($partName); + if (!$part instanceof AbstractPart) { + continue; + } + + $part->setObjects($this->objects); + + $zip->addFromString($fileName, $part->write()); + + $this->objects = $part->getObjects(); + } + + // Write objects charts + if (!empty($this->objects)) { + $writer = new MathML(); + foreach ($this->objects as $idxObject => $object) { + if ($object instanceof Formula) { + $zip->addFromString('Formula' . $idxObject . '/content.xml', $writer->write($object->getMath())); + } } } diff --git a/src/PhpWord/Writer/ODText/Element/Formula.php b/src/PhpWord/Writer/ODText/Element/Formula.php new file mode 100644 index 0000000000..ddb1d81aee --- /dev/null +++ b/src/PhpWord/Writer/ODText/Element/Formula.php @@ -0,0 +1,74 @@ +getXmlWriter(); + $element = $this->getElement(); + if (!$element instanceof ElementFormula) { + return; + } + + $part = $this->getPart(); + if (!$part instanceof AbstractPart) { + return; + } + + $objectIdx = $part->addObject($element); + + //$style = $element->getStyle(); + //$width = Converter::pixelToCm($style->getWidth()); + //$height = Converter::pixelToCm($style->getHeight()); + + $xmlWriter->startElement('text:p'); + $xmlWriter->writeAttribute('text:style-name', 'OB' . $objectIdx); + + $xmlWriter->startElement('draw:frame'); + $xmlWriter->writeAttribute('draw:name', $element->getElementId()); + $xmlWriter->writeAttribute('text:anchor-type', 'as-char'); + //$xmlWriter->writeAttribute('svg:width', $width . 'cm'); + //$xmlWriter->writeAttribute('svg:height', $height . 'cm'); + //$xmlWriter->writeAttribute('draw:z-index', $mediaIndex); + + $xmlWriter->startElement('draw:object'); + $xmlWriter->writeAttribute('xlink:href', 'Formula' . $objectIdx); + $xmlWriter->writeAttribute('xlink:type', 'simple'); + $xmlWriter->writeAttribute('xlink:show', 'embed'); + $xmlWriter->writeAttribute('xlink:actuate', 'onLoad'); + $xmlWriter->endElement(); // draw:object + + $xmlWriter->endElement(); // draw:frame + + $xmlWriter->endElement(); // text:p + } +} diff --git a/src/PhpWord/Writer/ODText/Part/AbstractPart.php b/src/PhpWord/Writer/ODText/Part/AbstractPart.php index 4db5ce6e09..59035ff787 100644 --- a/src/PhpWord/Writer/ODText/Part/AbstractPart.php +++ b/src/PhpWord/Writer/ODText/Part/AbstractPart.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWord\Writer\ODText\Part; +use PhpOffice\PhpWord\Element\AbstractElement; use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Shared\XMLWriter; use PhpOffice\PhpWord\Style; @@ -28,6 +29,11 @@ */ abstract class AbstractPart extends Word2007AbstractPart { + /** + * @var AbstractElement[] + */ + protected $objects = []; + /** * @var string Date format */ @@ -102,4 +108,29 @@ protected function writeFontFaces(XMLWriter $xmlWriter): void } $xmlWriter->endElement(); } + + public function addObject(AbstractElement $object): int + { + $this->objects[] = $object; + + return count($this->objects) - 1; + } + + /** + * @param AbstractElement[] $objects + */ + public function setObjects(array $objects): self + { + $this->objects = $objects; + + return $this; + } + + /** + * @return AbstractElement[] + */ + public function getObjects(): array + { + return $this->objects; + } } diff --git a/src/PhpWord/Writer/ODText/Part/Content.php b/src/PhpWord/Writer/ODText/Part/Content.php index 8c96650240..0c0607a06f 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -135,8 +135,11 @@ public function write() $xmlWriter->startElement('text:p'); $xmlWriter->writeAttribute('text:style-name', 'SB' . $section->getSectionId()); $xmlWriter->endElement(); + $containerWriter = new Container($xmlWriter, $section); + $containerWriter->setPart($this); $containerWriter->write(); + $xmlWriter->endElement(); // text:section } diff --git a/src/PhpWord/Writer/ODText/Part/Manifest.php b/src/PhpWord/Writer/ODText/Part/Manifest.php index 7d428b2c76..37fb797935 100644 --- a/src/PhpWord/Writer/ODText/Part/Manifest.php +++ b/src/PhpWord/Writer/ODText/Part/Manifest.php @@ -17,7 +17,9 @@ namespace PhpOffice\PhpWord\Writer\ODText\Part; +use PhpOffice\PhpWord\Element\Formula; use PhpOffice\PhpWord\Media; +use PhpOffice\PhpWord\Writer\ODText; /** * ODText manifest part writer: META-INF/manifest.xml. @@ -31,7 +33,6 @@ class Manifest extends AbstractPart */ public function write() { - $parts = ['content.xml', 'meta.xml', 'styles.xml']; $xmlWriter = $this->getXmlWriter(); $xmlWriter->startDocument('1.0', 'UTF-8'); @@ -46,7 +47,7 @@ public function write() $xmlWriter->endElement(); // Parts - foreach ($parts as $part) { + foreach (['content.xml', 'meta.xml', 'styles.xml'] as $part) { $xmlWriter->startElement('manifest:file-entry'); $xmlWriter->writeAttribute('manifest:media-type', 'text/xml'); $xmlWriter->writeAttribute('manifest:full-path', $part); @@ -64,6 +65,20 @@ public function write() } } + foreach ($this->getObjects() as $idxObject => $object) { + if ($object instanceof Formula) { + $xmlWriter->startElement('manifest:file-entry'); + $xmlWriter->writeAttribute('manifest:full-path', 'Formula' . $idxObject . '/content.xml'); + $xmlWriter->writeAttribute('manifest:media-type', 'text/xml'); + $xmlWriter->endElement(); + $xmlWriter->startElement('manifest:file-entry'); + $xmlWriter->writeAttribute('manifest:full-path', 'Formula' . $idxObject . '/'); + $xmlWriter->writeAttribute('manifest:version', '1.2'); + $xmlWriter->writeAttribute('manifest:media-type', 'application/vnd.oasis.opendocument.formula'); + $xmlWriter->endElement(); + } + } + $xmlWriter->endElement(); // manifest:manifest return $xmlWriter->getData(); diff --git a/src/PhpWord/Writer/Word2007/Element/AbstractElement.php b/src/PhpWord/Writer/Word2007/Element/AbstractElement.php index a7bfeab78b..abd1324aad 100644 --- a/src/PhpWord/Writer/Word2007/Element/AbstractElement.php +++ b/src/PhpWord/Writer/Word2007/Element/AbstractElement.php @@ -21,6 +21,7 @@ use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Shared\Text as SharedText; use PhpOffice\PhpWord\Shared\XMLWriter; +use PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart; /** * Abstract element writer. @@ -50,6 +51,11 @@ abstract class AbstractElement */ protected $withoutP = false; + /** + * @var null|AbstractPart + */ + protected $part; + /** * Write element. */ @@ -224,4 +230,16 @@ protected function writeText($content) return $this->getXmlWriter()->writeRaw($content); } + + public function setPart(?AbstractPart $part): self + { + $this->part = $part; + + return $this; + } + + public function getPart(): ?AbstractPart + { + return $this->part; + } } diff --git a/src/PhpWord/Writer/Word2007/Element/Container.php b/src/PhpWord/Writer/Word2007/Element/Container.php index b6db45197a..491e813c9e 100644 --- a/src/PhpWord/Writer/Word2007/Element/Container.php +++ b/src/PhpWord/Writer/Word2007/Element/Container.php @@ -83,6 +83,7 @@ private function writeElement(XMLWriter $xmlWriter, Element $element, $withoutP) if (class_exists($writerClass)) { /** @var \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement $writer Type hint */ $writer = new $writerClass($xmlWriter, $element, $withoutP); + $writer->setPart($this->getPart()); $writer->write(); } diff --git a/src/PhpWord/Writer/Word2007/Element/Formula.php b/src/PhpWord/Writer/Word2007/Element/Formula.php new file mode 100644 index 0000000000..6abb74b782 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/Formula.php @@ -0,0 +1,50 @@ +getElement(); + if (!$element instanceof FormulaElement) { + return; + } + + $this->startElementP(); + + $xmlWriter = $this->getXmlWriter(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->writeElement('w:rPr'); + $xmlWriter->endElement(); + + $xmlWriter->writeRaw((new OfficeMathML())->write($element->getMath())); + + $this->endElementP(); + } +} diff --git a/tests/PhpWordTests/Element/AbstractElementTest.php b/tests/PhpWordTests/Element/AbstractElementTest.php index 8a0a878eb2..a059712b1a 100644 --- a/tests/PhpWordTests/Element/AbstractElementTest.php +++ b/tests/PhpWordTests/Element/AbstractElementTest.php @@ -17,6 +17,8 @@ namespace PhpOffice\PhpWordTests\Element; +use PhpOffice\PhpWord\Element\AbstractElement; + /** * Test class for PhpOffice\PhpWord\Element\AbstractElement. */ @@ -27,7 +29,7 @@ class AbstractElementTest extends \PHPUnit\Framework\TestCase */ public function testElementIndex(): void { - $stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Element\AbstractElement'); + $stub = $this->getMockForAbstractClass(AbstractElement::class); $ival = mt_rand(0, 100); $stub->setElementIndex($ival); self::assertEquals($ival, $stub->getElementIndex()); @@ -38,7 +40,7 @@ public function testElementIndex(): void */ public function testElementId(): void { - $stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Element\AbstractElement'); + $stub = $this->getMockForAbstractClass(AbstractElement::class); $stub->setElementId(); self::assertEquals(6, strlen($stub->getElementId())); } diff --git a/tests/PhpWordTests/Element/FormulaTest.php b/tests/PhpWordTests/Element/FormulaTest.php new file mode 100644 index 0000000000..fef5c2221e --- /dev/null +++ b/tests/PhpWordTests/Element/FormulaTest.php @@ -0,0 +1,64 @@ +add(new Element\Fraction( + new Element\Numeric(2), + new Element\Identifier('π') + )); + + $element = new Formula(new Math()); + + self::assertInstanceOf(Formula::class, $element); + self::assertEquals(new Math(), $element->getMath()); + self::assertNotEquals($math, $element->getMath()); + + self::assertInstanceOf(Formula::class, $element->setMath($math)); + self::assertNotEquals(new Math(), $element->getMath()); + self::assertEquals($math, $element->getMath()); + } +} diff --git a/tests/PhpWordTests/Reader/ODTextTest.php b/tests/PhpWordTests/Reader/ODTextTest.php index e4baf8d480..20c5916c7d 100644 --- a/tests/PhpWordTests/Reader/ODTextTest.php +++ b/tests/PhpWordTests/Reader/ODTextTest.php @@ -17,7 +17,11 @@ namespace PhpOffice\PhpWordTests\Reader; +use PhpOffice\Math\Element; +use PhpOffice\PhpWord\Element\Formula; +use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\IOFactory; +use PhpOffice\PhpWord\PhpWord; /** * Test class for PhpOffice\PhpWord\Reader\ODText. @@ -33,8 +37,31 @@ class ODTextTest extends \PHPUnit\Framework\TestCase */ public function testLoad(): void { - $filename = __DIR__ . '/../_files/documents/reader.odt'; - $phpWord = IOFactory::load($filename, 'ODText'); - self::assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); + $phpWord = IOFactory::load(dirname(__DIR__, 1) . '/_files/documents/reader.odt', 'ODText'); + self::assertInstanceOf(PhpWord::class, $phpWord); + } + + public function testLoadFormula(): void + { + $phpWord = IOFactory::load(dirname(__DIR__, 1) . '/_files/documents/reader-formula.odt', 'ODText'); + + self::assertInstanceOf(PhpWord::class, $phpWord); + + $sections = $phpWord->getSections(); + self::assertCount(1, $sections); + + $section = $sections[0]; + self::assertInstanceOf(Section::class, $section); + + $elements = $section->getElements(); + self::assertCount(1, $elements); + + $element = $elements[0]; + self::assertInstanceOf(Formula::class, $element); + + $elements = $element->getMath()->getElements(); + self::assertCount(1, $elements); + + self::assertInstanceOf(Element\Semantics::class, $elements[0]); } } diff --git a/tests/PhpWordTests/Reader/Word2007Test.php b/tests/PhpWordTests/Reader/Word2007Test.php index e42f0110d5..1d8674d729 100644 --- a/tests/PhpWordTests/Reader/Word2007Test.php +++ b/tests/PhpWordTests/Reader/Word2007Test.php @@ -18,8 +18,11 @@ namespace PhpOffice\PhpWordTests\Reader; use DateTime; +use PhpOffice\Math\Element; use PhpOffice\PhpWord\Element\Comment; +use PhpOffice\PhpWord\Element\Formula; use PhpOffice\PhpWord\Element\Image; +use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\Element\Text; use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\IOFactory; @@ -159,4 +162,58 @@ public function testLoadComments(): void self::assertInstanceOf(Font::class, $fontStyle); self::assertEquals('de-DE', $fontStyle->getLang()->getLatin()); } + + public function testLoadFormula(): void + { + $phpWord = IOFactory::load(dirname(__DIR__, 1) . '/_files/documents/reader-formula.docx'); + + self::assertInstanceOf(PhpWord::class, $phpWord); + + $sections = $phpWord->getSections(); + self::assertCount(1, $sections); + + $section = $sections[0]; + self::assertInstanceOf(Section::class, $section); + + $elements = $section->getElements(); + self::assertCount(1, $elements); + + $element = $elements[0]; + self::assertInstanceOf(Formula::class, $element); + + $elements = $element->getMath()->getElements(); + self::assertCount(5, $elements); + + /** @var Element\Fraction $element */ + $element = $elements[0]; + self::assertInstanceOf(Element\Fraction::class, $element); + /** @var Element\Identifier $numerator */ + $numerator = $element->getNumerator(); + self::assertInstanceOf(Element\Identifier::class, $numerator); + self::assertEquals('π', $numerator->getValue()); + /** @var Element\Numeric $denominator */ + $denominator = $element->getDenominator(); + self::assertInstanceOf(Element\Numeric::class, $denominator); + self::assertEquals(2, $denominator->getValue()); + + /** @var Element\Operator $element */ + $element = $elements[1]; + self::assertInstanceOf(Element\Operator::class, $element); + self::assertEquals('+', $element->getValue()); + + /** @var Element\Identifier $element */ + $element = $elements[2]; + self::assertInstanceOf(Element\Identifier::class, $element); + self::assertEquals('a', $element->getValue()); + + /** @var Element\Operator $element */ + $element = $elements[3]; + self::assertInstanceOf(Element\Operator::class, $element); + self::assertEquals('∗', $element->getValue()); + + /** @var Element\Numeric $element */ + $element = $elements[4]; + self::assertInstanceOf(Element\Numeric::class, $element); + self::assertEquals(2, $element->getValue()); + } } diff --git a/tests/PhpWordTests/Writer/ODText/Element/FormulaTest.php b/tests/PhpWordTests/Writer/ODText/Element/FormulaTest.php new file mode 100644 index 0000000000..9276372105 --- /dev/null +++ b/tests/PhpWordTests/Writer/ODText/Element/FormulaTest.php @@ -0,0 +1,71 @@ +add( + new Element\Fraction( + new Element\Numeric(2), + new Element\Identifier('π') + ) + ) + ->add( + new Element\Operator('+') + ) + ->add( + new Element\Identifier('a') + ) + ->add( + new Element\Operator('∗') + ) + ->add( + new Element\Numeric(2) + ); + + $phpWord = new PhpWord(); + + $section = $phpWord->addSection(); + $section->addFormula($math); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + + self::assertTrue($doc->elementExists('/office:document-content/office:body/office:text/text:section/text:p/draw:frame/draw:object')); + } +} diff --git a/tests/PhpWordTests/Writer/ODText/Part/ManifestTest.php b/tests/PhpWordTests/Writer/ODText/Part/ManifestTest.php new file mode 100644 index 0000000000..01a8053c8f --- /dev/null +++ b/tests/PhpWordTests/Writer/ODText/Part/ManifestTest.php @@ -0,0 +1,100 @@ +addSection(); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + + self::assertFalse($doc->elementExists( + '/manifest:manifest/manifest:file-entry[@manifest:full-path="Formula0/content.xml"]', + 'META-INF/manifest.xml' + )); + self::assertFalse($doc->elementExists( + '/manifest:manifest/manifest:file-entry[@manifest:full-path="Formula0/"]', + 'META-INF/manifest.xml' + )); + } + + public function testWriteFormula(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + + $math = new Math(); + $math->add( + new Element\Fraction( + new Element\Numeric(2), + new Element\Identifier('π') + ) + ); + $section->addFormula($math); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + + self::assertTrue($doc->elementExists( + '/manifest:manifest/manifest:file-entry[@manifest:full-path="Formula0/content.xml"]', + 'META-INF/manifest.xml' + )); + self::assertEquals('text/xml', $doc->getElementAttribute( + '/manifest:manifest/manifest:file-entry[@manifest:full-path="Formula0/content.xml"]', + 'manifest:media-type', + 'META-INF/manifest.xml' + )); + + self::assertTrue($doc->elementExists( + '/manifest:manifest/manifest:file-entry[@manifest:full-path="Formula0/"]', + 'META-INF/manifest.xml' + )); + self::assertEquals('1.2', $doc->getElementAttribute( + '/manifest:manifest/manifest:file-entry[@manifest:full-path="Formula0/"]', + 'manifest:version', + 'META-INF/manifest.xml' + )); + self::assertEquals('application/vnd.oasis.opendocument.formula', $doc->getElementAttribute( + '/manifest:manifest/manifest:file-entry[@manifest:full-path="Formula0/"]', + 'manifest:media-type', + 'META-INF/manifest.xml' + )); + } +} diff --git a/tests/PhpWordTests/Writer/Word2007/Element/FormulaTest.php b/tests/PhpWordTests/Writer/Word2007/Element/FormulaTest.php new file mode 100644 index 0000000000..b9acb1c226 --- /dev/null +++ b/tests/PhpWordTests/Writer/Word2007/Element/FormulaTest.php @@ -0,0 +1,72 @@ +add( + new Element\Fraction( + new Element\Numeric(2), + new Element\Identifier('π') + ) + ) + ->add( + new Element\Operator('+') + ) + ->add( + new Element\Identifier('a') + ) + ->add( + new Element\Operator('∗') + ) + ->add( + new Element\Numeric(2) + ); + + $phpWord = new PhpWord(); + + $section = $phpWord->addSection(); + $section->addFormula($math); + + $doc = TestHelperDOCX::getDocument($phpWord); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/m:oMathPara')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/m:oMathPara/m:oMath')); + } +} diff --git a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php index 108142d6f2..afb22f17b7 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php @@ -408,10 +408,10 @@ public function testWriteImage(): void $style = $element->getAttribute('style'); // Try to address CI coverage issue for PHP 7.1 and 7.2 when using regex match assertions - if (method_exists(static::class, 'assertRegExp')) { - self::assertRegExp('/z\-index:\-[0-9]*/', $style); - } else { + if (method_exists(static::class, 'assertMatchesRegularExpression')) { self::assertMatchesRegularExpression('/z\-index:\-[0-9]*/', $style); + } else { + self::assertRegExp('/z\-index:\-[0-9]*/', $style); } // square diff --git a/tests/PhpWordTests/XmlDocument.php b/tests/PhpWordTests/XmlDocument.php index 80d64c4357..92e19d3bb9 100644 --- a/tests/PhpWordTests/XmlDocument.php +++ b/tests/PhpWordTests/XmlDocument.php @@ -64,48 +64,55 @@ class XmlDocument private $defaultFile = 'word/document.xml'; /** - * Get default file. + * Create new instance. * - * @return string + * @param string $path + */ + public function __construct($path) + { + $this->path = realpath($path); + } + + /** + * Get default file. */ - public function getDefaultFile() + public function getDefaultFile(): string { return $this->defaultFile; } /** * Set default file. - * - * @param string $file - * - * @return string */ - public function setDefaultFile($file) + public function setDefaultFile(string $file): string { $temp = $this->defaultFile; + $this->defaultFile = $file; return $temp; } /** - * Create new instance. - * - * @param string $path + * Get file name. */ - public function __construct($path) + public function getFile(): string { - $this->path = realpath($path); + return $this->file; + } + + /** + * Get path. + */ + public function getPath(): string + { + return $this->path; } /** * Get DOM from file. - * - * @param string $file - * - * @return DOMDocument */ - public function getFileDom($file = '') + public function getFileDom(string $file = ''): DOMDocument { if (!$file) { $file = $this->defaultFile; @@ -133,12 +140,9 @@ public function getFileDom($file = '') /** * Get node list. * - * @param string $path - * @param string $file - * * @return DOMNodeList */ - public function getNodeList($path, $file = '') + public function getNodeList(string $path, string $file = ''): DOMNodeList { if (!$file) { $file = $this->defaultFile; @@ -157,73 +161,25 @@ public function getNodeList($path, $file = '') /** * Get element. - * - * @param string $path - * @param string $file - * - * @return null|DOMElement - */ - public function getElement($path, $file = '') - { - if (!$file) { - $file = $this->defaultFile; - } - $elements = $this->getNodeList($path, $file); - - return $elements->item(0); - } - - /** - * Get file name. - * - * @return string - */ - public function getFile() - { - return $this->file; - } - - /** - * Get path. - * - * @return string */ - public function getPath() + public function getElement(string $path, string $file = ''): ?DOMElement { - return $this->path; + return $this->getNodeList($path, $file)->item(0); } /** * Get element attribute. - * - * @param string $path - * @param string $attribute - * @param string $file - * - * @return string */ - public function getElementAttribute($path, $attribute, $file = '') + public function getElementAttribute(string $path, string $attribute, string $file = ''): string { - if (!$file) { - $file = $this->defaultFile; - } - return $this->getElement($path, $file)->getAttribute($attribute); } /** * Check if element exists. - * - * @param string $path - * @param string $file - * - * @return bool */ - public function elementExists($path, $file = '') + public function elementExists(string $path, string $file = ''): bool { - if (!$file) { - $file = $this->defaultFile; - } $nodeList = $this->getNodeList($path, $file); return $nodeList->length != 0; @@ -232,17 +188,10 @@ public function elementExists($path, $file = '') /** * Returns the xml, or part of it as a formatted string. * - * @param string $path - * @param string $file - * * @return false|string */ - public function printXml($path = '/', $file = '') + public function printXml(string $path = '/', string $file = '') { - if (!$file) { - $file = $this->defaultFile; - } - $element = $this->getElement($path, $file); $newdoc = new DOMDocument(); diff --git a/tests/PhpWordTests/_files/documents/reader-formula.docx b/tests/PhpWordTests/_files/documents/reader-formula.docx new file mode 100644 index 0000000000000000000000000000000000000000..0e40f6672c93bc6860e6f531e0ad216c67c85816 GIT binary patch literal 4292 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 Hq+kC5`84qb literal 0 HcmV?d00001 diff --git a/tests/PhpWordTests/_files/documents/reader-formula.odt b/tests/PhpWordTests/_files/documents/reader-formula.odt new file mode 100644 index 0000000000000000000000000000000000000000..f94c44afbb50a140896952bb05e63862adb53934 GIT binary patch literal 10565 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 literal 0 HcmV?d00001 From f1a0aef3b8cda4412ea93e3791ede88440a063f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 11:16:28 +0000 Subject: [PATCH 149/246] Bump mpdf/mpdf from 8.1.6 to 8.2.0 Bumps [mpdf/mpdf](https://github.com/mpdf/mpdf) from 8.1.6 to 8.2.0. - [Release notes](https://github.com/mpdf/mpdf/releases) - [Changelog](https://github.com/mpdf/mpdf/blob/development/CHANGELOG.md) - [Commits](https://github.com/mpdf/mpdf/compare/v8.1.6...v8.2.0) --- updated-dependencies: - dependency-name: mpdf/mpdf dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- composer.lock | 94 ++++++++++++++++++++++++++++++--------- docs/changes/1.x/1.2.0.md | 3 +- 2 files changed, 75 insertions(+), 22 deletions(-) diff --git a/composer.lock b/composer.lock index 76d598a86f..20889ca94d 100644 --- a/composer.lock +++ b/composer.lock @@ -828,26 +828,27 @@ }, { "name": "mpdf/mpdf", - "version": "v8.1.6", + "version": "v8.2.0", "source": { "type": "git", "url": "https://github.com/mpdf/mpdf.git", - "reference": "146c7c1dfd21c826b9d5bbfe3c15e52fd933c90f" + "reference": "170a236a588d177c2aa7447ce490a030ca68e6f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mpdf/mpdf/zipball/146c7c1dfd21c826b9d5bbfe3c15e52fd933c90f", - "reference": "146c7c1dfd21c826b9d5bbfe3c15e52fd933c90f", + "url": "https://api.github.com/repos/mpdf/mpdf/zipball/170a236a588d177c2aa7447ce490a030ca68e6f4", + "reference": "170a236a588d177c2aa7447ce490a030ca68e6f4", "shasum": "" }, "require": { "ext-gd": "*", "ext-mbstring": "*", + "mpdf/psr-http-message-shim": "^1.0 || ^2.0", "mpdf/psr-log-aware-trait": "^2.0 || ^3.0", "myclabs/deep-copy": "^1.7", "paragonie/random_compat": "^1.4|^2.0|^9.99.99", "php": "^5.6 || ^7.0 || ~8.0.0 || ~8.1.0 || ~8.2.0", - "psr/http-message": "^1.0", + "psr/http-message": "^1.0 || ^2.0", "psr/log": "^1.0 || ^2.0 || ^3.0", "setasign/fpdi": "^2.1" }, @@ -865,6 +866,9 @@ }, "type": "library", "autoload": { + "files": [ + "src/functions.php" + ], "psr-4": { "Mpdf\\": "src/" } @@ -901,7 +905,55 @@ "type": "custom" } ], - "time": "2023-05-03T19:36:43+00:00" + "time": "2023-09-01T11:44:52+00:00" + }, + { + "name": "mpdf/psr-http-message-shim", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/mpdf/psr-http-message-shim.git", + "reference": "1cf4c0b68b8461cea27411ff961482ce7687e34f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mpdf/psr-http-message-shim/zipball/1cf4c0b68b8461cea27411ff961482ce7687e34f", + "reference": "1cf4c0b68b8461cea27411ff961482ce7687e34f", + "shasum": "" + }, + "require": { + "psr/http-message": "^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Mpdf\\PsrHttpMessageShim\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Dorison", + "email": "mark@chromatichq.com" + }, + { + "name": "Kristofer Widholm", + "email": "kristofer@chromatichq.com" + }, + { + "name": "Nigel Cunningham", + "email": "nigel.cunningham@technocrat.com.au" + } + ], + "description": "Shim to allow support of different psr/message versions.", + "support": { + "issues": "https://github.com/mpdf/psr-http-message-shim/issues", + "source": "https://github.com/mpdf/psr-http-message-shim/tree/2.0.0" + }, + "time": "2023-09-01T06:08:18+00:00" }, { "name": "mpdf/psr-log-aware-trait", @@ -2197,16 +2249,16 @@ }, { "name": "psr/http-message", - "version": "1.1", + "version": "2.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { @@ -2215,7 +2267,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -2230,7 +2282,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP messages", @@ -2244,9 +2296,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/1.1" + "source": "https://github.com/php-fig/http-message/tree/2.0" }, - "time": "2023-04-04T09:50:52+00:00" + "time": "2023-04-04T09:54:51+00:00" }, { "name": "psr/log", @@ -3317,16 +3369,16 @@ }, { "name": "setasign/fpdi", - "version": "v2.3.7", + "version": "v2.5.0", "source": { "type": "git", "url": "https://github.com/Setasign/FPDI.git", - "reference": "bccc892d5fa1f48c43f8ba7db5ed4ba6f30c8c05" + "reference": "ecf0459643ec963febfb9a5d529dcd93656006a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Setasign/FPDI/zipball/bccc892d5fa1f48c43f8ba7db5ed4ba6f30c8c05", - "reference": "bccc892d5fa1f48c43f8ba7db5ed4ba6f30c8c05", + "url": "https://api.github.com/repos/Setasign/FPDI/zipball/ecf0459643ec963febfb9a5d529dcd93656006a4", + "reference": "ecf0459643ec963febfb9a5d529dcd93656006a4", "shasum": "" }, "require": { @@ -3339,7 +3391,7 @@ "require-dev": { "phpunit/phpunit": "~5.7", "setasign/fpdf": "~1.8", - "setasign/tfpdf": "1.31", + "setasign/tfpdf": "~1.31", "squizlabs/php_codesniffer": "^3.5", "tecnickcom/tcpdf": "~6.2" }, @@ -3377,7 +3429,7 @@ ], "support": { "issues": "https://github.com/Setasign/FPDI/issues", - "source": "https://github.com/Setasign/FPDI/tree/v2.3.7" + "source": "https://github.com/Setasign/FPDI/tree/v2.5.0" }, "funding": [ { @@ -3385,7 +3437,7 @@ "type": "tidelift" } ], - "time": "2023-02-09T10:38:43+00:00" + "time": "2023-09-28T10:46:27+00:00" }, { "name": "symfony/config", diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index 40becc441d..a4810f16cd 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -36,4 +36,5 @@ - Bump phpstan/phpstan-phpunit from 1.3.13 to 1.3.14 by [@dependabot](https://github.com/dependabot) in [#2457](https://github.com/PHPOffice/PHPWord/pull/2457) - Bump symfony/process from 5.4.26 to 5.4.28 by [@dependabot](https://github.com/dependabot) in [#2456](https://github.com/PHPOffice/PHPWord/pull/2456) - Bump phpunit/phpunit from 9.6.10 to 9.6.11 by [@dependabot](https://github.com/dependabot) in [#2455](https://github.com/PHPOffice/PHPWord/pull/2455) -- Remove deprecated utf8_encode in PHP 8.2 by [@mhcwebdesign](https://github.com/mhcwebdesign) in [#2447](https://github.com/PHPOffice/PHPWord/pull/2447) & [#2472](https://github.com/PHPOffice/PHPWord/pull/2472) \ No newline at end of file +- Remove deprecated utf8_encode in PHP 8.2 by [@mhcwebdesign](https://github.com/mhcwebdesign) in [#2447](https://github.com/PHPOffice/PHPWord/pull/2447) & [#2472](https://github.com/PHPOffice/PHPWord/pull/2472) +- Bump mpdf/mpdf from 8.1.6 to 8.2.0 by [@dependabot](https://github.com/dependabot) in [#2480](https://github.com/PHPOffice/PHPWord/pull/2480) \ No newline at end of file From fce135310243915ea3bc393df56270a3772b3709 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 14:00:18 +0000 Subject: [PATCH 150/246] Bump phpunit/phpunit from 9.6.11 to 9.6.13 Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.11 to 9.6.13. - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/9.6.13/ChangeLog-9.6.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.6.11...9.6.13) --- updated-dependencies: - dependency-name: phpunit/phpunit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 26 +++++++++++++------------- docs/changes/1.x/1.2.0.md | 3 ++- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/composer.lock b/composer.lock index 20889ca94d..bccf406222 100644 --- a/composer.lock +++ b/composer.lock @@ -1680,16 +1680,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.27", + "version": "9.2.29", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1" + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/b0a88255cb70d52653d80c890bd7f38740ea50d1", - "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", "shasum": "" }, "require": { @@ -1746,7 +1746,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.27" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29" }, "funding": [ { @@ -1754,7 +1754,7 @@ "type": "github" } ], - "time": "2023-07-26T13:44:30+00:00" + "time": "2023-09-19T04:57:46+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1999,16 +1999,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.11", + "version": "9.6.13", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "810500e92855eba8a7a5319ae913be2da6f957b0" + "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/810500e92855eba8a7a5319ae913be2da6f957b0", - "reference": "810500e92855eba8a7a5319ae913be2da6f957b0", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f3d767f7f9e191eab4189abe41ab37797e30b1be", + "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be", "shasum": "" }, "require": { @@ -2023,7 +2023,7 @@ "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-code-coverage": "^9.2.28", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", "phpunit/php-text-template": "^2.0.3", @@ -2082,7 +2082,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.11" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.13" }, "funding": [ { @@ -2098,7 +2098,7 @@ "type": "tidelift" } ], - "time": "2023-08-19T07:10:56+00:00" + "time": "2023-09-19T05:39:22+00:00" }, { "name": "psr/cache", diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index a4810f16cd..bfb1cc3bb2 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -37,4 +37,5 @@ - Bump symfony/process from 5.4.26 to 5.4.28 by [@dependabot](https://github.com/dependabot) in [#2456](https://github.com/PHPOffice/PHPWord/pull/2456) - Bump phpunit/phpunit from 9.6.10 to 9.6.11 by [@dependabot](https://github.com/dependabot) in [#2455](https://github.com/PHPOffice/PHPWord/pull/2455) - Remove deprecated utf8_encode in PHP 8.2 by [@mhcwebdesign](https://github.com/mhcwebdesign) in [#2447](https://github.com/PHPOffice/PHPWord/pull/2447) & [#2472](https://github.com/PHPOffice/PHPWord/pull/2472) -- Bump mpdf/mpdf from 8.1.6 to 8.2.0 by [@dependabot](https://github.com/dependabot) in [#2480](https://github.com/PHPOffice/PHPWord/pull/2480) \ No newline at end of file +- Bump mpdf/mpdf from 8.1.6 to 8.2.0 by [@dependabot](https://github.com/dependabot) in [#2480](https://github.com/PHPOffice/PHPWord/pull/2480) +- 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) \ No newline at end of file From cc484c1b03494731f2241d6d524b1aa0447846d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 19:01:27 +0000 Subject: [PATCH 151/246] Bump tecnickcom/tcpdf from 6.6.2 to 6.6.5 Bumps [tecnickcom/tcpdf](https://github.com/tecnickcom/TCPDF) from 6.6.2 to 6.6.5. - [Changelog](https://github.com/tecnickcom/TCPDF/blob/main/CHANGELOG.TXT) - [Commits](https://github.com/tecnickcom/TCPDF/compare/6.6.2...6.6.5) --- updated-dependencies: - dependency-name: tecnickcom/tcpdf dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 14 +++++++------- docs/changes/1.x/1.2.0.md | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/composer.lock b/composer.lock index bccf406222..c17a5fdd98 100644 --- a/composer.lock +++ b/composer.lock @@ -4998,16 +4998,16 @@ }, { "name": "tecnickcom/tcpdf", - "version": "6.6.2", + "version": "6.6.5", "source": { "type": "git", "url": "https://github.com/tecnickcom/TCPDF.git", - "reference": "e3cffc9bcbc76e89e167e9eb0bbda0cab7518459" + "reference": "5fce932fcee4371865314ab7f6c0d85423c5c7ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/e3cffc9bcbc76e89e167e9eb0bbda0cab7518459", - "reference": "e3cffc9bcbc76e89e167e9eb0bbda0cab7518459", + "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/5fce932fcee4371865314ab7f6c0d85423c5c7ce", + "reference": "5fce932fcee4371865314ab7f6c0d85423c5c7ce", "shasum": "" }, "require": { @@ -5036,7 +5036,7 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0-only" + "LGPL-3.0-or-later" ], "authors": [ { @@ -5058,7 +5058,7 @@ ], "support": { "issues": "https://github.com/tecnickcom/TCPDF/issues", - "source": "https://github.com/tecnickcom/TCPDF/tree/6.6.2" + "source": "https://github.com/tecnickcom/TCPDF/tree/6.6.5" }, "funding": [ { @@ -5066,7 +5066,7 @@ "type": "custom" } ], - "time": "2022-12-17T10:28:59+00:00" + "time": "2023-09-06T15:09:26+00:00" }, { "name": "theseer/tokenizer", diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index bfb1cc3bb2..1a361b6bd0 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -38,4 +38,5 @@ - Bump phpunit/phpunit from 9.6.10 to 9.6.11 by [@dependabot](https://github.com/dependabot) in [#2455](https://github.com/PHPOffice/PHPWord/pull/2455) - Remove deprecated utf8_encode in PHP 8.2 by [@mhcwebdesign](https://github.com/mhcwebdesign) in [#2447](https://github.com/PHPOffice/PHPWord/pull/2447) & [#2472](https://github.com/PHPOffice/PHPWord/pull/2472) - Bump mpdf/mpdf from 8.1.6 to 8.2.0 by [@dependabot](https://github.com/dependabot) in [#2480](https://github.com/PHPOffice/PHPWord/pull/2480) -- 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) \ No newline at end of file +- 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) \ No newline at end of file From e72c65333b5330bac9e290b3c77e63385da71a78 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 12:43:10 +0000 Subject: [PATCH 152/246] Bump phpmd/phpmd from 2.13.0 to 2.14.1 Bumps [phpmd/phpmd](https://github.com/phpmd/phpmd) from 2.13.0 to 2.14.1. - [Release notes](https://github.com/phpmd/phpmd/releases) - [Changelog](https://github.com/phpmd/phpmd/blob/master/CHANGELOG) - [Commits](https://github.com/phpmd/phpmd/compare/2.13.0...2.14.1) --- updated-dependencies: - dependency-name: phpmd/phpmd dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- composer.lock | 109 +++++++++++++++++++------------------- docs/changes/1.x/1.2.0.md | 3 +- 2 files changed, 57 insertions(+), 55 deletions(-) diff --git a/composer.lock b/composer.lock index c17a5fdd98..56c51464eb 100644 --- a/composer.lock +++ b/composer.lock @@ -1166,16 +1166,16 @@ }, { "name": "pdepend/pdepend", - "version": "2.14.0", + "version": "2.15.1", "source": { "type": "git", "url": "https://github.com/pdepend/pdepend.git", - "reference": "1121d4b04af06e33e9659bac3a6741b91cab1de1" + "reference": "d12f25bcdfb7754bea458a4a5cb159d55e9950d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pdepend/pdepend/zipball/1121d4b04af06e33e9659bac3a6741b91cab1de1", - "reference": "1121d4b04af06e33e9659bac3a6741b91cab1de1", + "url": "https://api.github.com/repos/pdepend/pdepend/zipball/d12f25bcdfb7754bea458a4a5cb159d55e9950d0", + "reference": "d12f25bcdfb7754bea458a4a5cb159d55e9950d0", "shasum": "" }, "require": { @@ -1217,7 +1217,7 @@ ], "support": { "issues": "https://github.com/pdepend/pdepend/issues", - "source": "https://github.com/pdepend/pdepend/tree/2.14.0" + "source": "https://github.com/pdepend/pdepend/tree/2.15.1" }, "funding": [ { @@ -1225,7 +1225,7 @@ "type": "tidelift" } ], - "time": "2023-05-26T13:15:18+00:00" + "time": "2023-09-28T12:00:56+00:00" }, { "name": "phar-io/manifest", @@ -1483,22 +1483,22 @@ }, { "name": "phpmd/phpmd", - "version": "2.13.0", + "version": "2.14.1", "source": { "type": "git", "url": "https://github.com/phpmd/phpmd.git", - "reference": "dad0228156856b3ad959992f9748514fa943f3e3" + "reference": "442fc2c34edcd5198b442d8647c7f0aec3afabe8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpmd/phpmd/zipball/dad0228156856b3ad959992f9748514fa943f3e3", - "reference": "dad0228156856b3ad959992f9748514fa943f3e3", + "url": "https://api.github.com/repos/phpmd/phpmd/zipball/442fc2c34edcd5198b442d8647c7f0aec3afabe8", + "reference": "442fc2c34edcd5198b442d8647c7f0aec3afabe8", "shasum": "" }, "require": { "composer/xdebug-handler": "^1.0 || ^2.0 || ^3.0", "ext-xml": "*", - "pdepend/pdepend": "^2.12.1", + "pdepend/pdepend": "^2.15.1", "php": ">=5.3.9" }, "require-dev": { @@ -1508,7 +1508,7 @@ "gregwar/rst": "^1.0", "mikey179/vfsstream": "^1.6.8", "phpunit/phpunit": "^4.8.36 || ^5.7.27", - "squizlabs/php_codesniffer": "^2.0" + "squizlabs/php_codesniffer": "^2.9.2 || ^3.7.2" }, "bin": [ "src/bin/phpmd" @@ -1545,6 +1545,7 @@ "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", "homepage": "https://phpmd.org/", "keywords": [ + "dev", "mess detection", "mess detector", "pdepend", @@ -1554,7 +1555,7 @@ "support": { "irc": "irc://irc.freenode.org/phpmd", "issues": "https://github.com/phpmd/phpmd/issues", - "source": "https://github.com/phpmd/phpmd/tree/2.13.0" + "source": "https://github.com/phpmd/phpmd/tree/2.14.1" }, "funding": [ { @@ -1562,7 +1563,7 @@ "type": "tidelift" } ], - "time": "2022-09-10T08:44:15+00:00" + "time": "2023-09-28T13:07:44+00:00" }, { "name": "phpstan/phpstan", @@ -3441,16 +3442,16 @@ }, { "name": "symfony/config", - "version": "v5.4.21", + "version": "v5.4.26", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "2a6b1111d038adfa15d52c0871e540f3b352d1e4" + "reference": "8109892f27beed9252bd1f1c1880aeb4ad842650" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/2a6b1111d038adfa15d52c0871e540f3b352d1e4", - "reference": "2a6b1111d038adfa15d52c0871e540f3b352d1e4", + "url": "https://api.github.com/repos/symfony/config/zipball/8109892f27beed9252bd1f1c1880aeb4ad842650", + "reference": "8109892f27beed9252bd1f1c1880aeb4ad842650", "shasum": "" }, "require": { @@ -3500,7 +3501,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com/", "support": { - "source": "https://github.com/symfony/config/tree/v5.4.21" + "source": "https://github.com/symfony/config/tree/v5.4.26" }, "funding": [ { @@ -3516,7 +3517,7 @@ "type": "tidelift" } ], - "time": "2023-02-14T08:03:56+00:00" + "time": "2023-07-19T20:21:11+00:00" }, { "name": "symfony/console", @@ -3618,16 +3619,16 @@ }, { "name": "symfony/dependency-injection", - "version": "v5.4.24", + "version": "v5.4.29", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "4645e032d0963fb614969398ca28e47605b1a7da" + "reference": "338638ed8c9d5c7fcb136a73f5c7043465ae2f05" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/4645e032d0963fb614969398ca28e47605b1a7da", - "reference": "4645e032d0963fb614969398ca28e47605b1a7da", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/338638ed8c9d5c7fcb136a73f5c7043465ae2f05", + "reference": "338638ed8c9d5c7fcb136a73f5c7043465ae2f05", "shasum": "" }, "require": { @@ -3687,7 +3688,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com/", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v5.4.24" + "source": "https://github.com/symfony/dependency-injection/tree/v5.4.29" }, "funding": [ { @@ -3703,7 +3704,7 @@ "type": "tidelift" } ], - "time": "2023-05-05T14:42:55+00:00" + "time": "2023-09-20T06:23:43+00:00" }, { "name": "symfony/deprecation-contracts", @@ -3938,16 +3939,16 @@ }, { "name": "symfony/filesystem", - "version": "v5.4.23", + "version": "v5.4.25", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "b2f79d86cd9e7de0fff6d03baa80eaed7a5f38b5" + "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/b2f79d86cd9e7de0fff6d03baa80eaed7a5f38b5", - "reference": "b2f79d86cd9e7de0fff6d03baa80eaed7a5f38b5", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", + "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", "shasum": "" }, "require": { @@ -3982,7 +3983,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com/", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.23" + "source": "https://github.com/symfony/filesystem/tree/v5.4.25" }, "funding": [ { @@ -3998,7 +3999,7 @@ "type": "tidelift" } ], - "time": "2023-03-02T11:38:35+00:00" + "time": "2023-05-31T13:04:02+00:00" }, { "name": "symfony/finder", @@ -4134,16 +4135,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", "shasum": "" }, "require": { @@ -4158,7 +4159,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4196,7 +4197,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" }, "funding": [ { @@ -4212,7 +4213,7 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -4381,16 +4382,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + "reference": "42292d99c55abe617799667f454222c54c60e229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", + "reference": "42292d99c55abe617799667f454222c54c60e229", "shasum": "" }, "require": { @@ -4405,7 +4406,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4444,7 +4445,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" }, "funding": [ { @@ -4460,7 +4461,7 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-07-28T09:04:16+00:00" }, { "name": "symfony/polyfill-php73", @@ -4626,16 +4627,16 @@ }, { "name": "symfony/polyfill-php81", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", "shasum": "" }, "require": { @@ -4644,7 +4645,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4685,7 +4686,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" }, "funding": [ { @@ -4701,7 +4702,7 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/process", @@ -5140,5 +5141,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index 1a361b6bd0..60ffd9eac2 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -39,4 +39,5 @@ - Remove deprecated utf8_encode in PHP 8.2 by [@mhcwebdesign](https://github.com/mhcwebdesign) in [#2447](https://github.com/PHPOffice/PHPWord/pull/2447) & [#2472](https://github.com/PHPOffice/PHPWord/pull/2472) - Bump mpdf/mpdf from 8.1.6 to 8.2.0 by [@dependabot](https://github.com/dependabot) in [#2480](https://github.com/PHPOffice/PHPWord/pull/2480) - 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) \ No newline at end of file +- 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) \ No newline at end of file From 3bf29c7e20908ccb511bf85a436c5212e5b56258 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 15:12:49 +0000 Subject: [PATCH 153/246] Bump phpstan/phpstan-phpunit from 1.3.14 to 1.3.15 Bumps [phpstan/phpstan-phpunit](https://github.com/phpstan/phpstan-phpunit) from 1.3.14 to 1.3.15. - [Release notes](https://github.com/phpstan/phpstan-phpunit/releases) - [Commits](https://github.com/phpstan/phpstan-phpunit/compare/1.3.14...1.3.15) --- updated-dependencies: - dependency-name: phpstan/phpstan-phpunit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 26 +++++++-------- docs/changes/1.x/1.2.0.md | 3 +- phpstan-baseline.neon | 5 --- .../Reader/Word2007/ElementTest.php | 33 ++++++++++++------- 4 files changed, 36 insertions(+), 31 deletions(-) diff --git a/composer.lock b/composer.lock index 56c51464eb..23452781b4 100644 --- a/composer.lock +++ b/composer.lock @@ -1567,16 +1567,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.32", + "version": "1.10.40", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "c47e47d3ab03137c0e121e77c4d2cb58672f6d44" + "reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c47e47d3ab03137c0e121e77c4d2cb58672f6d44", - "reference": "c47e47d3ab03137c0e121e77c4d2cb58672f6d44", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/93c84b5bf7669920d823631e39904d69b9c7dc5d", + "reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d", "shasum": "" }, "require": { @@ -1625,20 +1625,20 @@ "type": "tidelift" } ], - "time": "2023-08-24T21:54:50+00:00" + "time": "2023-10-30T14:48:31+00:00" }, { "name": "phpstan/phpstan-phpunit", - "version": "1.3.14", + "version": "1.3.15", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "614acc10c522e319639bf38b0698a4a566665f04" + "reference": "70ecacc64fe8090d8d2a33db5a51fe8e88acd93a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/614acc10c522e319639bf38b0698a4a566665f04", - "reference": "614acc10c522e319639bf38b0698a4a566665f04", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/70ecacc64fe8090d8d2a33db5a51fe8e88acd93a", + "reference": "70ecacc64fe8090d8d2a33db5a51fe8e88acd93a", "shasum": "" }, "require": { @@ -1675,9 +1675,9 @@ "description": "PHPUnit extensions and rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.14" + "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.15" }, - "time": "2023-08-25T09:46:39+00:00" + "time": "2023-10-09T18:58:39+00:00" }, { "name": "phpunit/php-code-coverage", @@ -5122,9 +5122,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "phpstan/phpstan-phpunit": 0 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index 60ffd9eac2..16d16a47d0 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -40,4 +40,5 @@ - Bump mpdf/mpdf from 8.1.6 to 8.2.0 by [@dependabot](https://github.com/dependabot) in [#2480](https://github.com/PHPOffice/PHPWord/pull/2480) - 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) \ No newline at end of file +- 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 diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 2dd69c7278..088d4c5427 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1690,11 +1690,6 @@ parameters: count: 1 path: tests/PhpWordTests/PhpWordTest.php - - - message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:getElements\\(\\)\\.$#" - count: 1 - path: tests/PhpWordTests/Reader/Word2007/ElementTest.php - - message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement\\:\\:getRows\\(\\)\\.$#" count: 1 diff --git a/tests/PhpWordTests/Reader/Word2007/ElementTest.php b/tests/PhpWordTests/Reader/Word2007/ElementTest.php index 9c002236ed..f96d8ac1a2 100644 --- a/tests/PhpWordTests/Reader/Word2007/ElementTest.php +++ b/tests/PhpWordTests/Reader/Word2007/ElementTest.php @@ -17,7 +17,9 @@ namespace PhpOffice\PhpWordTests\Reader\Word2007; +use PhpOffice\PhpWord\Element\Text; use PhpOffice\PhpWord\Element\TrackChange; +use PhpOffice\PhpWord\Style\Font; use PhpOffice\PhpWordTests\AbstractTestReader; /** @@ -60,7 +62,7 @@ public function testReadAlternateContent(): void $elements = $phpWord->getSection(0)->getElements(); self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); - self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $elements[0]->getElement(0)); + self::assertInstanceOf(Text::class, $elements[0]->getElement(0)); $text = $elements[0]; self::assertEquals('Test node value', trim($text->getElement(0)->getText())); } @@ -84,7 +86,7 @@ public function testReadTextBreak(): void /** @var \PhpOffice\PhpWord\Element\TextRun $textRun */ $textRun = $elements[0]; self::assertInstanceOf('PhpOffice\PhpWord\Element\TextBreak', $textRun->getElement(0)); - self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(1)); + self::assertInstanceOf(Text::class, $textRun->getElement(1)); self::assertEquals('test string', $textRun->getElement(1)->getText()); } @@ -107,7 +109,7 @@ public function testSmartTag(): void self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); /** @var \PhpOffice\PhpWord\Element\TextRun $textRun */ $textRun = $elements[0]; - self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(0)); + self::assertInstanceOf(Text::class, $textRun->getElement(0)); self::assertEquals('test string', $textRun->getElement(0)->getText()); } @@ -145,11 +147,20 @@ public function testReadListItemRunWithFormatting(): void self::assertEquals(0, $sections->getElement(0)->getDepth()); $listElements = $sections->getElement(0)->getElements(); - self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $listElements[0]); - self::assertEquals('Two', $listElements[0]->getText()); - self::assertEquals(' with ', $listElements[1]->getText()); - self::assertEquals('bold', $listElements[2]->getText()); - self::assertTrue($listElements[2]->getFontStyle()->isBold()); + /** @var Text $listElement0 */ + $listElement0 = $listElements[0]; + self::assertInstanceOf(Text::class, $listElement0); + self::assertEquals('Two', $listElement0->getText()); + /** @var Text $listElement1 */ + $listElement1 = $listElements[1]; + self::assertEquals(' with ', $listElement1->getText()); + /** @var Text $listElement2 */ + $listElement2 = $listElements[2]; + self::assertEquals('bold', $listElement2->getText()); + /** @var Font $listElement2FontStyle */ + $listElement2FontStyle = $listElement2->getFontStyle(); + self::assertInstanceOf(Font::class, $listElement2FontStyle); + self::assertTrue($listElement2FontStyle->isBold()); } /** @@ -214,11 +225,11 @@ public function testReadTab(): void self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); /** @var \PhpOffice\PhpWord\Element\TextRun $textRun */ $textRun = $elements[0]; - self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(0)); + self::assertInstanceOf(Text::class, $textRun->getElement(0)); self::assertEquals('One', $textRun->getElement(0)->getText()); - self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(1)); + self::assertInstanceOf(Text::class, $textRun->getElement(1)); self::assertEquals("\t", $textRun->getElement(1)->getText()); - self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(2)); + self::assertInstanceOf(Text::class, $textRun->getElement(2)); self::assertEquals('Two', $textRun->getElement(2)->getText()); } From 21f71c90c1247ea5a135ff3d909b52e19c22b368 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Mon, 18 Sep 2023 16:28:09 -0700 Subject: [PATCH 154/246] Add Support for Various Missing Features in HTML Writer This PR supersedes #1814 and #2343, which had become badly out of sync due to recent changes to the repository. Implement a number of features implemented in PhpWord, but not yet supported in PhpWord HTML Writer. 1. Use css @page and page declarations for sections. 2. Wrap sections in div, with page break before each (except first). 3. Add ability to specify generic fallback font for html (documentation change). 4. Add ability to specify handling of whitespace in html (documentation change). Currently, Word writer preserves space but HTML writer does not. 5. Support for Language, both for document overall and individual text elements. 6. Support for PageBreak for HTML (currently only PDF is supported). 7. Support for Table Border style, color, and size. 8. Support for empty paragraphs (Word writer permits, browsers generally suppress). 9. Default paragraph style should apply to all paragraphs, as well as class Normal. 10. Paragraph style should support line-height. 11. Paragraph style should support indentation. 12. Paragraph style should support page-break-before. 13. Paragraph style should not specify margin-top/bottom when spacing is null. --- composer.json | 1 - composer.lock | 62 ---- docs/usage/styles/font.md | 4 +- docs/usage/writers.md | 9 + phpstan-baseline.neon | 130 -------- phpunit.xml.dist | 49 ++- samples/Sample_36_RTL.php | 12 +- samples/Sample_52_RTLDefault.php | 34 ++ src/PhpWord/Element/Cell.php | 2 +- src/PhpWord/Element/Image.php | 4 +- src/PhpWord/PhpWord.php | 110 ++++--- src/PhpWord/Reader/MsDoc.php | 30 +- src/PhpWord/Shared/Handler.php | 46 +++ src/PhpWord/Shared/Html.php | 14 +- src/PhpWord/Shared/Text.php | 19 +- src/PhpWord/Shared/XMLReader.php | 8 +- src/PhpWord/Style.php | 16 + src/PhpWord/Style/Font.php | 128 +++++++- src/PhpWord/Style/Indentation.php | 8 +- src/PhpWord/Style/Paragraph.php | 31 +- src/PhpWord/Style/Spacing.php | 18 +- src/PhpWord/Style/Table.php | 11 +- src/PhpWord/TemplateProcessor.php | 35 +- src/PhpWord/Writer/HTML.php | 74 ++++- .../Writer/HTML/Element/AbstractElement.php | 7 - src/PhpWord/Writer/HTML/Element/Link.php | 12 +- src/PhpWord/Writer/HTML/Element/ListItem.php | 8 +- src/PhpWord/Writer/HTML/Element/PageBreak.php | 5 +- src/PhpWord/Writer/HTML/Element/Table.php | 94 ++++-- src/PhpWord/Writer/HTML/Element/Text.php | 57 ++-- src/PhpWord/Writer/HTML/Element/Title.php | 8 +- src/PhpWord/Writer/HTML/Part/AbstractPart.php | 22 +- src/PhpWord/Writer/HTML/Part/Body.php | 9 + src/PhpWord/Writer/HTML/Part/Head.php | 68 +++- .../Writer/HTML/Style/AbstractStyle.php | 19 +- src/PhpWord/Writer/HTML/Style/Font.php | 34 +- src/PhpWord/Writer/HTML/Style/Paragraph.php | 38 ++- src/PhpWord/Writer/ODText/Element/Table.php | 2 +- src/PhpWord/Writer/ODText/Element/Title.php | 3 +- src/PhpWord/Writer/ODText/Part/Content.php | 2 +- src/PhpWord/Writer/ODText/Style/Paragraph.php | 28 +- src/PhpWord/Writer/PDF.php | 5 + src/PhpWord/Writer/PDF/AbstractRenderer.php | 3 +- src/PhpWord/Writer/PDF/DomPDF.php | 4 +- src/PhpWord/Writer/PDF/MPDF.php | 28 +- src/PhpWord/Writer/PDF/TCPDF.php | 48 ++- .../Writer/RTF/Element/AbstractElement.php | 43 ++- src/PhpWord/Writer/RTF/Element/Container.php | 33 +- src/PhpWord/Writer/RTF/Element/Table.php | 6 +- src/PhpWord/Writer/RTF/Element/Title.php | 13 +- src/PhpWord/Writer/RTF/Part/AbstractPart.php | 6 +- src/PhpWord/Writer/RTF/Part/Document.php | 8 +- .../Writer/RTF/Style/AbstractStyle.php | 82 ++++- src/PhpWord/Writer/RTF/Style/Paragraph.php | 25 +- src/PhpWord/Writer/Word2007/Element/TOC.php | 7 +- .../Writer/Word2007/Element/TOC.php.bak | 202 ++++++++++++ src/PhpWord/Writer/Word2007/Element/Title.php | 3 +- src/PhpWord/Writer/WriterInterface.php | 4 +- .../Collection/CollectionTest.php | 3 - tests/PhpWordTests/Element/CellTest.php | 10 +- tests/PhpWordTests/Element/FooterTest.php | 4 +- tests/PhpWordTests/Element/HeaderTest.php | 4 +- tests/PhpWordTests/Element/ImageTest.php | 2 +- .../PhpWordTests/Element/ListItemRunTest.php | 2 +- tests/PhpWordTests/Element/SectionTest.php | 10 +- tests/PhpWordTests/Element/TextRunTest.php | 2 +- tests/PhpWordTests/Element/Utf8Decode.php | 29 ++ .../PhpWordTests/Escaper/RtfEscaper3Test.php | 95 ++++++ tests/PhpWordTests/IOFactoryTest.php | 2 +- tests/PhpWordTests/PhpWordTest.php | 7 +- tests/PhpWordTests/Reader/Word2007Test.php | 8 + tests/PhpWordTests/Shared/HandlerTest.php | 79 +++++ tests/PhpWordTests/Shared/HtmlTest.php | 11 + tests/PhpWordTests/Shared/TextTest.php | 3 +- tests/PhpWordTests/Style/FontTest.php | 5 + tests/PhpWordTests/Style/ParagraphTest.php | 1 + tests/PhpWordTests/TemplateProcessorTest.php | 49 +-- tests/PhpWordTests/TestHelperDOCX.php | 3 +- .../Writer/HTML/DirectionTest.php | 57 ++++ .../PhpWordTests/Writer/HTML/ElementTest.php | 28 +- tests/PhpWordTests/Writer/HTML/FontTest.php | 301 ++++++++++++++++++ tests/PhpWordTests/Writer/HTML/Helper.php | 95 ++++++ .../Writer/HTML/ParagraphTest.php | 137 ++++++++ tests/PhpWordTests/Writer/HTML/PartTest.php | 152 +++++++++ tests/PhpWordTests/Writer/HTML/StyleTest.php | 141 ++++++++ .../Writer/ODText/Element/ImageTest.php | 31 ++ .../Writer/ODText/ElementTest.php | 2 +- .../Writer/ODText/Style/FontTest.php | 2 +- .../Writer/ODText/Style/Paragraph2Test.php | 153 +++++++++ tests/PhpWordTests/Writer/ODTextTest.php | 7 +- tests/PhpWordTests/Writer/PDF/MPDFTest.php | 35 +- tests/PhpWordTests/Writer/PDF/TCPDFTest.php | 1 + tests/PhpWordTests/Writer/PDFTest.php | 4 +- .../PhpWordTests/Writer/RTF/Element2Test.php | 122 +++++++ tests/PhpWordTests/Writer/RTF/StyleTest.php | 26 ++ tests/PhpWordTests/Writer/RTFTest.php | 7 +- .../Writer/Word2007/Element/TOCTest.php | 2 +- .../Writer/Word2007/Part/DocumentTest.php | 60 ++-- .../Writer/Word2007/Part/FooterTest.php | 9 +- .../Writer/Word2007/Part/HeaderTest.php | 9 +- .../Writer/Word2007/Style/DirectionTest.php | 61 ++++ tests/PhpWordTests/Writer/Word2007Test.php | 15 +- tests/bootstrap.php | 32 ++ 103 files changed, 2968 insertions(+), 641 deletions(-) create mode 100644 samples/Sample_52_RTLDefault.php create mode 100644 src/PhpWord/Shared/Handler.php create mode 100644 src/PhpWord/Writer/Word2007/Element/TOC.php.bak create mode 100644 tests/PhpWordTests/Element/Utf8Decode.php create mode 100644 tests/PhpWordTests/Escaper/RtfEscaper3Test.php create mode 100644 tests/PhpWordTests/Shared/HandlerTest.php create mode 100644 tests/PhpWordTests/Writer/HTML/DirectionTest.php create mode 100644 tests/PhpWordTests/Writer/HTML/FontTest.php create mode 100644 tests/PhpWordTests/Writer/HTML/Helper.php create mode 100644 tests/PhpWordTests/Writer/HTML/ParagraphTest.php create mode 100644 tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php create mode 100644 tests/PhpWordTests/Writer/RTF/Element2Test.php create mode 100644 tests/PhpWordTests/Writer/Word2007/Style/DirectionTest.php diff --git a/composer.json b/composer.json index 4a0a5789f1..7e0deaa092 100644 --- a/composer.json +++ b/composer.json @@ -68,7 +68,6 @@ "ext-dom": "*", "ext-json": "*", "ext-xml": "*", - "laminas/laminas-escaper": ">=2.6", "phpoffice/math": "^0.1" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 23452781b4..0f140f1e5a 100644 --- a/composer.lock +++ b/composer.lock @@ -6,68 +6,6 @@ ], "content-hash": "23680170abecc52de95d0833296ced64", "packages": [ - { - "name": "laminas/laminas-escaper", - "version": "2.12.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-escaper.git", - "reference": "ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490", - "reference": "ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-mbstring": "*", - "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0" - }, - "conflict": { - "zendframework/zend-escaper": "*" - }, - "require-dev": { - "infection/infection": "^0.26.6", - "laminas/laminas-coding-standard": "~2.4.0", - "maglnet/composer-require-checker": "^3.8.0", - "phpunit/phpunit": "^9.5.18", - "psalm/plugin-phpunit": "^0.17.0", - "vimeo/psalm": "^4.22.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\Escaper\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs", - "homepage": "https://laminas.dev/", - "keywords": [ - "escaper", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-escaper/", - "forum": "https://discourse.laminas.dev/", - "issues": "https://github.com/laminas/laminas-escaper/issues", - "rss": "https://github.com/laminas/laminas-escaper/releases.atom", - "source": "https://github.com/laminas/laminas-escaper" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-10-10T10:11:09+00:00" - }, { "name": "phpoffice/math", "version": "0.1.0", diff --git a/docs/usage/styles/font.md b/docs/usage/styles/font.md index 90e492bf0e..94b59b6500 100644 --- a/docs/usage/styles/font.md +++ b/docs/usage/styles/font.md @@ -23,4 +23,6 @@ Available Font style options: - ``lang``. Language, either a language code like *en-US*, *fr-BE*, etc. or an object (or as an array) if you need to set eastAsian or bidirectional languages 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*. \ No newline at end of file +- ``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). diff --git a/docs/usage/writers.md b/docs/usage/writers.md index 684abeeeac..f68008bf87 100644 --- a/docs/usage/writers.md +++ b/docs/usage/writers.md @@ -10,6 +10,15 @@ $writer = IOFactory::createWriter($oPhpWord, 'HTML'); $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: + +```php + $phpWord->setDefaultHtmlGenericFont('serif'); + $phpWord->setDefaultHtmlWhiteSpace('pre-wrap'); +``` + ## ODText The name of the writer is `ODText`. diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 088d4c5427..8c75ddf8a3 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -520,16 +520,6 @@ parameters: count: 1 path: src/PhpWord/Shared/Microsoft/PasswordEncoder.php - - - message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\XMLReader\\:\\:getElements\\(\\) should return DOMNodeList\\ but returns DOMNodeList\\\\.$#" - count: 1 - path: src/PhpWord/Shared/XMLReader.php - - - - message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\XMLReader\\:\\:getElements\\(\\) should return DOMNodeList\\ but returns DOMNodeList\\\\|false\\.$#" - count: 2 - path: src/PhpWord/Shared/XMLReader.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\XMLWriter\\:\\:getData\\(\\) should return string but returns string\\|false\\.$#" count: 1 @@ -1180,46 +1170,11 @@ parameters: count: 1 path: src/PhpWord/Writer/HTML/Element/AbstractElement.php - - - message: "#^Call to an undefined method Laminas\\\\Escaper\\\\Escaper\\|PhpOffice\\\\PhpWord\\\\Escaper\\\\AbstractEscaper\\:\\:escapeHtml\\(\\)\\.$#" - count: 1 - path: src/PhpWord/Writer/HTML/Element/Link.php - - - - message: "#^Call to an undefined method Laminas\\\\Escaper\\\\Escaper\\|PhpOffice\\\\PhpWord\\\\Escaper\\\\AbstractEscaper\\:\\:escapeHtmlAttr\\(\\)\\.$#" - count: 1 - path: src/PhpWord/Writer/HTML/Element/Link.php - - - - message: "#^Call to an undefined method Laminas\\\\Escaper\\\\Escaper\\|PhpOffice\\\\PhpWord\\\\Escaper\\\\AbstractEscaper\\:\\:escapeHtml\\(\\)\\.$#" - count: 1 - path: src/PhpWord/Writer/HTML/Element/ListItem.php - - message: "#^Variable \\$row in PHPDoc tag @var does not match assigned variable \\$rowStyle\\.$#" count: 1 path: src/PhpWord/Writer/HTML/Element/Table.php - - - message: "#^Call to an undefined method Laminas\\\\Escaper\\\\Escaper\\|PhpOffice\\\\PhpWord\\\\Escaper\\\\AbstractEscaper\\:\\:escapeHtml\\(\\)\\.$#" - count: 2 - path: src/PhpWord/Writer/HTML/Element/Text.php - - - - message: "#^Call to an undefined method Laminas\\\\Escaper\\\\Escaper\\|PhpOffice\\\\PhpWord\\\\Escaper\\\\AbstractEscaper\\:\\:escapeHtml\\(\\)\\.$#" - count: 1 - path: src/PhpWord/Writer/HTML/Element/Title.php - - - - message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\HTML\\\\Style\\\\AbstractStyle\\:\\:write\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpWord/Writer/HTML/Style/AbstractStyle.php - - - - message: "#^Else branch is unreachable because previous condition is always true\\.$#" - count: 1 - path: src/PhpWord/Writer/HTML/Style/Paragraph.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Element\\\\Field\\:\\:writeDefault\\(\\) has parameter \\$type with no type specified\\.$#" count: 1 @@ -1275,11 +1230,6 @@ parameters: count: 1 path: src/PhpWord/Writer/ODText/Part/Styles.php - - - message: "#^Variable \\$indent in empty\\(\\) always exists and is not falsy\\.$#" - count: 1 - path: src/PhpWord/Writer/ODText/Style/Paragraph.php - - message: "#^Parameter \\#1 \\$callback of function call_user_func_array expects callable\\(\\)\\: mixed, array\\{PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\\\AbstractRenderer, string\\} given\\.$#" count: 1 @@ -1330,11 +1280,6 @@ parameters: count: 1 path: src/PhpWord/Writer/RTF/Element/AbstractElement.php - - - message: "#^Call to an undefined method Laminas\\\\Escaper\\\\Escaper\\|PhpOffice\\\\PhpWord\\\\Escaper\\\\AbstractEscaper\\:\\:escape\\(\\)\\.$#" - count: 1 - path: src/PhpWord/Writer/RTF/Element/AbstractElement.php - - message: "#^Parameter \\#1 \\$value of method PhpOffice\\\\PhpWord\\\\Writer\\\\RTF\\\\Style\\\\Font\\:\\:setNameIndex\\(\\) expects int, int\\|string given\\.$#" count: 1 @@ -1415,21 +1360,6 @@ parameters: count: 1 path: src/PhpWord/Writer/RTF/Style/Border.php - - - message: "#^Variable \\$spaceAfter on left side of \\?\\? always exists and is not nullable\\.$#" - count: 1 - path: src/PhpWord/Writer/RTF/Style/Paragraph.php - - - - message: "#^Variable \\$spaceBefore on left side of \\?\\? always exists and is not nullable\\.$#" - count: 1 - path: src/PhpWord/Writer/RTF/Style/Paragraph.php - - - - message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\RTF\\\\Style\\\\Tab\\:\\:write\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpWord/Writer/RTF/Style/Tab.php - - message: "#^PHPDoc tag @param has invalid value \\(\\\\PhpOffice\\\\PhpWord\\\\PhpWord\\)\\: Unexpected token \"\\\\n \", expected variable at offset 86$#" count: 1 @@ -1480,16 +1410,6 @@ parameters: count: 1 path: src/PhpWord/Writer/Word2007/Element/SDT.php - - - message: "#^Parameter \\#1 \\$content of method PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Element\\\\AbstractElement\\:\\:writeText\\(\\) expects string, PhpOffice\\\\PhpWord\\\\Element\\\\TextRun\\|string given\\.$#" - count: 1 - path: src/PhpWord/Writer/Word2007/Element/TOC.php - - - - message: "#^Parameter \\#3 \\$indent of method PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Element\\\\TOC\\:\\:writeStyle\\(\\) expects int, float\\|int given\\.$#" - count: 1 - path: src/PhpWord/Writer/Word2007/Element/TOC.php - - message: "#^Property PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Element\\\\TableAlignment\\:\\:\\$attributes has no type specified\\.$#" count: 1 @@ -1540,11 +1460,6 @@ parameters: count: 1 path: src/PhpWord/Writer/Word2007/Style/Font.php - - - message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\WriterInterface\\:\\:save\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpWord/Writer/WriterInterface.php - - message: "#^Call to an undefined method object\\:\\:read\\(\\)\\.$#" count: 1 @@ -1905,21 +1820,6 @@ parameters: count: 2 path: tests/PhpWordTests/TemplateProcessorTest.php - - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\TemplateProcessorTest\\:\\:testTemplateCanBeSavedInTemporaryLocation\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/PhpWordTests/TemplateProcessorTest.php - - - - message: "#^Parameter \\#1 \\$expectedXml of static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertXmlStringEqualsXmlString\\(\\) expects DOMDocument\\|string, string\\|false given\\.$#" - count: 3 - path: tests/PhpWordTests/TemplateProcessorTest.php - - - - message: "#^Parameter \\#2 \\$actualXml of static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertXmlStringEqualsXmlString\\(\\) expects DOMDocument\\|string, string\\|false given\\.$#" - count: 3 - path: tests/PhpWordTests/TemplateProcessorTest.php - - message: "#^Parameter \\#2 \\$haystack of static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertStringContainsString\\(\\) expects string, string\\|false given\\.$#" count: 6 @@ -2000,11 +1900,6 @@ parameters: count: 1 path: tests/PhpWordTests/Writer/PDF/DomPDFTest.php - - - message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:save\\(\\)\\.$#" - count: 1 - path: tests/PhpWordTests/Writer/PDF/DomPDFTest.php - - message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:setFont\\(\\)\\.$#" count: 1 @@ -2030,26 +1925,11 @@ parameters: count: 3 path: tests/PhpWordTests/Writer/PDF/DomPDFTest.php - - - message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:save\\(\\)\\.$#" - count: 1 - path: tests/PhpWordTests/Writer/PDF/MPDFTest.php - - - - message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" - count: 2 - path: tests/PhpWordTests/Writer/PDF/MPDFTest.php - - message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:getFont\\(\\)\\.$#" count: 1 path: tests/PhpWordTests/Writer/PDF/MPDFTest.php - - - message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:save\\(\\)\\.$#" - count: 1 - path: tests/PhpWordTests/Writer/PDF/TCPDFTest.php - - message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" count: 2 @@ -2060,16 +1940,6 @@ parameters: count: 1 path: tests/PhpWordTests/Writer/PDF/TCPDFTest.php - - - message: "#^Call to an undefined method PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:save\\(\\)\\.$#" - count: 2 - path: tests/PhpWordTests/Writer/PDFTest.php - - - - message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" - count: 1 - path: tests/PhpWordTests/Writer/PDFTest.php - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\Writer\\\\RTF\\\\ElementTest\\:\\:removeCr\\(\\) has no return type specified\\.$#" count: 1 diff --git a/phpunit.xml.dist b/phpunit.xml.dist index a81487036d..6f1f5445ab 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,27 +1,24 @@ - - - - ./tests/PhpWordTests - - - - - ./src - - ./src/PhpWordTests/Shared/PCLZip - - - - - - - + + + + + ./src + + + ./src/PhpWord/Shared/PCLZip + + + + + + + + + + + + ./tests/PhpWordTests + + + diff --git a/samples/Sample_36_RTL.php b/samples/Sample_36_RTL.php index 4b3e760465..b3baca90cb 100644 --- a/samples/Sample_36_RTL.php +++ b/samples/Sample_36_RTL.php @@ -2,9 +2,15 @@ include_once 'Sample_Header.php'; +use PhpOffice\PhpWord\Settings; + // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord->setDefaultFontName('DejaVu Sans'); // for good rendition of PDF +$rendererName = Settings::PDF_RENDERER_MPDF; +$rendererLibraryPath = $vendorDirPath . '/mpdf/mpdf'; +Settings::setPdfRenderer($rendererName, $rendererLibraryPath); // New section $section = $phpWord->addSection(); @@ -26,15 +32,15 @@ //Vidually bidirectinal table $table->addRow(); -$cell = $table->addCell(500, $cellVCentered); +$cell = $table->addCell(1500, $cellVCentered); $textrun = $cell->addTextRun($cellHCentered); $textrun->addText('ردیف', $style); -$cell = $table->addCell(11000); +$cell = $table->addCell(2000); $textrun = $cell->addTextRun($cellHEnd); $textrun->addText('سوالات', $style); -$cell = $table->addCell(500, $cellVCentered); +$cell = $table->addCell(1000, $cellVCentered); $textrun = $cell->addTextRun($cellHCentered); $textrun->addText('بارم', $style); diff --git a/samples/Sample_52_RTLDefault.php b/samples/Sample_52_RTLDefault.php new file mode 100644 index 0000000000..080df5571b --- /dev/null +++ b/samples/Sample_52_RTLDefault.php @@ -0,0 +1,34 @@ +setDefaultFontName('DejaVu Sans'); // for good rendition of PDF +$rendererName = Settings::PDF_RENDERER_MPDF; +$rendererLibraryPath = $vendorDirPath . '/mpdf/mpdf'; +Settings::setPdfRenderer($rendererName, $rendererLibraryPath); + +// New section +$section = $phpWord->addSection(); +$arabic = '

الألم الذي ربما تنجم عنه بعض ا.

'; +$english = '

LTR in RTL document.

'; +SharedHtml::addHtml($section, $arabic, false, false); +SharedHtml::addHtml($section, $english, false, false); +SharedHtml::addHtml($section, $english, false, false); +SharedHtml::addHtml($section, $arabic, false, false); +SharedHtml::addHtml($section, $arabic, false, false); + +// Save file +echo write($phpWord, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} +Style::setDefaultRtl(null); diff --git a/src/PhpWord/Element/Cell.php b/src/PhpWord/Element/Cell.php index 7f2a189b83..b0aa0c4ed4 100644 --- a/src/PhpWord/Element/Cell.php +++ b/src/PhpWord/Element/Cell.php @@ -46,7 +46,7 @@ class Cell extends AbstractContainer /** * Create new instance. * - * @param int $width + * @param null|int $width * @param array|\PhpOffice\PhpWord\Style\Cell $style */ public function __construct($width = null, $style = null) diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php index f92f4bd572..1f1a62500a 100644 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -417,10 +417,10 @@ public function getImageStringData($base64 = false) } if ($base64) { - return chunk_split(base64_encode($imageBinary)); + return base64_encode($imageBinary); } - return chunk_split(bin2hex($imageBinary)); + return bin2hex($imageBinary); } /** diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index da57f38d29..489119052b 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -256,6 +256,68 @@ 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. * @@ -325,52 +387,4 @@ 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/Reader/MsDoc.php b/src/PhpWord/Reader/MsDoc.php index fed6c99188..842ba75ba8 100644 --- a/src/PhpWord/Reader/MsDoc.php +++ b/src/PhpWord/Reader/MsDoc.php @@ -57,16 +57,6 @@ class MsDoc extends AbstractReader implements ReaderInterface */ private $dataObjectPool; - /** - * Object Stream. - */ - private $_SummaryInformation; - - /** - * Object Stream. - */ - private $_DocumentSummaryInformation; - /** * @var stdClass[] */ @@ -92,6 +82,12 @@ class MsDoc extends AbstractReader implements ReaderInterface */ private $arraySections = []; + /** @var string */ + private $summaryInformation; + + /** @var string */ + private $documentSummaryInformation; + const VERSION_97 = '97'; const VERSION_2000 = '2000'; const VERSION_2002 = '2002'; @@ -160,9 +156,9 @@ private function loadOLE($filename): void // Get Data stream $this->dataObjectPool = $ole->getStream($ole->wrkObjectPool); // Get Summary Information data - $this->_SummaryInformation = $ole->getStream($ole->summaryInformation); + $this->summaryInformation = $ole->getStream($ole->summaryInformation); // Get Document Summary Information data - $this->_DocumentSummaryInformation = $ole->getStream($ole->docSummaryInfos); + $this->documentSummaryInformation = $ole->getStream($ole->docSummaryInfos); } private function getNumInLcb($lcb, $iSize) @@ -1141,7 +1137,7 @@ private function readFibContent(): void /** * Section and information about them. * - * @see http://msdn.microsoft.com/en-us/library/dd924458%28v=office.12%29.aspx + * @see : http://msdn.microsoft.com/en-us/library/dd924458%28v=office.12%29.aspx */ private function readRecordPlcfSed(): void { @@ -1187,7 +1183,7 @@ private function readRecordPlcfSed(): void /** * Specifies the fonts that are used in the document. * - * @see http://msdn.microsoft.com/en-us/library/dd943880%28v=office.12%29.aspx + * @see : http://msdn.microsoft.com/en-us/library/dd943880%28v=office.12%29.aspx */ private function readRecordSttbfFfn(): void { @@ -1271,7 +1267,7 @@ private function readRecordPlcfBtePapx(): void } $arrayRGB = []; for ($inc = 1; $inc <= $numRun; ++$inc) { - //@see http://msdn.microsoft.com/en-us/library/dd925804(v=office.12).aspx + // @see http://msdn.microsoft.com/en-us/library/dd925804(v=office.12).aspx $arrayRGB[$inc] = self::getInt1d($this->dataWorkDocument, $offset); ++$offset; // reserved @@ -1478,7 +1474,7 @@ private function readRecordPlcfBteChpx(): void $offset = $offsetBase; // ChpxFkp - //@see : http://msdn.microsoft.com/en-us/library/dd910989%28v=office.12%29.aspx + // @see : http://msdn.microsoft.com/en-us/library/dd910989%28v=office.12%29.aspx $numRGFC = self::getInt1d($this->dataWorkDocument, $offset + 511); $arrayRGFC = []; for ($inc = 0; $inc <= $numRGFC; ++$inc) { @@ -1501,7 +1497,7 @@ private function readRecordPlcfBteChpx(): void if ($rgb > 0) { // Chp Structure - //@see : http://msdn.microsoft.com/en-us/library/dd772849%28v=office.12%29.aspx + // @see : http://msdn.microsoft.com/en-us/library/dd772849%28v=office.12%29.aspx $posRGB = $offsetBase + $rgb * 2; $cb = self::getInt1d($this->dataWorkDocument, $posRGB); diff --git a/src/PhpWord/Shared/Handler.php b/src/PhpWord/Shared/Handler.php new file mode 100644 index 0000000000..72232cc9e6 --- /dev/null +++ b/src/PhpWord/Shared/Handler.php @@ -0,0 +1,46 @@ +nodeType) { $attributes = $node->attributes; // get all the attributes(eg: id, class) + $bidi = ($attributes['dir'] ?? '') === 'rtl'; foreach ($attributes as $attribute) { $val = $attribute->value; switch (strtolower($attribute->name)) { case 'align': - $styles['alignment'] = self::mapAlign(trim($val)); + $styles['alignment'] = self::mapAlign(trim($val), $bidi); break; case 'lang': @@ -680,6 +681,7 @@ protected static function parseStyle($attribute, $styles) protected static function parseStyleDeclarations(array $selectors, array $styles) { + $bidi = ($selectors['direction'] ?? '') === 'rtl'; foreach ($selectors as $property => $value) { switch ($property) { case 'text-decoration': @@ -696,7 +698,7 @@ protected static function parseStyleDeclarations(array $selectors, array $styles break; case 'text-align': - $styles['alignment'] = self::mapAlign($value); + $styles['alignment'] = self::mapAlign($value, $bidi); break; case 'display': @@ -705,6 +707,7 @@ protected static function parseStyleDeclarations(array $selectors, array $styles break; case 'direction': $styles['rtl'] = $value === 'rtl'; + $styles['bidi'] = $value === 'rtl'; break; case 'font-size': @@ -1026,20 +1029,21 @@ protected static function mapBorderColor(&$styles, $cssBorderColor): void * Transforms a HTML/CSS alignment into a \PhpOffice\PhpWord\SimpleType\Jc. * * @param string $cssAlignment + * @param bool $bidi * * @return null|string */ - protected static function mapAlign($cssAlignment) + protected static function mapAlign($cssAlignment, $bidi) { switch ($cssAlignment) { case 'right': - return Jc::END; + return $bidi ? Jc::START : Jc::END; case 'center': return Jc::CENTER; case 'justify': return Jc::BOTH; default: - return Jc::START; + return $bidi ? Jc::END : Jc::START; } } diff --git a/src/PhpWord/Shared/Text.php b/src/PhpWord/Shared/Text.php index 4a530b2e10..967fce3f95 100644 --- a/src/PhpWord/Shared/Text.php +++ b/src/PhpWord/Shared/Text.php @@ -138,21 +138,24 @@ public static function isUTF8($value = '') /** * Return UTF8 encoded value. * - * @param string $value + * @param ?string $value * - * @return string + * @return ?string */ public static function toUTF8($value = '') { if (null !== $value && !self::isUTF8($value)) { - if (PHP_VERSION_ID < 80200) { - $value = utf8_encode($value); - } else { - $value = mb_convert_encoding($value, 'UTF-8', mb_list_encodings()); - } + // utf8_encode deprecated in php8.2, but mb_convert_encoding always usable + $value = (function_exists('mb_convert_encoding')) ? mb_convert_encoding($value, 'UTF-8', 'ISO-8859-1') : utf8_encode($value); } - return $value; + return self::ensureStringOrNull($value); + } + + /** @param null|array|string $value */ + private static function ensureStringOrNull($value): ?string + { + return is_array($value) ? '' : $value; } /** diff --git a/src/PhpWord/Shared/XMLReader.php b/src/PhpWord/Shared/XMLReader.php index 99c59931e9..9acde47d1f 100644 --- a/src/PhpWord/Shared/XMLReader.php +++ b/src/PhpWord/Shared/XMLReader.php @@ -104,17 +104,15 @@ public function getDomFromString($content) public function getElements($path, ?DOMElement $contextNode = null) { if ($this->dom === null) { - return new DOMNodeList(); + return new DOMNodeList(); // @phpstan-ignore-line } if ($this->xpath === null) { $this->xpath = new DOMXpath($this->dom); } - if (null === $contextNode) { - return $this->xpath->query($path); - } + $result = @$this->xpath->query($path, $contextNode); - return $this->xpath->query($path, $contextNode); + return empty($result) ? new DOMNodeList() : $result; // @phpstan-ignore-line } /** diff --git a/src/PhpWord/Style.php b/src/PhpWord/Style.php index cd27bffec6..f280c9cc2a 100644 --- a/src/PhpWord/Style.php +++ b/src/PhpWord/Style.php @@ -35,6 +35,9 @@ class Style */ private static $styles = []; + /** @var ?bool */ + private static $defaultRtl; + /** * Add paragraph style. * @@ -144,6 +147,7 @@ public static function countStyles() public static function resetStyles(): void { self::$styles = []; + self::$defaultRtl = null; } /** @@ -214,4 +218,16 @@ private static function setStyleValues($name, $style, $value = null) return self::getStyle($name); } + + /** @param ?bool $defaultRtl */ + public static function setDefaultRtl($defaultRtl): void + { + self::$defaultRtl = $defaultRtl; + } + + /** @return ?bool */ + public static function getDefaultRtl() + { + return self::$defaultRtl; + } } diff --git a/src/PhpWord/Style/Font.php b/src/PhpWord/Style/Font.php index d0cc2503e1..6c81b003c6 100644 --- a/src/PhpWord/Style/Font.php +++ b/src/PhpWord/Style/Font.php @@ -17,6 +17,8 @@ namespace PhpOffice\PhpWord\Style; +use PhpOffice\PhpWord\Style; + /** * Font style. */ @@ -230,7 +232,7 @@ class Font extends AbstractStyle /** * Right to left languages. * - * @var bool + * @var ?bool */ private $rtl; @@ -245,7 +247,7 @@ class Font extends AbstractStyle /** * Languages. * - * @var \PhpOffice\PhpWord\Style\Language + * @var null|\PhpOffice\PhpWord\Style\Language */ private $lang; @@ -288,6 +290,8 @@ public function __construct($type = 'text', $paragraph = null) */ public function getStyleValues() { + $hws = 'htmlWhiteSpace'; + $hgf = 'htmlGenericFont'; $styles = [ 'name' => $this->getStyleName(), 'basic' => [ @@ -319,6 +323,8 @@ public function getStyleValues() 'rtl' => $this->isRTL(), 'shading' => $this->getShading(), 'lang' => $this->getLang(), + $hws => $this->getHtmlWhiteSpace(), + $hgf => $this->getHtmlGenericFont(), ]; return $styles; @@ -827,17 +833,17 @@ public function setParagraph($value = null) /** * Get rtl. * - * @return bool + * @return ?bool */ public function isRTL() { - return $this->rtl; + return $this->rtl ?? Style::getDefaultRtl(); } /** * Set rtl. * - * @param bool $value + * @param ?bool $value * * @return self */ @@ -875,7 +881,7 @@ public function setShading($value = null) /** * Get language. * - * @return \PhpOffice\PhpWord\Style\Language + * @return null|\PhpOffice\PhpWord\Style\Language */ public function getLang() { @@ -946,4 +952,114 @@ 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 + * + * @return self + */ + public function setHtmlWhiteSpace($value) + { + $this->htmlWhiteSpace = self::validateWhiteSpace($value); + + return $this; + } + + /** + * Get html css white-space value. + * + * @return string + */ + public function getHtmlWhiteSpace() + { + 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 ''; + } + } + + /** + * Set generic font for fallback for html. + * + * @param string $value generic font name + * + * @return self + */ + public function setHtmlGenericFont($value) + { + $this->htmlGenericFont = self::validateGenericFont($value); + + return $this; + } + + /** + * Get html fallback generic font. + * + * @return string + */ + public function getHtmlGenericFont() + { + return $this->htmlGenericFont; + } } diff --git a/src/PhpWord/Style/Indentation.php b/src/PhpWord/Style/Indentation.php index 87277b4b81..42c6e11845 100644 --- a/src/PhpWord/Style/Indentation.php +++ b/src/PhpWord/Style/Indentation.php @@ -44,7 +44,7 @@ class Indentation extends AbstractStyle * * @var float|int */ - private $firstLine; + private $firstLine = 0; /** * Indentation removed from first line (twip). @@ -80,7 +80,7 @@ public function getLeft() * * @return self */ - public function setLeft($value = null) + public function setLeft($value) { $this->left = $this->setNumericVal($value, $this->left); @@ -104,7 +104,7 @@ public function getRight() * * @return self */ - public function setRight($value = null) + public function setRight($value) { $this->right = $this->setNumericVal($value, $this->right); @@ -128,7 +128,7 @@ public function getFirstLine() * * @return self */ - public function setFirstLine($value = null) + public function setFirstLine($value) { $this->firstLine = $this->setNumericVal($value, $this->firstLine); diff --git a/src/PhpWord/Style/Paragraph.php b/src/PhpWord/Style/Paragraph.php index e7b97afb1b..cfd1b5b974 100644 --- a/src/PhpWord/Style/Paragraph.php +++ b/src/PhpWord/Style/Paragraph.php @@ -21,6 +21,7 @@ use PhpOffice\PhpWord\Shared\Text; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\SimpleType\TextAlignment; +use PhpOffice\PhpWord\Style; /** * Paragraph style. @@ -99,7 +100,7 @@ class Paragraph extends Border /** * Text line height. * - * @var float|int + * @var null|float|int */ private $lineHeight; @@ -169,9 +170,9 @@ class Paragraph extends Border /** * Right to Left Paragraph Layout. * - * @var bool + * @var ?bool */ - private $bidi = false; + private $bidi; /** * Vertical Character Alignment on Line. @@ -321,9 +322,9 @@ public function setNext($value = null) } /** - * Get shading. + * Get indentation. * - * @return \PhpOffice\PhpWord\Style\Indentation + * @return null|\PhpOffice\PhpWord\Style\Indentation */ public function getIndentation() { @@ -419,7 +420,7 @@ public function setSpace($value = null) /** * Get space before paragraph. * - * @return int + * @return null|float|int */ public function getSpaceBefore() { @@ -429,7 +430,7 @@ public function getSpaceBefore() /** * Set space before paragraph. * - * @param int $value + * @param null|float|int $value * * @return self */ @@ -441,7 +442,7 @@ public function setSpaceBefore($value = null) /** * Get space after paragraph. * - * @return int + * @return null|float|int */ public function getSpaceAfter() { @@ -451,7 +452,7 @@ public function getSpaceAfter() /** * Set space after paragraph. * - * @param int $value + * @param null|float|int $value * * @return self */ @@ -463,7 +464,7 @@ public function setSpaceAfter($value = null) /** * Get spacing between lines. * - * @return float|int + * @return null|float|int */ public function getSpacing() { @@ -473,7 +474,7 @@ public function getSpacing() /** * Set spacing between lines. * - * @param float|int $value + * @param null|float|int $value * * @return self */ @@ -507,7 +508,7 @@ public function setSpacingLineRule($value) /** * Get line height. * - * @return float|int + * @return null|float|int */ public function getLineHeight() { @@ -759,17 +760,17 @@ public function setContextualSpacing($contextualSpacing) /** * Get bidirectional. * - * @return bool + * @return ?bool */ public function isBidi() { - return $this->bidi; + return $this->bidi ?? Style::getDefaultRtl(); } /** * Set bidi. * - * @param bool $bidi + * @param ?bool $bidi * Set to true to write from right to left * * @return self diff --git a/src/PhpWord/Style/Spacing.php b/src/PhpWord/Style/Spacing.php index 7807065dd4..196ad8daa1 100644 --- a/src/PhpWord/Style/Spacing.php +++ b/src/PhpWord/Style/Spacing.php @@ -30,21 +30,21 @@ class Spacing extends AbstractStyle /** * Spacing above paragraph (twip). * - * @var float|int + * @var null|float|int */ private $before; /** * Spacing below paragraph (twip). * - * @var float|int + * @var null|float|int */ private $after; /** * Spacing between lines in paragraph (twip). * - * @var float|int + * @var null|float|int */ private $line; @@ -68,7 +68,7 @@ public function __construct($style = []) /** * Get before. * - * @return float|int + * @return null|float|int */ public function getBefore() { @@ -78,7 +78,7 @@ public function getBefore() /** * Set before. * - * @param float|int $value + * @param null|float|int $value * * @return self */ @@ -92,7 +92,7 @@ public function setBefore($value = null) /** * Get after. * - * @return float|int + * @return null|float|int */ public function getAfter() { @@ -102,7 +102,7 @@ public function getAfter() /** * Set after. * - * @param float|int $value + * @param null|float|int $value * * @return self */ @@ -116,7 +116,7 @@ public function setAfter($value = null) /** * Get line. * - * @return float|int + * @return null|float|int */ public function getLine() { @@ -126,7 +126,7 @@ public function getLine() /** * Set distance. * - * @param float|int $value + * @param null|float|int $value * * @return self */ diff --git a/src/PhpWord/Style/Table.php b/src/PhpWord/Style/Table.php index 1833024d14..d1ad6d8a3e 100644 --- a/src/PhpWord/Style/Table.php +++ b/src/PhpWord/Style/Table.php @@ -21,6 +21,7 @@ use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\SimpleType\JcTable; use PhpOffice\PhpWord\SimpleType\TblWidth; +use PhpOffice\PhpWord\Style; class Table extends Border { @@ -162,9 +163,9 @@ class Table extends Border * * @see http://www.datypic.com/sc/ooxml/e-w_bidiVisual-1.html * - * @var bool + * @var ?bool */ - private $bidiVisual = false; + private $bidiVisual; /** * Create new table style. @@ -768,17 +769,17 @@ public function setColumnWidths(?array $value = null): void /** * Get bidiVisual. * - * @return bool + * @return ?bool */ public function isBidiVisual() { - return $this->bidiVisual; + return $this->bidiVisual ?? Style::getDefaultRtl(); } /** * Set bidiVisual. * - * @param bool $bidi + * @param ?bool $bidi * Set to true to visually present table as Right to Left * * @return self diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index ea90ef1d5e..5198ff1229 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -27,6 +27,7 @@ use PhpOffice\PhpWord\Shared\Text; use PhpOffice\PhpWord\Shared\XMLWriter; use PhpOffice\PhpWord\Shared\ZipArchive; +use Throwable; use XSLTProcessor; class TemplateProcessor @@ -135,6 +136,28 @@ public function __construct($documentTemplate) $this->tempDocumentContentTypes = $this->zipClass->getFromName($this->getDocumentContentTypesName()); } + public function __destruct() + { + if ($this->zipClass !== null) { + try { + $this->zipClass->close(); + } catch (Throwable $e) { + // Nothing to do here. + } + } + if ($this->tempDocumentFilename && file_exists($this->tempDocumentFilename)) { + unlink($this->tempDocumentFilename); + } + } + + public function __wakeup(): void + { + $this->tempDocumentFilename = ''; + $this->zipClass = null; + + throw new Exception('unserialize not permitted for this class'); + } + /** * Expose zip class. * @@ -256,15 +279,7 @@ protected static function ensureMacroCompleted($macro) */ protected static function ensureUtf8Encoded($subject) { - if (!Text::isUTF8($subject) && null !== $subject) { - if (PHP_VERSION_ID < 80200) { - $subject = utf8_encode($subject); - } else { - $subject = mb_convert_encoding($subject, 'UTF-8', mb_list_encodings()); - } - } - - return (null !== $subject) ? $subject : ''; + return (null !== $subject) ? Text::toUTF8($subject) : ''; } /** @@ -441,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 ea0d654e5d..ca9784a83b 100644 --- a/src/PhpWord/Writer/HTML.php +++ b/src/PhpWord/Writer/HTML.php @@ -35,6 +35,13 @@ class HTML extends AbstractWriter implements WriterInterface */ protected $isPdf = false; + /** + * Is the current writer creating TCPDF? + * + * @var bool + */ + protected $isTcpdf = false; + /** * Footnotes and endnotes collection. * @@ -42,6 +49,13 @@ class HTML extends AbstractWriter implements WriterInterface */ protected $notes = []; + /** + * Callback for editing generated html. + * + * @var null|callable + */ + private $editHtmlCallback; + /** * Create new instance. */ @@ -63,10 +77,8 @@ public function __construct(?PhpWord $phpWord = null) /** * Save PhpWord to file. - * - * @param string $filename */ - public function save($filename = null): void + public function save(string $filename): void { $this->writeFile($this->openFile($filename), $this->getContent()); } @@ -84,14 +96,44 @@ public function getContent() $content .= '' . PHP_EOL; $content .= '' . PHP_EOL; - $content .= '' . PHP_EOL; + $langtext = ''; + $phpWord = $this->getPhpWord(); + $lang = $phpWord->getSettings()->getThemeFontLang(); + if (!empty($lang)) { // @phpstan-ignore-line + $lang2 = $lang->getLatin(); + if (!$lang2) { + $lang2 = $lang->getEastAsia(); + } + if (!$lang2) { + $lang2 = $lang->getBidirectional(); + } + if ($lang2) { + $langtext = " lang='" . $lang2 . "'"; + } + } + $content .= "" . PHP_EOL; $content .= $this->getWriterPart('Head')->write(); $content .= $this->getWriterPart('Body')->write(); $content .= '' . PHP_EOL; + $callback = $this->editHtmlCallback; + if ($callback !== null) { + $content = $callback($content); + } return $content; } + /** + * 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 + { + $this->editHtmlCallback = $callback; + } + /** * Get is PDF. * @@ -102,6 +144,16 @@ public function isPdf() return $this->isPdf; } + /** + * Get is TCPDF. + * + * @return bool + */ + public function isTcpdf() + { + return $this->isTcpdf; + } + /** * Get notes. * @@ -122,4 +174,18 @@ public function addNote($noteId, $noteMark): void { $this->notes[$noteId] = $noteMark; } + + /** + * Escape string or not depending on setting. + * + * @param string $txt + */ + public static function escapeOrNot($txt): string + { + if (\PhpOffice\PhpWord\Settings::isOutputEscapingEnabled()) { + return htmlspecialchars($txt, ENT_QUOTES | (defined('ENT_SUBSTITUTE') ? ENT_SUBSTITUTE : 0), 'UTF-8'); + } + + return $txt; + } } diff --git a/src/PhpWord/Writer/HTML/Element/AbstractElement.php b/src/PhpWord/Writer/HTML/Element/AbstractElement.php index f5b0e91719..ae203d70d2 100644 --- a/src/PhpWord/Writer/HTML/Element/AbstractElement.php +++ b/src/PhpWord/Writer/HTML/Element/AbstractElement.php @@ -17,7 +17,6 @@ namespace PhpOffice\PhpWord\Writer\HTML\Element; -use Laminas\Escaper\Escaper; use PhpOffice\PhpWord\Element\AbstractElement as Element; use PhpOffice\PhpWord\Writer\AbstractWriter; @@ -49,11 +48,6 @@ abstract class AbstractElement */ protected $withoutP = false; - /** - * @var \Laminas\Escaper\Escaper|\PhpOffice\PhpWord\Escaper\AbstractEscaper - */ - protected $escaper; - /** * Write element. */ @@ -69,7 +63,6 @@ public function __construct(AbstractWriter $parentWriter, Element $element, $wit $this->parentWriter = $parentWriter; $this->element = $element; $this->withoutP = $withoutP; - $this->escaper = new Escaper(); } /** diff --git a/src/PhpWord/Writer/HTML/Element/Link.php b/src/PhpWord/Writer/HTML/Element/Link.php index 7d302c1f85..5ff7030118 100644 --- a/src/PhpWord/Writer/HTML/Element/Link.php +++ b/src/PhpWord/Writer/HTML/Element/Link.php @@ -17,7 +17,7 @@ namespace PhpOffice\PhpWord\Writer\HTML\Element; -use PhpOffice\PhpWord\Settings; +use PhpOffice\PhpWord\Writer\HTML; /** * Link element HTML writer. @@ -39,11 +39,11 @@ public function write() $prefix = $this->element->isInternal() ? '#' : ''; $content = $this->writeOpening(); - if (Settings::isOutputEscapingEnabled()) { - $content .= "escaper->escapeHtmlAttr($this->element->getSource())}\">{$this->escaper->escapeHtml($this->element->getText())}"; - } else { - $content .= "element->getSource()}\">{$this->element->getText()}"; - } + $content .= "element->getSource()) + . '">' + . HTML::escapeOrNot($this->element->getText()) + . ''; $content .= $this->writeClosing(); return $content; diff --git a/src/PhpWord/Writer/HTML/Element/ListItem.php b/src/PhpWord/Writer/HTML/Element/ListItem.php index d04798684f..4dd61ff321 100644 --- a/src/PhpWord/Writer/HTML/Element/ListItem.php +++ b/src/PhpWord/Writer/HTML/Element/ListItem.php @@ -17,7 +17,7 @@ namespace PhpOffice\PhpWord\Writer\HTML\Element; -use PhpOffice\PhpWord\Settings; +use PhpOffice\PhpWord\Writer\HTML; /** * ListItem element HTML writer. @@ -37,11 +37,7 @@ public function write() return ''; } - if (Settings::isOutputEscapingEnabled()) { - $content = '

' . $this->escaper->escapeHtml($this->element->getTextObject()->getText()) . '

' . PHP_EOL; - } else { - $content = '

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

' . PHP_EOL; - } + $content = '

' . HTML::escapeOrNot($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 762426bf26..8e3971781c 100644 --- a/src/PhpWord/Writer/HTML/Element/PageBreak.php +++ b/src/PhpWord/Writer/HTML/Element/PageBreak.php @@ -35,10 +35,13 @@ public function write() { /** @var \PhpOffice\PhpWord\Writer\HTML $parentWriter Type hint */ $parentWriter = $this->parentWriter; + if ($parentWriter->isTcpdf()) { + return '
'; + } if ($parentWriter->isPdf()) { return ''; } - return ''; + return '
 
' . PHP_EOL; } } diff --git a/src/PhpWord/Writer/HTML/Element/Table.php b/src/PhpWord/Writer/HTML/Element/Table.php index b1a2ee9667..43320ea8fb 100644 --- a/src/PhpWord/Writer/HTML/Element/Table.php +++ b/src/PhpWord/Writer/HTML/Element/Table.php @@ -51,10 +51,10 @@ public function write() $rowCellCount = count($rowCells); for ($j = 0; $j < $rowCellCount; ++$j) { $cellStyle = $rowCells[$j]->getStyle(); + $cellStyleCss = self::getTableStyle($cellStyle); $cellBgColor = $cellStyle->getBgColor(); - $cellBgColor === 'auto' && $cellBgColor = null; // auto cannot be parsed to hexadecimal number $cellFgColor = null; - if ($cellBgColor) { + if ($cellBgColor && $cellBgColor !== 'auto') { $red = hexdec(substr($cellBgColor, 0, 2)); $green = hexdec(substr($cellBgColor, 2, 2)); $blue = hexdec(substr($cellBgColor, 4, 2)); @@ -67,12 +67,8 @@ public function write() if ($cellVMerge === 'restart') { for ($k = $i + 1; $k < $rowCount; ++$k) { $kRowCells = $rows[$k]->getCells(); - if (isset($kRowCells[$j])) { - if ($kRowCells[$j]->getStyle()->getVMerge() === 'continue') { - ++$cellRowSpan; - } else { - break; - } + if (isset($kRowCells[$j]) && $kRowCells[$j]->getStyle()->getVMerge() === 'continue') { + ++$cellRowSpan; } else { break; } @@ -83,22 +79,18 @@ public function write() $cellTag = $tblHeader ? 'th' : 'td'; $cellColSpanAttr = (is_numeric($cellColSpan) && ($cellColSpan > 1) ? " colspan=\"{$cellColSpan}\"" : ''); $cellRowSpanAttr = ($cellRowSpan > 1 ? " rowspan=\"{$cellRowSpan}\"" : ''); - $cellBgColorAttr = (null === $cellBgColor ? '' : " bgcolor=\"#{$cellBgColor}\""); - $cellFgColorAttr = (null === $cellFgColor ? '' : " color=\"#{$cellFgColor}\""); - $content .= "<{$cellTag}{$cellColSpanAttr}{$cellRowSpanAttr}{$cellBgColorAttr}{$cellFgColorAttr}>" . PHP_EOL; + $cellBgColorAttr = (empty($cellBgColor) ? '' : " bgcolor=\"#{$cellBgColor}\""); + $cellFgColorAttr = (empty($cellFgColor) ? '' : " color=\"#{$cellFgColor}\""); + $content .= "<{$cellTag}{$cellStyleCss}{$cellColSpanAttr}{$cellRowSpanAttr}{$cellBgColorAttr}{$cellFgColorAttr}>" . PHP_EOL; $writer = new Container($this->parentWriter, $rowCells[$j]); $content .= $writer->write(); if ($cellRowSpan > 1) { // There shouldn't be any content in the subsequent merged cells, but lets check anyway for ($k = $i + 1; $k < $rowCount; ++$k) { $kRowCells = $rows[$k]->getCells(); - if (isset($kRowCells[$j])) { - if ($kRowCells[$j]->getStyle()->getVMerge() === 'continue') { - $writer = new Container($this->parentWriter, $kRowCells[$j]); - $content .= $writer->write(); - } else { - break; - } + if (isset($kRowCells[$j]) && $kRowCells[$j]->getStyle()->getVMerge() === 'continue') { + $writer = new Container($this->parentWriter, $kRowCells[$j]); + $content .= $writer->write(); } else { break; } @@ -118,26 +110,82 @@ public function write() /** * Translates Table style in CSS equivalent. * - * @param null|\PhpOffice\PhpWord\Style\Table|string $tableStyle + * @param null|\PhpOffice\PhpWord\Style\Cell|\PhpOffice\PhpWord\Style\Table|string $tableStyle * * @return string */ - private function getTableStyle($tableStyle = null) + private static function getTableStyle($tableStyle = null) { if ($tableStyle == null) { return ''; } if (is_string($tableStyle)) { $style = ' class="' . $tableStyle; - } else { - $style = ' style="'; + + return $style . '"'; + } + + $style = self::getTableStyleString($tableStyle); + 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 . '"'; + return $style; } } diff --git a/src/PhpWord/Writer/HTML/Element/Text.php b/src/PhpWord/Writer/HTML/Element/Text.php index a360f0922b..e6c9d00134 100644 --- a/src/PhpWord/Writer/HTML/Element/Text.php +++ b/src/PhpWord/Writer/HTML/Element/Text.php @@ -18,9 +18,10 @@ namespace PhpOffice\PhpWord\Writer\HTML\Element; use PhpOffice\PhpWord\Element\TrackChange; -use PhpOffice\PhpWord\Settings; +use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Style\Font; use PhpOffice\PhpWord\Style\Paragraph; +use PhpOffice\PhpWord\Writer\HTML; use PhpOffice\PhpWord\Writer\HTML\Style\Font as FontStyleWriter; use PhpOffice\PhpWord\Writer\HTML\Style\Paragraph as ParagraphStyleWriter; @@ -74,11 +75,11 @@ public function write() $content .= $this->writeOpening(); $content .= $this->openingText; $content .= $this->openingTags; - if (Settings::isOutputEscapingEnabled()) { - $content .= $this->escaper->escapeHtml($element->getText()); - } else { - $content .= $element->getText(); + $contenx = HTML::escapeOrNot($element->getText()); + if (!$this->withoutP && !trim(/** @scrutinizer ignore-type */ $contenx)) { + $contenx = ' '; } + $content .= $contenx; $content .= $this->closingTags; $content .= $this->closingText; $content .= $this->writeClosing(); @@ -115,10 +116,7 @@ protected function writeOpening() { $content = ''; if (!$this->withoutP) { - $style = ''; - if (method_exists($this->element, 'getParagraphStyle')) { - $style = $this->getParagraphStyle(); - } + $style = $this->getParagraphStyle(); $content .= ""; } @@ -141,12 +139,7 @@ protected function writeClosing() $content .= $this->writeTrackChangeClosing(); if (!$this->withoutP) { - if (Settings::isOutputEscapingEnabled()) { - $content .= $this->escaper->escapeHtml($this->closingText); - } else { - $content .= $this->closingText; - } - + $content .= HTML::escapeOrNot($this->closingText); $content .= '

' . PHP_EOL; } @@ -248,17 +241,39 @@ private function getFontStyle(): void /** @var \PhpOffice\PhpWord\Element\Text $element Type hint */ $element = $this->element; $style = ''; + $langtext = ''; + $lang = null; $fontStyle = $element->getFontStyle(); $fStyleIsObject = ($fontStyle instanceof Font); if ($fStyleIsObject) { $styleWriter = new FontStyleWriter($fontStyle); - $style = $styleWriter->write(); - } elseif (is_string($fontStyle)) { - $style = $fontStyle; + $styl2 = $styleWriter->write(); + if ($styl2) { + $style = " style=\"$styl2\""; + } + $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(); + } } - if ($style) { - $attribute = $fStyleIsObject ? 'style' : 'class'; - $this->openingTags = ""; + if ($lang) { + $langtext = $lang->getLatin(); + if (!$langtext) { + $langtext = $lang->getEastAsia(); + } + if (!$langtext) { + $langtext = $lang->getBidirectional(); + } + if ($langtext) { + $langtext = " lang='$langtext'"; + } + } + if ($style || $langtext) { + $this->openingTags = ""; $this->closingTags = ''; } } diff --git a/src/PhpWord/Writer/HTML/Element/Title.php b/src/PhpWord/Writer/HTML/Element/Title.php index 3749505013..c46249f373 100644 --- a/src/PhpWord/Writer/HTML/Element/Title.php +++ b/src/PhpWord/Writer/HTML/Element/Title.php @@ -17,7 +17,7 @@ namespace PhpOffice\PhpWord\Writer\HTML\Element; -use PhpOffice\PhpWord\Settings; +use PhpOffice\PhpWord\Writer\HTML; /** * TextRun element HTML writer. @@ -41,10 +41,8 @@ public function write() $text = $this->element->getText(); if (is_string($text)) { - if (Settings::isOutputEscapingEnabled()) { - $text = $this->escaper->escapeHtml($text); - } - } elseif ($text instanceof \PhpOffice\PhpWord\Element\AbstractContainer) { + $text = HTML::escapeOrNot($text); + } else { $writer = new Container($this->parentWriter, $text); $text = $writer->write(); } diff --git a/src/PhpWord/Writer/HTML/Part/AbstractPart.php b/src/PhpWord/Writer/HTML/Part/AbstractPart.php index 8612e28451..0fd9a40940 100644 --- a/src/PhpWord/Writer/HTML/Part/AbstractPart.php +++ b/src/PhpWord/Writer/HTML/Part/AbstractPart.php @@ -17,9 +17,8 @@ namespace PhpOffice\PhpWord\Writer\HTML\Part; -use Laminas\Escaper\Escaper; use PhpOffice\PhpWord\Exception\Exception; -use PhpOffice\PhpWord\Writer\AbstractWriter; +use PhpOffice\PhpWord\Writer\HTML; /** * @since 0.11.0 @@ -27,35 +26,22 @@ abstract class AbstractPart { /** - * @var \PhpOffice\PhpWord\Writer\AbstractWriter + * @var ?HTML */ private $parentWriter; - /** - * @var \Laminas\Escaper\Escaper - */ - protected $escaper; - - public function __construct() - { - $this->escaper = new Escaper(); - } - /** * @return string */ abstract public function write(); - /** - * @param \PhpOffice\PhpWord\Writer\AbstractWriter $writer - */ - public function setParentWriter(?AbstractWriter $writer = null): void + public function setParentWriter(?HTML $writer = null): void { $this->parentWriter = $writer; } /** - * @return \PhpOffice\PhpWord\Writer\AbstractWriter + * @return HTML */ public function getParentWriter() { diff --git a/src/PhpWord/Writer/HTML/Part/Body.php b/src/PhpWord/Writer/HTML/Part/Body.php index 19aae8aa1f..fe25df5f90 100644 --- a/src/PhpWord/Writer/HTML/Part/Body.php +++ b/src/PhpWord/Writer/HTML/Part/Body.php @@ -40,9 +40,18 @@ public function write() $content .= '' . PHP_EOL; $sections = $phpWord->getSections(); + $secno = 0; + $tcpdf = $this->getParentWriter()->isTcpdf(); foreach ($sections as $section) { + ++$secno; + if ($tcpdf && $secno > 1) { + $content .= "
" . PHP_EOL; + } else { + $content .= "
" . PHP_EOL; + } $writer = new Container($this->getParentWriter(), $section); $content .= $writer->write(); + $content .= '
' . PHP_EOL; } $content .= $this->writeNotes(); diff --git a/src/PhpWord/Writer/HTML/Part/Head.php b/src/PhpWord/Writer/HTML/Part/Head.php index 6117f736e3..b8daf4dab2 100644 --- a/src/PhpWord/Writer/HTML/Part/Head.php +++ b/src/PhpWord/Writer/HTML/Part/Head.php @@ -21,6 +21,9 @@ 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; @@ -63,8 +66,10 @@ public function write() $method = 'get' . $key; if ($docProps->$method() != '') { $content .= '' . PHP_EOL; + . ' content="' + . HTML::escapeOrNot($docProps->$method()) + . '"' + . ' />' . PHP_EOL; } } $content .= $this->writeStyles(); @@ -83,11 +88,19 @@ private function writeStyles() $css = '' . PHP_EOL; diff --git a/src/PhpWord/Writer/HTML/Style/AbstractStyle.php b/src/PhpWord/Writer/HTML/Style/AbstractStyle.php index 5a5fcacd79..a650786769 100644 --- a/src/PhpWord/Writer/HTML/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/HTML/Style/AbstractStyle.php @@ -17,7 +17,8 @@ namespace PhpOffice\PhpWord\Writer\HTML\Style; -use PhpOffice\PhpWord\Style\AbstractStyle as Style; +use PhpOffice\PhpWord\Style\AbstractStyle as StyleAbstract; +use PhpOffice\PhpWord\Writer\HTML; /** * Style writer. @@ -29,26 +30,28 @@ abstract class AbstractStyle /** * Parent writer. * - * @var \PhpOffice\PhpWord\Writer\AbstractWriter + * @var HTML */ private $parentWriter; /** * Style. * - * @var null|array|\PhpOffice\PhpWord\Style\AbstractStyle + * @var null|array|StyleAbstract */ private $style; /** * Write style. + * + * @return mixed */ abstract public function write(); /** * Create new instance. * - * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $style + * @param array|StyleAbstract $style */ public function __construct($style = null) { @@ -58,7 +61,7 @@ public function __construct($style = null) /** * Set parent writer. * - * @param \PhpOffice\PhpWord\Writer\AbstractWriter $writer + * @param HTML $writer */ public function setParentWriter($writer): void { @@ -68,7 +71,7 @@ public function setParentWriter($writer): void /** * Get parent writer. * - * @return \PhpOffice\PhpWord\Writer\AbstractWriter + * @return HTML */ public function getParentWriter() { @@ -78,11 +81,11 @@ public function getParentWriter() /** * Get style. * - * @return null|array|\PhpOffice\PhpWord\Style\AbstractStyle|string + * @return null|array|string|StyleAbstract */ public function getStyle() { - if (!$this->style instanceof Style && !is_array($this->style)) { + if (!$this->style instanceof StyleAbstract && !is_array($this->style)) { return ''; } diff --git a/src/PhpWord/Writer/HTML/Style/Font.php b/src/PhpWord/Writer/HTML/Style/Font.php index 1fd88f5e8e..5aead50c07 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 = $style->getName(); + $font = self::getFontFamily($style->getName(), $style->getHtmlGenericFont()); $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($font !== null, "'{$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,10 +61,40 @@ 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(); + if ($whitespace) { + $css['white-space'] = $whitespace; + } $spacing = $style->getSpacing(); $css['letter-spacing'] = $this->getValueIf(null !== $spacing, ($spacing / 20) . 'pt'); + if ($style->isRTL()) { + $css['direction'] = 'rtl'; + } elseif ($style->isRTL() === false) { + $css['direction'] = 'ltr'; + } return $this->assembleCss($css); } + + /** + * Set font and alternates for css font-family. + * + * @param string $font + * @param string $genericFont + * + * @return string + */ + public static function getFontFamily($font, $genericFont) + { + 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/Paragraph.php b/src/PhpWord/Writer/HTML/Style/Paragraph.php index 865114ff58..73286bda8b 100644 --- a/src/PhpWord/Writer/HTML/Style/Paragraph.php +++ b/src/PhpWord/Writer/HTML/Style/Paragraph.php @@ -49,23 +49,31 @@ public function write() break; case Jc::END: + $textAlign = ($style->isBidi()) ? 'left' : 'right'; + + break; case Jc::MEDIUM_KASHIDA: case Jc::HIGH_KASHIDA: case Jc::LOW_KASHIDA: - case Jc::RIGHT: + case /** @scrutinizer ignore-deprecated */ Jc::RIGHT: $textAlign = 'right'; break; case Jc::BOTH: case Jc::DISTRIBUTE: case Jc::THAI_DISTRIBUTE: - case Jc::JUSTIFY: + case /** @scrutinizer ignore-deprecated */ Jc::JUSTIFY: $textAlign = 'justify'; break; - default: //all others, align left + case /** @scrutinizer ignore-deprecated */ Jc::LEFT: $textAlign = 'left'; + break; + + default: //all others, including Jc::START + $textAlign = ($style->isBidi()) ? 'right' : 'left'; + break; } @@ -79,9 +87,27 @@ public function write() $after = $spacing->getAfter(); $css['margin-top'] = $this->getValueIf(null !== $before, ($before / 20) . 'pt'); $css['margin-bottom'] = $this->getValueIf(null !== $after, ($after / 20) . 'pt'); - } else { - $css['margin-top'] = '0'; - $css['margin-bottom'] = '0'; + } + + $lht = $style->getLineHeight(); + if (!empty($lht)) { + $css['line-height'] = $lht; + } + $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; + $css['margin-right'] = ((string) $inches) . 'in'; + } + if ($style->hasPageBreakBefore()) { + $css['page-break-before'] = 'always'; + } + if ($style->isBidi()) { + $css['direction'] = 'rtl'; } return $this->assembleCss($css); diff --git a/src/PhpWord/Writer/ODText/Element/Table.php b/src/PhpWord/Writer/ODText/Element/Table.php index 783bb21232..e12ae24b58 100644 --- a/src/PhpWord/Writer/ODText/Element/Table.php +++ b/src/PhpWord/Writer/ODText/Element/Table.php @@ -44,7 +44,7 @@ public function write(): void if ($rowCount > 0) { $xmlWriter->startElement('table:table'); $xmlWriter->writeAttribute('table:name', $element->getElementId()); - $xmlWriter->writeAttribute('table:style', $element->getElementId()); + $xmlWriter->writeAttribute('table:style-name', $element->getElementId()); // Write columns $this->writeColumns($xmlWriter, $element); diff --git a/src/PhpWord/Writer/ODText/Element/Title.php b/src/PhpWord/Writer/ODText/Element/Title.php index 45fe65c7f5..ebe7dc4d5f 100644 --- a/src/PhpWord/Writer/ODText/Element/Title.php +++ b/src/PhpWord/Writer/ODText/Element/Title.php @@ -55,7 +55,8 @@ public function write(): void $text = $element->getText(); if (is_string($text)) { $this->writeText($text); - } elseif ($text instanceof \PhpOffice\PhpWord\Element\AbstractContainer) { + } + if ($text instanceof \PhpOffice\PhpWord\Element\AbstractContainer) { $containerWriter = new Container($xmlWriter, $text); $containerWriter->write(); } diff --git a/src/PhpWord/Writer/ODText/Part/Content.php b/src/PhpWord/Writer/ODText/Part/Content.php index 0c0607a06f..00871d9c52 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -201,7 +201,7 @@ private function writeTextStyles(XMLWriter $xmlWriter): void } foreach ($styles as $style) { - $sty = $style->getStyleName(); + $sty = (string) $style->getStyleName(); if (substr($sty, 0, 8) === 'Heading_') { $style = new Paragraph(); $style->setStyleName('HD' . substr($sty, 8)); diff --git a/src/PhpWord/Writer/ODText/Style/Paragraph.php b/src/PhpWord/Writer/ODText/Style/Paragraph.php index 330043e116..666294efee 100644 --- a/src/PhpWord/Writer/ODText/Style/Paragraph.php +++ b/src/PhpWord/Writer/ODText/Style/Paragraph.php @@ -18,6 +18,8 @@ namespace PhpOffice\PhpWord\Writer\ODText\Style; use PhpOffice\PhpWord\Shared\Converter; +use PhpOffice\PhpWord\SimpleType\Jc; +use PhpOffice\PhpWord\Style; /** * Font style writer. @@ -26,6 +28,16 @@ */ class Paragraph extends AbstractStyle { + private const BIDI_MAP = [ + Jc::END => Jc::LEFT, + Jc::START => Jc::RIGHT, + ]; + + private const NON_BIDI_MAP = [ + Jc::START => Jc::LEFT, + Jc::END => Jc::RIGHT, + ]; + /** * Write style. */ @@ -42,7 +54,7 @@ public function write(): void $xmlWriter->startElement('style:style'); - $styleName = $style->getStyleName(); + $styleName = (string) $style->getStyleName(); $styleAuto = false; $mpm = ''; $psm = ''; @@ -111,8 +123,18 @@ public function write(): void $xmlWriter->writeAttributeIf($marginTop !== null, 'fo:margin-top', ($marginTop / $twipToPoint) . 'pt'); $xmlWriter->writeAttributeIf($marginBottom !== null, 'fo:margin-bottom', ($marginBottom / $twipToPoint) . 'pt'); } - $temp = $style->getAlignment(); - $xmlWriter->writeAttributeIf($temp !== '', 'fo:text-align', $temp); + $alignment = $style->getAlignment(); + $bidi = $style->isBidi(); + $defaultRtl = Style::getDefaultRtl(); + if ($alignment === '' && $bidi !== null) { + $alignment = Jc::START; + } + if ($bidi) { + $alignment = self::BIDI_MAP[$alignment] ?? $alignment; + } elseif ($defaultRtl !== null) { + $alignment = self::NON_BIDI_MAP[$alignment] ?? $alignment; + } + $xmlWriter->writeAttributeIf($alignment !== '', 'fo:text-align', $alignment); $temp = $style->getLineHeight(); $xmlWriter->writeAttributeIf($temp !== null, 'fo:line-height', ((string) ($temp * 100) . '%')); $xmlWriter->writeAttributeIf($style->hasPageBreakBefore() === true, 'fo:break-before', 'page'); diff --git a/src/PhpWord/Writer/PDF.php b/src/PhpWord/Writer/PDF.php index 9a8cd6ac25..b24e66efb8 100644 --- a/src/PhpWord/Writer/PDF.php +++ b/src/PhpWord/Writer/PDF.php @@ -73,4 +73,9 @@ public function __call($name, $arguments) return call_user_func_array([$this->renderer, $name], $arguments); } + + public function save(string $filename): void + { + $this->renderer->save($filename); + } } diff --git a/src/PhpWord/Writer/PDF/AbstractRenderer.php b/src/PhpWord/Writer/PDF/AbstractRenderer.php index 6ab6535f4c..c143a6cb5c 100644 --- a/src/PhpWord/Writer/PDF/AbstractRenderer.php +++ b/src/PhpWord/Writer/PDF/AbstractRenderer.php @@ -81,7 +81,7 @@ abstract class AbstractRenderer extends HTML public function __construct(PhpWord $phpWord) { parent::__construct($phpWord); - + $this->isPdf = true; if ($this->includeFile != null) { $includeFile = Settings::getPdfRendererPath() . '/' . $this->includeFile; if (file_exists($includeFile)) { @@ -194,7 +194,6 @@ protected function prepareForSave($filename = null) throw new Exception("Could not open file $filename for writing."); } // @codeCoverageIgnoreEnd - $this->isPdf = true; return $fileHandle; } diff --git a/src/PhpWord/Writer/PDF/DomPDF.php b/src/PhpWord/Writer/PDF/DomPDF.php index ea167b4d0a..8e5b4054d5 100644 --- a/src/PhpWord/Writer/PDF/DomPDF.php +++ b/src/PhpWord/Writer/PDF/DomPDF.php @@ -53,10 +53,8 @@ protected function createExternalWriterInstance() /** * Save PhpWord to file. - * - * @param string $filename Name of the file to save as */ - public function save($filename = null): void + public function save(string $filename): void { $fileHandle = parent::prepareForSave($filename); diff --git a/src/PhpWord/Writer/PDF/MPDF.php b/src/PhpWord/Writer/PDF/MPDF.php index 481d4629b3..311f743d6d 100644 --- a/src/PhpWord/Writer/PDF/MPDF.php +++ b/src/PhpWord/Writer/PDF/MPDF.php @@ -29,6 +29,9 @@ */ class MPDF extends AbstractRenderer implements WriterInterface { + public const SIMULATED_BODY_START = ''; + private const BODY_TAG = ''; + /** * Overridden to set the correct includefile, only needed for MPDF 5. * @@ -46,7 +49,7 @@ public function __construct(PhpWord $phpWord) /** * Gets the implementation of external PDF library that should be used. * - * @return Mpdf implementation + * @return \Mpdf\Mpdf implementation */ protected function createExternalWriterInstance() { @@ -62,10 +65,8 @@ protected function createExternalWriterInstance() /** * Save PhpWord to file. - * - * @param string $filename Name of the file to save as */ - public function save($filename = null): void + public function save(string $filename): void { $fileHandle = parent::prepareForSave($filename); @@ -87,7 +88,24 @@ public function save($filename = null): void $pdf->setKeywords($docProps->getKeywords()); $pdf->setCreator($docProps->getCreator()); - $pdf->writeHTML($this->getContent()); + $html = $this->getContent(); + $bodyLocation = strpos($html, self::SIMULATED_BODY_START); + if ($bodyLocation === false) { + $bodyLocation = strpos($html, self::BODY_TAG); + if ($bodyLocation !== false) { + $bodyLocation += strlen(self::BODY_TAG); + } + } + // Make sure first data presented to Mpdf includes body tag + // (and any htmlpageheader/htmlpagefooter tags) + // so that Mpdf doesn't parse it as content. Issue 2432. + if ($bodyLocation !== false) { + $pdf->WriteHTML(substr($html, 0, $bodyLocation)); + $html = substr($html, $bodyLocation); + } + foreach (explode("\n", $html) as $line) { + $pdf->WriteHTML("$line\n"); + } // Write to file fwrite($fileHandle, $pdf->output($filename, 'S')); diff --git a/src/PhpWord/Writer/PDF/TCPDF.php b/src/PhpWord/Writer/PDF/TCPDF.php index 0847a0c3e8..5ef92f451b 100644 --- a/src/PhpWord/Writer/PDF/TCPDF.php +++ b/src/PhpWord/Writer/PDF/TCPDF.php @@ -17,6 +17,9 @@ namespace PhpOffice\PhpWord\Writer\PDF; +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Settings; +use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Writer\WriterInterface; /** @@ -35,6 +38,17 @@ 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. * @@ -55,17 +69,41 @@ protected function createExternalWriterInstance($orientation, $unit, $paperSize) return $instance; } + /** + * Overwriteable function to allow user to extend TCPDF. + * There should always be an AddPage call, preceded or followed + * by code to customize TCPDF configuration. + * The customization below sets vertical spacing + * between paragaraphs when the user has + * explicitly set those values to numeric in default style. + */ + protected function prepareToWrite(\TCPDF $pdf): void + { + $pdf->AddPage(); + $customStyles = Style::getStyles(); + $normal = $customStyles['Normal'] ?? null; + if ($normal instanceof Style\Paragraph) { + $before = $normal->getSpaceBefore(); + $after = $normal->getSpaceAfter(); + $height = $normal->getLineHeight() ?? ''; + if (is_numeric($before) && is_numeric($after)) { + $tagvs = [ + 'p' => [['n' => $before, 'h' => $height], ['n' => $after, 'h' => $height]], + ]; + $pdf->setHtmlVSpace($tagvs); + } + } + } + /** * Save PhpWord to file. - * - * @param string $filename Name of the file to save as */ - public function save($filename = null): void + public function save(string $filename): void { $fileHandle = parent::prepareForSave($filename); // PDF settings - $paperSize = 'A4'; + $paperSize = strtoupper(Settings::getDefaultPaper()); $orientation = 'P'; // Create PDF @@ -73,8 +111,8 @@ public function save($filename = null): void $pdf->setFontSubsetting(false); $pdf->setPrintHeader(false); $pdf->setPrintFooter(false); - $pdf->AddPage(); $pdf->SetFont($this->getFont()); + $this->prepareToWrite($pdf); $pdf->writeHTML($this->getContent()); // Write document properties diff --git a/src/PhpWord/Writer/RTF/Element/AbstractElement.php b/src/PhpWord/Writer/RTF/Element/AbstractElement.php index a12469ad4c..dedbc8bfa1 100644 --- a/src/PhpWord/Writer/RTF/Element/AbstractElement.php +++ b/src/PhpWord/Writer/RTF/Element/AbstractElement.php @@ -25,7 +25,6 @@ use PhpOffice\PhpWord\Style\Font as FontStyle; use PhpOffice\PhpWord\Style\Paragraph as ParagraphStyle; use PhpOffice\PhpWord\Writer\AbstractWriter; -use PhpOffice\PhpWord\Writer\HTML\Element\AbstractElement as HTMLAbstractElement; use PhpOffice\PhpWord\Writer\RTF\Style\Font as FontStyleWriter; use PhpOffice\PhpWord\Writer\RTF\Style\Paragraph as ParagraphStyleWriter; @@ -34,8 +33,36 @@ * * @since 0.11.0 */ -abstract class AbstractElement extends HTMLAbstractElement +abstract class AbstractElement { + /** + * Parent writer. + * + * @var \PhpOffice\PhpWord\Writer\AbstractWriter + */ + protected $parentWriter; + + /** + * Element. + * + * @var \PhpOffice\PhpWord\Element\AbstractElement + */ + protected $element; + + /** + * Without paragraph. + * + * @var bool + */ + protected $withoutP = false; + + /** + * Write element. + * + * @return string + */ + abstract public function write(); + /** * Font style. * @@ -50,10 +77,16 @@ abstract class AbstractElement extends HTMLAbstractElement */ protected $paragraphStyle; - public function __construct(AbstractWriter $parentWriter, Element $element, $withoutP = false) - { - parent::__construct($parentWriter, $element, $withoutP); + /** + * @var \PhpOffice\PhpWord\Escaper\EscaperInterface + */ + protected $escaper; + public function __construct(AbstractWriter $parentWriter, Element $element, bool $withoutP = false) + { + $this->parentWriter = $parentWriter; + $this->element = $element; + $this->withoutP = $withoutP; $this->escaper = new Rtf(); } diff --git a/src/PhpWord/Writer/RTF/Element/Container.php b/src/PhpWord/Writer/RTF/Element/Container.php index 7f43cb6aaa..5e198aec86 100644 --- a/src/PhpWord/Writer/RTF/Element/Container.php +++ b/src/PhpWord/Writer/RTF/Element/Container.php @@ -17,14 +17,14 @@ namespace PhpOffice\PhpWord\Writer\RTF\Element; -use PhpOffice\PhpWord\Writer\HTML\Element\Container as HTMLContainer; +use PhpOffice\PhpWord\Element\AbstractContainer as ContainerElement; /** * Container element RTF writer. * * @since 0.11.0 */ -class Container extends HTMLContainer +class Container extends AbstractElement { /** * Namespace; Can't use __NAMESPACE__ in inherited class (RTF). @@ -32,4 +32,33 @@ class Container extends HTMLContainer * @var string */ protected $namespace = 'PhpOffice\\PhpWord\\Writer\\RTF\\Element'; + + /** + * Write container. + * + * @return string + */ + public function write() + { + $container = $this->element; + if (!$container instanceof ContainerElement) { + return ''; + } + $containerClass = substr(get_class($container), strrpos(get_class($container), '\\') + 1); + $withoutP = in_array($containerClass, ['TextRun', 'Footnote', 'Endnote']) ? true : false; + $content = ''; + + $elements = $container->getElements(); + foreach ($elements as $element) { + $elementClass = get_class($element); + $writerClass = str_replace('PhpOffice\\PhpWord\\Element', $this->namespace, $elementClass); + if (class_exists($writerClass)) { + /** @var AbstractElement $writer Type hint */ + $writer = new $writerClass($this->parentWriter, $element, $withoutP); + $content .= $writer->write(); + } + } + + return $content; + } } diff --git a/src/PhpWord/Writer/RTF/Element/Table.php b/src/PhpWord/Writer/RTF/Element/Table.php index 5d0755c931..45211a9202 100644 --- a/src/PhpWord/Writer/RTF/Element/Table.php +++ b/src/PhpWord/Writer/RTF/Element/Table.php @@ -20,6 +20,7 @@ use PhpOffice\PhpWord\Element\Cell as CellElement; use PhpOffice\PhpWord\Element\Row as RowElement; use PhpOffice\PhpWord\Element\Table as TableElement; +use PhpOffice\PhpWord\Style; /** * Table element RTF writer. @@ -45,6 +46,9 @@ public function write() } $content = ''; + $style = $this->element->getStyle(); + $bidiStyle = (is_object($style) && method_exists($style, 'isBidiVisual')) ? $style->isBidiVisual() : Style::getDefaultRtl(); + $bidi = $bidiStyle ? '\rtlrow' : ''; $rows = $element->getRows(); $rowCount = count($rows); @@ -52,7 +56,7 @@ public function write() $content .= '\pard' . PHP_EOL; for ($i = 0; $i < $rowCount; ++$i) { - $content .= '\trowd '; + $content .= "\\trowd$bidi "; $content .= $this->writeRowDef($rows[$i]); $content .= PHP_EOL; $content .= $this->writeRow($rows[$i]); diff --git a/src/PhpWord/Writer/RTF/Element/Title.php b/src/PhpWord/Writer/RTF/Element/Title.php index 653ba93df7..a387f273ca 100644 --- a/src/PhpWord/Writer/RTF/Element/Title.php +++ b/src/PhpWord/Writer/RTF/Element/Title.php @@ -38,7 +38,7 @@ protected function getStyles(): void $sect = $element->getParent(); if ($sect instanceof \PhpOffice\PhpWord\Element\Section) { $elems = $sect->getElements(); - if ($elems[0] === $element) { + if (self::isEqual($elems[0], $element)) { $pstyle = clone $pstyle; $pstyle->setPageBreakBefore(false); } @@ -48,6 +48,15 @@ protected function getStyles(): void } } + /** + * @param mixed $comparand1 + * @param mixed $comparand2 + */ + private static function isEqual($comparand1, $comparand2): bool + { + return $comparand1 === $comparand2; + } + /** * Write element. * @@ -71,7 +80,7 @@ public function write() $style = $element->getStyle(); if (is_string($style)) { $style = str_replace('Heading', '', $style); - if (is_numeric($style)) { + if ("$style" !== '') { $style = (int) $style - 1; if ($style >= 0 && $style <= 8) { $content .= '{\\outlinelevel' . $style; diff --git a/src/PhpWord/Writer/RTF/Part/AbstractPart.php b/src/PhpWord/Writer/RTF/Part/AbstractPart.php index d1bca0a4e2..be772b93a0 100644 --- a/src/PhpWord/Writer/RTF/Part/AbstractPart.php +++ b/src/PhpWord/Writer/RTF/Part/AbstractPart.php @@ -27,7 +27,7 @@ abstract class AbstractPart { /** - * @var \PhpOffice\PhpWord\Writer\AbstractWriter + * @var \PhpOffice\PhpWord\Writer\RTF */ private $parentWriter; @@ -47,7 +47,7 @@ public function __construct() abstract public function write(); /** - * @param \PhpOffice\PhpWord\Writer\AbstractWriter $writer + * @param \PhpOffice\PhpWord\Writer\RTF $writer */ public function setParentWriter(?AbstractWriter $writer = null): void { @@ -55,7 +55,7 @@ public function setParentWriter(?AbstractWriter $writer = null): void } /** - * @return \PhpOffice\PhpWord\Writer\AbstractWriter + * @return \PhpOffice\PhpWord\Writer\RTF */ public function getParentWriter() { diff --git a/src/PhpWord/Writer/RTF/Part/Document.php b/src/PhpWord/Writer/RTF/Part/Document.php index b452b9e937..1d55d43fa1 100644 --- a/src/PhpWord/Writer/RTF/Part/Document.php +++ b/src/PhpWord/Writer/RTF/Part/Document.php @@ -148,7 +148,13 @@ private function writeSections() $sections = $this->getParentWriter()->getPhpWord()->getSections(); $evenOdd = $this->getParentWriter()->getPhpWord()->getSettings()->hasEvenAndOddHeaders(); + $sectOwed = false; foreach ($sections as $section) { + if ($sectOwed) { + $content .= '\sect' . PHP_EOL; + } else { + $sectOwed = true; + } $styleWriter = new SectionStyleWriter($section->getStyle()); $styleWriter->setParentWriter($this->getParentWriter()); $content .= $styleWriter->write(); @@ -198,7 +204,7 @@ private function writeSections() $elementWriter = new Container($this->getParentWriter(), $section); $content .= $elementWriter->write(); - $content .= '\sect' . PHP_EOL; + //$content .= '\sect' . PHP_EOL; } return $content; diff --git a/src/PhpWord/Writer/RTF/Style/AbstractStyle.php b/src/PhpWord/Writer/RTF/Style/AbstractStyle.php index e7117d3261..355e384440 100644 --- a/src/PhpWord/Writer/RTF/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/RTF/Style/AbstractStyle.php @@ -17,13 +17,91 @@ namespace PhpOffice\PhpWord\Writer\RTF\Style; -use PhpOffice\PhpWord\Writer\HTML\Style\AbstractStyle as HTMLAbstractStyle; +use PhpOffice\PhpWord\Style\AbstractStyle as StyleAbstract; +use PhpOffice\PhpWord\Writer\RTF; /** * Abstract RTF style writer. * * @since 0.11.0 */ -abstract class AbstractStyle extends HTMLAbstractStyle +abstract class AbstractStyle { + /** + * Parent writer. + * + * @var RTF + */ + private $parentWriter; + + /** + * Style. + * + * @var null|array|StyleAbstract + */ + private $style; + + /** + * Write style. + * + * @return mixed + */ + abstract public function write(); + + /** + * Create new instance. + * + * @param array|StyleAbstract $style + */ + public function __construct($style = null) + { + $this->style = $style; + } + + /** + * Set parent writer. + * + * @param RTF $writer + */ + public function setParentWriter($writer): void + { + $this->parentWriter = $writer; + } + + /** + * Get parent writer. + * + * @return RTF + */ + public function getParentWriter() + { + return $this->parentWriter; + } + + /** + * Get style. + * + * @return null|array|string|StyleAbstract + */ + public function getStyle() + { + if (!$this->style instanceof StyleAbstract && !is_array($this->style)) { + return ''; + } + + return $this->style; + } + + /** + * Get value if ... + * + * @param null|bool $condition + * @param string $value + * + * @return string + */ + protected function getValueIf($condition, $value) + { + return $condition == true ? $value : ''; + } } diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index c61f3ab23d..333975da03 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -35,6 +35,10 @@ 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; + /** * Write style. * @@ -52,6 +56,18 @@ public function write() Jc::END => '\qr', Jc::CENTER => '\qc', Jc::BOTH => '\qj', + self::LEFT => '\ql', + self::RIGHT => '\qr', + self::JUSTIFY => '\qj', + ]; + $bidiAlignments = [ + Jc::START => '\qr', + Jc::END => '\ql', + Jc::CENTER => '\qc', + Jc::BOTH => '\qj', + self::LEFT => '\ql', + self::RIGHT => '\qr', + self::JUSTIFY => '\qj', ]; $spaceAfter = $style->getSpaceAfter(); @@ -61,8 +77,13 @@ public function write() if ($this->nestedLevel == 0) { $content .= '\pard\nowidctlpar '; } - if (isset($alignments[$style->getAlignment()])) { - $content .= $alignments[$style->getAlignment()]; + $alignment = $style->getAlignment(); + $bidi = $style->isBidi(); + if ($alignment === '' && $bidi !== null) { + $alignment = Jc::START; + } + if (isset($alignments[$alignment])) { + $content .= $bidi ? $bidiAlignments[$alignment] : $alignments[$alignment]; } $content .= $this->writeIndentation($style->getIndentation()); $content .= $this->getValueIf($spaceBefore !== null, '\sb' . round($spaceBefore ?? 0)); diff --git a/src/PhpWord/Writer/Word2007/Element/TOC.php b/src/PhpWord/Writer/Word2007/Element/TOC.php index 7c5d089775..f7d00c14c8 100644 --- a/src/PhpWord/Writer/Word2007/Element/TOC.php +++ b/src/PhpWord/Writer/Word2007/Element/TOC.php @@ -93,7 +93,8 @@ private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, Title $ti $styleWriter->write(); } $xmlWriter->startElement('w:t'); - $this->writeText($title->getText()); + $titleText = $title->getText(); + $this->writeText(is_string($titleText) ? $titleText : ''); $xmlWriter->endElement(); // w:t $xmlWriter->endElement(); // w:r @@ -141,8 +142,10 @@ private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, Title $ti /** * Write style. + * + * @param float|int $indent */ - private function writeStyle(XMLWriter $xmlWriter, TOCElement $element, int $indent): void + private function writeStyle(XMLWriter $xmlWriter, TOCElement $element, $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 new file mode 100644 index 0000000000..a86199bf23 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/TOC.php.bak @@ -0,0 +1,202 @@ +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/src/PhpWord/Writer/Word2007/Element/Title.php b/src/PhpWord/Writer/Word2007/Element/Title.php index dd46d755e3..072dcc8d84 100644 --- a/src/PhpWord/Writer/Word2007/Element/Title.php +++ b/src/PhpWord/Writer/Word2007/Element/Title.php @@ -67,7 +67,8 @@ public function write(): void $this->writeText($text); $xmlWriter->endElement(); // w:t $xmlWriter->endElement(); // w:r - } elseif ($text instanceof \PhpOffice\PhpWord\Element\AbstractContainer) { + } + if ($text instanceof \PhpOffice\PhpWord\Element\AbstractContainer) { $containerWriter = new Container($xmlWriter, $text); $containerWriter->write(); } diff --git a/src/PhpWord/Writer/WriterInterface.php b/src/PhpWord/Writer/WriterInterface.php index 58bd455756..f205eed019 100644 --- a/src/PhpWord/Writer/WriterInterface.php +++ b/src/PhpWord/Writer/WriterInterface.php @@ -24,8 +24,6 @@ interface WriterInterface { /** * Save PhpWord to file. - * - * @param string $filename */ - public function save($filename = null); + public function save(string $filename): void; } diff --git a/tests/PhpWordTests/Collection/CollectionTest.php b/tests/PhpWordTests/Collection/CollectionTest.php index 9a18a2a75f..55425a333a 100644 --- a/tests/PhpWordTests/Collection/CollectionTest.php +++ b/tests/PhpWordTests/Collection/CollectionTest.php @@ -45,9 +45,6 @@ public function testCollection(): void self::assertNull($object->getItem(2)); // Check if it's null } - /** - * @covers ::setItem - */ public function testCollectionSetItem(): void { $object = new Footnotes(); diff --git a/tests/PhpWordTests/Element/CellTest.php b/tests/PhpWordTests/Element/CellTest.php index a6affafe7f..a80328edea 100644 --- a/tests/PhpWordTests/Element/CellTest.php +++ b/tests/PhpWordTests/Element/CellTest.php @@ -68,7 +68,7 @@ public function testAddText(): void public function testAddTextNotUTF8(): void { $oCell = new Cell(); - $element = $oCell->addText(utf8_decode('ééé')); + $element = $oCell->addText(Utf8Decode::decode('ééé')); self::assertCount(1, $oCell->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Text', $element); @@ -81,7 +81,7 @@ public function testAddTextNotUTF8(): void public function testAddLink(): void { $oCell = new Cell(); - $element = $oCell->addLink(utf8_decode('ééé'), utf8_decode('ééé')); + $element = $oCell->addLink(Utf8Decode::decode('ééé'), Utf8Decode::decode('ééé')); self::assertCount(1, $oCell->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Link', $element); @@ -117,7 +117,7 @@ public function testAddListItem(): void public function testAddListItemNotUTF8(): void { $oCell = new Cell(); - $element = $oCell->addListItem(utf8_decode('ééé')); + $element = $oCell->addListItem(Utf8Decode::decode('ééé')); self::assertCount(1, $oCell->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\ListItem', $element); @@ -219,7 +219,7 @@ public function testAddPreserveTextNotUTF8(): void { $oCell = new Cell(); $oCell->setDocPart('Header', 1); - $element = $oCell->addPreserveText(utf8_decode('ééé')); + $element = $oCell->addPreserveText(Utf8Decode::decode('ééé')); self::assertCount(1, $oCell->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\PreserveText', $element); @@ -255,7 +255,7 @@ public function testCreateTextRun(): void public function testAddCheckBox(): void { $oCell = new Cell(); - $element = $oCell->addCheckBox(utf8_decode('ééé'), utf8_decode('ééé')); + $element = $oCell->addCheckBox(Utf8Decode::decode('ééé'), Utf8Decode::decode('ééé')); self::assertCount(1, $oCell->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\CheckBox', $element); diff --git a/tests/PhpWordTests/Element/FooterTest.php b/tests/PhpWordTests/Element/FooterTest.php index 672f3db75a..fcd2448611 100644 --- a/tests/PhpWordTests/Element/FooterTest.php +++ b/tests/PhpWordTests/Element/FooterTest.php @@ -57,7 +57,7 @@ public function testAddText(): void public function testAddTextNotUTF8(): void { $oFooter = new Footer(1); - $element = $oFooter->addText(utf8_decode('ééé')); + $element = $oFooter->addText(Utf8Decode::decode('ééé')); self::assertCount(1, $oFooter->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Text', $element); @@ -143,7 +143,7 @@ public function testAddPreserveText(): void public function testAddPreserveTextNotUTF8(): void { $oFooter = new Footer(1); - $element = $oFooter->addPreserveText(utf8_decode('ééé')); + $element = $oFooter->addPreserveText(Utf8Decode::decode('ééé')); self::assertCount(1, $oFooter->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\PreserveText', $element); diff --git a/tests/PhpWordTests/Element/HeaderTest.php b/tests/PhpWordTests/Element/HeaderTest.php index 74e7c12685..5a6f63ed9d 100644 --- a/tests/PhpWordTests/Element/HeaderTest.php +++ b/tests/PhpWordTests/Element/HeaderTest.php @@ -60,7 +60,7 @@ public function testAddText(): void public function testAddTextNotUTF8(): void { $oHeader = new Header(1); - $element = $oHeader->addText(utf8_decode('ééé')); + $element = $oHeader->addText(Utf8Decode::decode('ééé')); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Text', $element); self::assertCount(1, $oHeader->getElements()); @@ -153,7 +153,7 @@ public function testAddPreserveText(): void public function testAddPreserveTextNotUTF8(): void { $oHeader = new Header(1); - $element = $oHeader->addPreserveText(utf8_decode('ééé')); + $element = $oHeader->addPreserveText(Utf8Decode::decode('ééé')); self::assertCount(1, $oHeader->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\PreserveText', $element); diff --git a/tests/PhpWordTests/Element/ImageTest.php b/tests/PhpWordTests/Element/ImageTest.php index 9f1773eb4e..725331a2df 100644 --- a/tests/PhpWordTests/Element/ImageTest.php +++ b/tests/PhpWordTests/Element/ImageTest.php @@ -88,7 +88,7 @@ public function testImages($source, $type, $extension, $createFunction, $imageFu self::assertNotNull($image->getImageStringData()); } - public function providerImages(): array + public static function providerImages(): array { return [ ['mars.jpg', 'image/jpeg', 'jpg', 'imagecreatefromjpeg', true, 100], diff --git a/tests/PhpWordTests/Element/ListItemRunTest.php b/tests/PhpWordTests/Element/ListItemRunTest.php index e438d186d2..387725cb31 100644 --- a/tests/PhpWordTests/Element/ListItemRunTest.php +++ b/tests/PhpWordTests/Element/ListItemRunTest.php @@ -114,7 +114,7 @@ public function testAddText(): void public function testAddTextNotUTF8(): void { $oListItemRun = new ListItemRun(); - $element = $oListItemRun->addText(utf8_decode('ééé')); + $element = $oListItemRun->addText(Utf8Decode::decode('ééé')); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Text', $element); self::assertCount(1, $oListItemRun->getElements()); diff --git a/tests/PhpWordTests/Element/SectionTest.php b/tests/PhpWordTests/Element/SectionTest.php index 72aada10d6..7bcc3bb9a6 100644 --- a/tests/PhpWordTests/Element/SectionTest.php +++ b/tests/PhpWordTests/Element/SectionTest.php @@ -75,18 +75,18 @@ public function testAddElements(): void $section = new Section(0); $section->setPhpWord(new PhpWord()); - $section->addText(utf8_decode('ä')); - $section->addLink(utf8_decode('http://xn--4caaa.com/'), utf8_decode('ä')); + $section->addText(Utf8Decode::decode('ä')); + $section->addLink(Utf8Decode::decode('http://xn--4caaa.com/'), Utf8Decode::decode('ä')); $section->addTextBreak(); $section->addPageBreak(); $section->addTable(); - $section->addListItem(utf8_decode('ä')); + $section->addListItem(Utf8Decode::decode('ä')); $section->addObject($objectSource); $section->addImage($imageSource); - $section->addTitle(utf8_decode('ä'), 1); + $section->addTitle(Utf8Decode::decode('ä'), 1); $section->addTextRun(); $section->addFootnote(); - $section->addCheckBox(utf8_decode('chkä'), utf8_decode('Contentä')); + $section->addCheckBox(Utf8Decode::decode('chkä'), Utf8Decode::decode('Contentä')); $section->addTOC(); $elementCollection = $section->getElements(); diff --git a/tests/PhpWordTests/Element/TextRunTest.php b/tests/PhpWordTests/Element/TextRunTest.php index 2a1ad6efcd..f3c50624ec 100644 --- a/tests/PhpWordTests/Element/TextRunTest.php +++ b/tests/PhpWordTests/Element/TextRunTest.php @@ -99,7 +99,7 @@ public function testAddText(): void public function testAddTextNotUTF8(): void { $oTextRun = new TextRun(); - $element = $oTextRun->addText(utf8_decode('ééé')); + $element = $oTextRun->addText(Utf8Decode::decode('ééé')); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Text', $element); self::assertCount(1, $oTextRun->getElements()); diff --git a/tests/PhpWordTests/Element/Utf8Decode.php b/tests/PhpWordTests/Element/Utf8Decode.php new file mode 100644 index 0000000000..8f3a1cb1ad --- /dev/null +++ b/tests/PhpWordTests/Element/Utf8Decode.php @@ -0,0 +1,29 @@ +write()); + + return $txt2; + } + + public function expect(string $str, bool $rtl = false): string + { + return ($rtl ? self:: HEADER_RTL : self::HEADER) . $str . self::TRAILER; + } + + /** + * Test special characters which require escaping. + */ + public function testSpecial(): void + { + Style::setDefaultRtl(false); + $str = 'Special characters { open brace } close brace \\ backslash'; + $expect = $this->expect('Special characters \\{ open brace \\} close brace \\\\ backslash'); + self::assertEquals($expect, $this->escapestring($str)); + } + + /** + * Test accented character. + */ + public function testAccent(): void + { + Style::setDefaultRtl(false); + $str = 'Voilà - string with accented char'; + $expect = $this->expect('Voil\\uc0{\\u224} - string with accented char'); + self::assertEquals($expect, $this->escapestring($str)); + } + + /** + * Test Hebrew. + */ + public function testHebrew(): void + { + Style::setDefaultRtl(true); + $str = 'Hebrew - שלום'; + $expect = $this->expect('Hebrew - \\uc0{\\u1513}\\uc0{\\u1500}\\uc0{\\u1493}\\uc0{\\u1501}', true); + self::assertEquals($expect, $this->escapestring($str)); + } + + /** + * Test tab. + */ + public function testTab(): void + { + Style::setDefaultRtl(false); + $str = "Here's a tab\tfollowed by more characters."; + $expect = $this->expect("Here's a tab{\\tab}followed by more characters."); + self::assertEquals($expect, $this->escapestring($str)); + } +} diff --git a/tests/PhpWordTests/IOFactoryTest.php b/tests/PhpWordTests/IOFactoryTest.php index 890f45c78e..ee8d7fe180 100644 --- a/tests/PhpWordTests/IOFactoryTest.php +++ b/tests/PhpWordTests/IOFactoryTest.php @@ -54,7 +54,7 @@ public function testCreateWriter(string $name, string $expected): void self::assertInstanceOf($expected, $actual); } - public function providerCreateWriter(): iterable + public static function providerCreateWriter(): iterable { return [ ['ODText', ODText::class], diff --git a/tests/PhpWordTests/PhpWordTest.php b/tests/PhpWordTests/PhpWordTest.php index 19e141f49e..7b756e7082 100644 --- a/tests/PhpWordTests/PhpWordTest.php +++ b/tests/PhpWordTests/PhpWordTest.php @@ -122,13 +122,14 @@ public function testAddTitleStyle(): void */ public function testSave(): void { - $this->setOutputCallback(function (): void { - }); $phpWord = new PhpWord(); $section = $phpWord->addSection(); $section->addText('Hello world!'); - + ob_start(); self::assertTrue($phpWord->save('test.docx', 'Word2007', true)); + $contents = ob_get_contents(); + self::assertTrue(ob_end_clean()); + self::assertNotEmpty($contents); } /** diff --git a/tests/PhpWordTests/Reader/Word2007Test.php b/tests/PhpWordTests/Reader/Word2007Test.php index 1d8674d729..fac5b6b59a 100644 --- a/tests/PhpWordTests/Reader/Word2007Test.php +++ b/tests/PhpWordTests/Reader/Word2007Test.php @@ -40,6 +40,14 @@ */ class Word2007Test extends \PHPUnit\Framework\TestCase { + /** + * Tear down after each test. + */ + protected function tearDown(): void + { + TestHelperDOCX::clear(); + } + /** * Test canRead() method. */ diff --git a/tests/PhpWordTests/Shared/HandlerTest.php b/tests/PhpWordTests/Shared/HandlerTest.php new file mode 100644 index 0000000000..4aa051d3ce --- /dev/null +++ b/tests/PhpWordTests/Shared/HandlerTest.php @@ -0,0 +1,79 @@ +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/HtmlTest.php b/tests/PhpWordTests/Shared/HtmlTest.php index b0ab159150..c8640509de 100644 --- a/tests/PhpWordTests/Shared/HtmlTest.php +++ b/tests/PhpWordTests/Shared/HtmlTest.php @@ -35,6 +35,14 @@ */ class HtmlTest extends AbstractWebServerEmbeddedTest { + /** + * Tear down after each test. + */ + protected function tearDown(): void + { + TestHelperDOCX::clear(); + } + /** * Test unit conversion functions with various numbers. */ @@ -900,7 +908,10 @@ public function testParseLink(): void self::assertEquals('link text', $doc->getElement('/w:document/w:body/w:p/w:hyperlink/w:r/w:t')->nodeValue); self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:hyperlink/w:r/w:rPr/w:u')); self::assertEquals('single', $doc->getElementAttribute('/w:document/w:body/w:p/w:hyperlink/w:r/w:rPr/w:u', 'w:val')); + } + public function testParseLink2(): void + { $phpWord = new PhpWord(); $section = $phpWord->addSection(); $section->addBookmark('bookmark'); diff --git a/tests/PhpWordTests/Shared/TextTest.php b/tests/PhpWordTests/Shared/TextTest.php index fdd9e9df7a..56d7681bcd 100644 --- a/tests/PhpWordTests/Shared/TextTest.php +++ b/tests/PhpWordTests/Shared/TextTest.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWordTests\Shared; use PhpOffice\PhpWord\Shared\Text; +use PhpOffice\PhpWordTests\Element\Utf8Decode; /** * Test class for Text. @@ -66,7 +67,7 @@ public function testIsUTF8(): void { self::assertTrue(Text::isUTF8('')); self::assertTrue(Text::isUTF8('éééé')); - self::assertFalse(Text::isUTF8(utf8_decode('éééé'))); + self::assertFalse(Text::isUTF8(Utf8Decode::decode('éééé'))); } /** diff --git a/tests/PhpWordTests/Style/FontTest.php b/tests/PhpWordTests/Style/FontTest.php index 854a4b5951..e2d7d4f582 100644 --- a/tests/PhpWordTests/Style/FontTest.php +++ b/tests/PhpWordTests/Style/FontTest.php @@ -79,6 +79,8 @@ public function testSetStyleValueWithNullOrEmpty(): void 'kerning' => null, 'lang' => null, 'hidden' => false, + 'htmlWhiteSpace' => '', + 'htmlGenericFont' => '', ]; foreach ($attributes as $key => $default) { $get = is_bool($default) ? "is{$key}" : "get{$key}"; @@ -121,6 +123,8 @@ public function testSetStyleValueNormal(): void 'noProof' => true, 'lang' => new Language(Language::EN_US), 'hidden' => true, + 'htmlWhiteSpace' => 'pre-wrap', + 'htmlGenericFont' => 'serif', ]; $object->setStyleByArray($attributes); foreach ($attributes as $key => $value) { @@ -150,6 +154,7 @@ public function testLineHeight(): void self::assertEquals('auto', $lineRule); // Test setter + TestHelperDOCX::clear(); $text->getFontStyle()->setLineHeight(3.0); $doc = TestHelperDOCX::getDocument($phpWord); $element = $doc->getElement('/w:document/w:body/w:p/w:pPr/w:spacing'); diff --git a/tests/PhpWordTests/Style/ParagraphTest.php b/tests/PhpWordTests/Style/ParagraphTest.php index 124b8829c8..2263e9938e 100644 --- a/tests/PhpWordTests/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Style/ParagraphTest.php @@ -157,6 +157,7 @@ public function testLineHeight(): void // Test setter $text->getParagraphStyle()->setLineHeight(3.0); + TestHelperDOCX::clear(); $doc = TestHelperDOCX::getDocument($phpWord); $element = $doc->getElement('/w:document/w:body/w:p/w:pPr/w:spacing'); diff --git a/tests/PhpWordTests/TemplateProcessorTest.php b/tests/PhpWordTests/TemplateProcessorTest.php index d8ff9ace9e..843ac798e2 100644 --- a/tests/PhpWordTests/TemplateProcessorTest.php +++ b/tests/PhpWordTests/TemplateProcessorTest.php @@ -21,10 +21,12 @@ use Exception; use PhpOffice\PhpWord\Element\Text; use PhpOffice\PhpWord\Element\TextRun; +use PhpOffice\PhpWord\Exception\Exception as WordException; use PhpOffice\PhpWord\IOFactory; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\TemplateProcessor; +use TypeError; use ZipArchive; /** @@ -54,11 +56,8 @@ public function testTheConstruct(): void * @covers ::save * @covers ::zip */ - public function testTemplateCanBeSavedInTemporaryLocation() + public function xtestTemplateCanBeSavedInTemporaryLocation(string $templateFqfn, TemplateProcessor $templateProcessor): string { - $templateFqfn = __DIR__ . '/_files/templates/with_table_macros.docx'; - - $templateProcessor = new TemplateProcessor($templateFqfn); $xslDomDocument = new DOMDocument(); $xslDomDocument->load(__DIR__ . '/_files/xsl/remove_tables_by_needle.xsl'); foreach (['${employee.', '${scoreboard.', '${reference.'] as $needle) { @@ -103,13 +102,13 @@ public function testTemplateCanBeSavedInTemporaryLocation() * XSL stylesheet can be applied. * * @covers ::applyXslStyleSheet - * - * @depends testTemplateCanBeSavedInTemporaryLocation - * - * @param string $actualDocumentFqfn */ - public function testXslStyleSheetCanBeApplied($actualDocumentFqfn): void + public function testXslStyleSheetCanBeApplied(): void { + $templateFqfn = __DIR__ . '/_files/templates/with_table_macros.docx'; + $templateProcessor = new TemplateProcessor($templateFqfn); + + $actualDocumentFqfn = $this->xtestTemplateCanBeSavedInTemporaryLocation($templateFqfn, $templateProcessor); $expectedDocumentFqfn = __DIR__ . '/_files/documents/without_table_macros.docx'; $actualDocumentZip = new ZipArchive(); @@ -130,9 +129,9 @@ public function testXslStyleSheetCanBeApplied($actualDocumentFqfn): void throw new Exception("Could not close zip file \"{$expectedDocumentFqfn}\"."); } - self::assertXmlStringEqualsXmlString($expectedHeaderXml, $actualHeaderXml); - self::assertXmlStringEqualsXmlString($expectedMainPartXml, $actualMainPartXml); - self::assertXmlStringEqualsXmlString($expectedFooterXml, $actualFooterXml); + self::assertSame($expectedHeaderXml, $actualHeaderXml); + self::assertSame($expectedMainPartXml, $actualMainPartXml); + self::assertSame($expectedFooterXml, $actualFooterXml); } /** @@ -142,11 +141,13 @@ public function testXslStyleSheetCanBeApplied($actualDocumentFqfn): void */ public function testXslStyleSheetCanNotBeAppliedOnFailureOfSettingParameterValue(): void { - $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); - $this->expectExceptionMessage('Could not set values for the given XSL style sheet parameters.'); - // Test is not needed for PHP 8.0, because internally validation throws TypeError exception. if (\PHP_VERSION_ID >= 80000) { - self::markTestSkipped('not needed for PHP 8.0'); + // PHP 8+ internal validation throws TypeError. + $this->expectException(TypeError::class); + $this->expectExceptionMessage('must contain only string keys'); + } else { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); + $this->expectExceptionMessage('Could not set values for the given XSL style sheet parameters.'); } $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); @@ -223,7 +224,7 @@ public function testCloneRow(): void ); $docName = 'clone-test-result.docx'; - $templateProcessor->setValue('tableHeader', utf8_decode('ééé')); + $templateProcessor->setValue('tableHeader', 'ééé'); $templateProcessor->cloneRow('userId', 1); $templateProcessor->setValue('userId#1', 'Test'); $templateProcessor->saveAs($docName); @@ -250,7 +251,7 @@ public function testCloneRowWithCustomMacro(): void ); $docName = 'clone-test-result.docx'; - $templateProcessor->setValue('tableHeader', utf8_decode('ééé')); + $templateProcessor->setValue('tableHeader', 'ééé'); $templateProcessor->cloneRow('userId', 1); $templateProcessor->setValue('userId#1', 'Test'); $templateProcessor->saveAs($docName); @@ -1423,6 +1424,18 @@ public function testShouldMakeFieldsUpdateOnOpen(): void self::assertStringContainsString('', $templateProcessor->getSettingsPart()); } + /** + * Should not allow unserialize to avoid malware. + */ + public function testUnserialize(): void + { + $this->expectException(WordException::class); + $this->expectExceptionMessage('unserialize not permitted'); + $object = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); + $serialized = serialize($object); + $object2 = unserialize($serialized); + } + public function testShouldMakeFieldsUpdateOnOpenWithCustomMacro(): void { $settingsPart = ' diff --git a/tests/PhpWordTests/TestHelperDOCX.php b/tests/PhpWordTests/TestHelperDOCX.php index 44766bedaa..de9f1a81b7 100644 --- a/tests/PhpWordTests/TestHelperDOCX.php +++ b/tests/PhpWordTests/TestHelperDOCX.php @@ -80,6 +80,7 @@ public static function clear(): void { if (self::$file && file_exists(self::$file)) { unlink(self::$file); + self::$file = ''; } if (is_dir(Settings::getTempDir() . '/PhpWord_Unit_Test/')) { self::deleteDir(Settings::getTempDir() . '/PhpWord_Unit_Test/'); @@ -103,7 +104,7 @@ public static function deleteDir($dir): void } } - rmdir($dir); + @rmdir($dir); } /** diff --git a/tests/PhpWordTests/Writer/HTML/DirectionTest.php b/tests/PhpWordTests/Writer/HTML/DirectionTest.php new file mode 100644 index 0000000000..d14c0cfad8 --- /dev/null +++ b/tests/PhpWordTests/Writer/HTML/DirectionTest.php @@ -0,0 +1,57 @@ +addSection(); + $html = '

الألم الذي ربما تنجم عنه بعض ا.

'; + SharedHtml::addHtml($section, $html, false, false); + $english = '

LTR in RTL document.

'; + SharedHtml::addHtml($section, $english, false, false); + SharedHtml::addHtml($section, $english, false, false); + SharedHtml::addHtml($section, $html, false, false); + SharedHtml::addHtml($section, $html, false, false); + $writer = new HTML($doc); + $content = $writer->getContent(); + self::assertSame(3, substr_count($content, '')); + self::assertSame(2, substr_count($content, '')); + self::assertSame(3, substr_count($content, '

')); + self::assertSame(2, substr_count($content, '

')); + } +} diff --git a/tests/PhpWordTests/Writer/HTML/ElementTest.php b/tests/PhpWordTests/Writer/HTML/ElementTest.php index ccdd5eaf06..64fa5a31ff 100644 --- a/tests/PhpWordTests/Writer/HTML/ElementTest.php +++ b/tests/PhpWordTests/Writer/HTML/ElementTest.php @@ -76,8 +76,8 @@ public function testWriteTrackChanges(): void $dom = $this->getAsHTML($phpWord); $xpath = new DOMXPath($dom); - self::assertEquals(1, $xpath->query('/html/body/p[1]/ins')->length); - self::assertEquals(1, $xpath->query('/html/body/p[2]/del')->length); + self::assertEquals(1, $xpath->query('/html/body/div/p[1]/ins')->length); + self::assertEquals(1, $xpath->query('/html/body/div/p[2]/del')->length); } /** @@ -100,14 +100,14 @@ public function testWriteColSpan(): void $dom = $this->getAsHTML($phpWord); $xpath = new DOMXPath($dom); - self::assertEquals(1, $xpath->query('/html/body/table/tr[1]/td')->length); - self::assertEquals('2', $xpath->query('/html/body/table/tr/td[1]')->item(0)->attributes->getNamedItem('colspan')->textContent); - self::assertEquals(2, $xpath->query('/html/body/table/tr[2]/td')->length); + self::assertEquals(1, $xpath->query('/html/body/div/table/tr[1]/td')->length); + self::assertEquals('2', $xpath->query('/html/body/div/table/tr/td[1]')->item(0)->attributes->getNamedItem('colspan')->textContent); + self::assertEquals(2, $xpath->query('/html/body/div/table/tr[2]/td')->length); - self::assertEquals('#6086B8', $xpath->query('/html/body/table/tr[1]/td')->item(0)->attributes->getNamedItem('bgcolor')->textContent); - self::assertEquals('#ffffff', $xpath->query('/html/body/table/tr[1]/td')->item(0)->attributes->getNamedItem('color')->textContent); - self::assertEquals('#ffffff', $xpath->query('/html/body/table/tr[2]/td')->item(0)->attributes->getNamedItem('bgcolor')->textContent); - self::assertNull($xpath->query('/html/body/table/tr[2]/td')->item(0)->attributes->getNamedItem('color')); + self::assertEquals('#6086B8', $xpath->query('/html/body/div/table/tr[1]/td')->item(0)->attributes->getNamedItem('bgcolor')->textContent); + self::assertEquals('#ffffff', $xpath->query('/html/body/div/table/tr[1]/td')->item(0)->attributes->getNamedItem('color')->textContent); + self::assertEquals('#ffffff', $xpath->query('/html/body/div/table/tr[2]/td')->item(0)->attributes->getNamedItem('bgcolor')->textContent); + self::assertNull($xpath->query('/html/body/div/table/tr[2]/td')->item(0)->attributes->getNamedItem('color')); } /** @@ -134,9 +134,9 @@ public function testWriteRowSpan(): void $dom = $this->getAsHTML($phpWord); $xpath = new DOMXPath($dom); - self::assertEquals(2, $xpath->query('/html/body/table/tr[1]/td')->length); - self::assertEquals('3', $xpath->query('/html/body/table/tr[1]/td[1]')->item(0)->attributes->getNamedItem('rowspan')->textContent); - self::assertEquals(1, $xpath->query('/html/body/table/tr[2]/td')->length); + self::assertEquals(2, $xpath->query('/html/body/div/table/tr[1]/td')->length); + self::assertEquals('3', $xpath->query('/html/body/div/table/tr[1]/td[1]')->item(0)->attributes->getNamedItem('rowspan')->textContent); + self::assertEquals(1, $xpath->query('/html/body/div/table/tr[2]/td')->length); } private function getAsHTML(PhpWord $phpWord) @@ -211,7 +211,7 @@ public function testWriteTableLayout(): void $dom = $this->getAsHTML($phpWord); $xpath = new DOMXPath($dom); - self::assertEquals('table-layout: fixed;', $xpath->query('/html/body/table[1]')->item(0)->attributes->getNamedItem('style')->textContent); - self::assertEquals('table-layout: auto;', $xpath->query('/html/body/table[2]')->item(0)->attributes->getNamedItem('style')->textContent); + self::assertEquals('table-layout: fixed;', $xpath->query('/html/body/div/table[1]')->item(0)->attributes->getNamedItem('style')->textContent); + self::assertEquals('table-layout: auto;', $xpath->query('/html/body/div/table[2]')->item(0)->attributes->getNamedItem('style')->textContent); } } diff --git a/tests/PhpWordTests/Writer/HTML/FontTest.php b/tests/PhpWordTests/Writer/HTML/FontTest.php new file mode 100644 index 0000000000..cffcd6c7de --- /dev/null +++ b/tests/PhpWordTests/Writer/HTML/FontTest.php @@ -0,0 +1,301 @@ +defaultFontName = Settings::getDefaultFontName(); + $this->defaultFontSize = Settings::getDefaultFontSize(); + } + + /** + * Executed after each method of the class. + */ + protected function tearDown(): void + { + Settings::setDefaultFontName($this->defaultFontName); + Settings::setDefaultFontSize($this->defaultFontSize); + } + + /** + * Tests font names - without generics. + */ + public function testFontNames1(): void + { + $phpWord = new PhpWord(); + $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]); + $phpWord->addFontStyle('style3', ['name' => 'hack attempt\'}; display:none', 'size' => 10]); + $phpWord->addFontStyle('style4', ['name' => 'padmaa 1.1', 'size' => 10, 'bold' => true]); + $phpWord->addFontStyle('style5', ['name' => 'MingLiU-ExtB', 'size' => 10, 'bold' => true]); + $section1 = $phpWord->addSection(); + $section1->addText('Default font'); + $section1->addText('Tahoma', 'style1'); + $section1->addText('Arial', 'style2'); + $section1->addText('hack attempt', 'style3'); + $section1->addText('padmaa 1.1 bold', 'style4'); + $section1->addText('MingLiu-ExtB bold', 'style5'); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/p[1]', 'class')); + self::assertEquals(0, Helper::getLength($xpath, '/html/body/div/p[1]/span')); + self::assertEquals('style1', Helper::getTextContent($xpath, '/html/body/div/p[2]/span', 'class')); + self::assertEquals('style2', Helper::getTextContent($xpath, '/html/body/div/p[3]/span', 'class')); + self::assertEquals('style3', Helper::getTextContent($xpath, '/html/body/div/p[4]/span', 'class')); + self::assertEquals('style4', Helper::getTextContent($xpath, '/html/body/div/p[5]/span', 'class')); + self::assertEquals('style5', Helper::getTextContent($xpath, '/html/body/div/p[6]/span', 'class')); + + $style = Helper::getTextContent($xpath, '/html/head/style'); + $prg = preg_match('/^[*][^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('* {font-family: \'Courier New\'; font-size: 12pt;}', $matches[0]); + $prg = preg_match('/^[.]style1[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style1 {font-family: \'Tahoma\'; font-size: 10pt; color: #1B2232; font-weight: bold;}', $matches[0]); + $prg = preg_match('/^[.]style2[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style2 {font-family: \'Arial\'; font-size: 10pt;}', $matches[0]); + $prg = preg_match('/^[.]style3[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style3 {font-family: \'hack attempt'}; display:none\'; font-size: 10pt;}', $matches[0]); + $prg = preg_match('/^[.]style4[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style4 {font-family: \'padmaa 1.1\'; font-size: 10pt; font-weight: bold;}', $matches[0]); + $prg = preg_match('/^[.]style5[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style5 {font-family: \'MingLiU-ExtB\'; font-size: 10pt; font-weight: bold;}', $matches[0]); + } + + /** + * Tests font names - with generics. + */ + public function testFontNames2(): void + { + $phpWord = new PhpWord(); + $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']); + $section1 = $phpWord->addSection(); + $section1->addText('Default font'); + $section1->addText('Tahoma', 'style1'); + $section1->addText('Arial', 'style2'); + $section1->addText('DejaVu Sans Monospace', 'style3'); + $section1->addText('Arial with invalid fallback', 'style4'); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/p[1]', 'class')); + self::assertEquals(0, Helper::getLength($xpath, '/html/body/div/p[1]/span')); + self::assertEquals('style1', Helper::getTextContent($xpath, '/html/body/div/p[2]/span', 'class')); + self::assertEquals('style2', Helper::getTextContent($xpath, '/html/body/div/p[3]/span', 'class')); + self::assertEquals('style3', Helper::getTextContent($xpath, '/html/body/div/p[4]/span', 'class')); + self::assertEquals('style4', Helper::getTextContent($xpath, '/html/body/div/p[5]/span', 'class')); + + $style = Helper::getTextContent($xpath, '/html/head/style'); + $prg = preg_match('/^[*][^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('* {font-family: \'Courier New\'; font-size: 12pt;}', $matches[0]); + $prg = preg_match('/^[.]style1[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style1 {font-family: \'Tahoma\'; font-size: 10pt; color: #1B2232; font-weight: bold;}', $matches[0]); + $prg = preg_match('/^[.]style2[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style2 {font-family: \'Arial\', sans-serif; font-size: 10pt;}', $matches[0]); + $prg = preg_match('/^[.]style3[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style3 {font-family: \'DejaVu Sans Monospace\', monospace; font-size: 10pt;}', $matches[0]); + $prg = preg_match('/^[.]style4[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style4 {font-family: \'Arial\'; font-size: 10pt;}', $matches[0]); + } + + /** + * Tests font names - with generics including for default font. + */ + 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']); + $section1 = $phpWord->addSection(); + $section1->addText('Default font'); + $section1->addText('Tahoma', 'style1'); + $section1->addText('Arial', 'style2'); + $section1->addText('DejaVu Sans Monospace', 'style3'); + $section1->addText('Arial with invalid fallback', 'style4'); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/p[1]', 'class')); + self::assertEquals(0, Helper::getLength($xpath, '/html/body/div/p[1]/span')); + self::assertEquals('style1', Helper::getTextContent($xpath, '/html/body/div/p[2]/span', 'class')); + self::assertEquals('style2', Helper::getTextContent($xpath, '/html/body/div/p[3]/span', 'class')); + self::assertEquals('style3', Helper::getTextContent($xpath, '/html/body/div/p[4]/span', 'class')); + self::assertEquals('style4', Helper::getTextContent($xpath, '/html/body/div/p[5]/span', 'class')); + + $style = Helper::getTextContent($xpath, '/html/head/style'); + $prg = preg_match('/^[*][^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('* {font-family: \'Courier New\', monospace; font-size: 12pt;}', $matches[0]); + $prg = preg_match('/^[.]style1[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style1 {font-family: \'Tahoma\'; font-size: 10pt; color: #1B2232; font-weight: bold;}', $matches[0]); + $prg = preg_match('/^[.]style2[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style2 {font-family: \'Arial\', sans-serif; font-size: 10pt;}', $matches[0]); + $prg = preg_match('/^[.]style3[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style3 {font-family: \'DejaVu Sans Monospace\', monospace; font-size: 10pt;}', $matches[0]); + $prg = preg_match('/^[.]style4[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style4 {font-family: \'Arial\'; font-size: 10pt;}', $matches[0]); + } + + /** + * Tests white space. + */ + 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']); + $text = 'This is a long line which will be split over 2 lines with pre-wrap'; + $section1 = $phpWord->addSection(); + $section1->addText($text); + $section1->addText($text, 'style1'); + $section1->addText($text, 'style2'); + $section1->addText($text, 'style3'); + $section1->addText($text, 'style4'); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + $style = Helper::getTextContent($xpath, '/html/head/style'); + self::assertNotFalse(preg_match('/^[*][^\\r\\n]*/m', $style, $matches)); + self::assertEquals('* {font-family: \'Arial\'; font-size: 12pt; white-space: pre-wrap;}', $matches[0]); + $prg = preg_match('/^[.]style1[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style1 {font-family: \'Courier New\'; font-size: 10pt; white-space: pre-wrap;}', $matches[0]); + $prg = preg_match('/^[.]style2[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style2 {font-family: \'Courier New\'; font-size: 10pt;}', $matches[0]); + $prg = preg_match('/^[.]style3[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style3 {font-family: \'Courier New\'; font-size: 10pt; white-space: normal;}', $matches[0]); + $prg = preg_match('/^[.]style4[^\\r\\n]*/m', $style, $matches); + self::assertNotFalse($prg); + self::assertEquals('.style4 {font-family: \'Courier New\'; font-size: 10pt;}', $matches[0]); + } + + /** + * Tests inline font style. + */ + public function testInline(): void + { + $phpWord = new PhpWord(); + $style1 = ['name' => 'Courier New', 'size' => 10, 'htmlWhiteSpace' => 'pre-wrap']; + $style2 = ['name' => 'Verdana', 'size' => 8.5]; + $text = 'This is a paragraph.'; + $section1 = $phpWord->addSection(); + $section1->addText($text, $style1); + $section1->addText($text, $style2); + $section1->addText($text); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + self::assertEquals('font-family: \'Courier New\'; font-size: 10pt; white-space: pre-wrap;', Helper::getTextContent($xpath, '/html/body/div/p[1]/span', 'style')); + self::assertEquals('font-family: \'Verdana\'; font-size: 8.5pt;', Helper::getTextContent($xpath, '/html/body/div/p[2]/span', 'style')); + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/p[3]', 'class')); + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/p[3]', 'style')); + self::assertEquals(0, Helper::getLength($xpath, '/html/body/div/p[3]/span')); + } + + /** + * Tests languages. + */ + public function testLanguages(): void + { + $phpWord = new PhpWord(); + $langarabic = new Language('', '', 'ar-DZ'); + $phpWord->addFontStyle('arabic', ['lang' => $langarabic]); + $langhindi = new Language('', 'hi-IN'); + $phpWord->addFontStyle('hindi', ['lang' => $langhindi, 'name' => 'Arial']); + $phpWord->addFontStyle('nolang', ['name' => 'Verdana', 'size' => '10']); + $section = $phpWord->addSection(); + $textrun = $section->addTextRun(); + $textrun->addText('سلام این یک پاراگراف راست به چپ است', ['rtl' => true, 'lang' => $langarabic]); + $section->addText('Ce texte-ci est en français.', ['lang' => 'fr-BE']); + $section->addText('Ce texte-ci aussi.', ['lang' => 'fr-BE', 'name' => 'Verdana']); + $section->addText('Text with no language'); + $section->addText('पाठ हिंदी में', 'hindi'); + $section->addText('Non-existent style', 'nonexistent'); + $section->addText('Style without language', 'nolang'); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + self::assertEquals('ar-DZ', Helper::getTextContent($xpath, '/html/body/div/p[1]/span', 'lang')); + self::assertEquals('fr-BE', Helper::getTextContent($xpath, '/html/body/div/p[2]/span', 'lang')); + self::assertEquals('fr-BE', Helper::getTextContent($xpath, '/html/body/div/p[3]/span', 'lang')); + self::assertEquals('font-family: \'Verdana\';', Helper::getTextContent($xpath, '/html/body/div/p[3]/span', 'style')); + self::assertEquals(0, Helper::getLength($xpath, '/html/body/div/p[4]/span')); + self::assertEquals('hi-IN', Helper::getTextContent($xpath, '/html/body/div/p[5]/span', 'lang')); + self::assertEquals('hindi', Helper::getTextContent($xpath, '/html/body/div/p[5]/span', 'class')); + self::assertEquals('nonexistent', Helper::getTextContent($xpath, '/html/body/div/p[6]/span', 'class')); + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/p[6]/span', 'lang')); + self::assertEquals('nolang', Helper::getTextContent($xpath, '/html/body/div/p[7]/span', 'class')); + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/p[7]/span', 'lang')); + } +} diff --git a/tests/PhpWordTests/Writer/HTML/Helper.php b/tests/PhpWordTests/Writer/HTML/Helper.php new file mode 100644 index 0000000000..ccd542a1c6 --- /dev/null +++ b/tests/PhpWordTests/Writer/HTML/Helper.php @@ -0,0 +1,95 @@ +query($query); + if ($item === false) { + self::fail('Unexpected false return from xpath query'); + } else { + $item2 = $item->item($itemNumber); + if ($item2 === null) { + self::fail('Unexpected null return requesting item'); + } elseif ($namedItem !== '') { + $item3 = $item2->attributes->getNamedItem($namedItem); + if ($item3 === null) { + self::fail('Unexpected null return requesting namedItem'); + } else { + $returnVal = $item3->textContent; + } + } else { + $returnVal = $item2->textContent; + } + } + + return $returnVal; + } + + /** @return mixed */ + public static function getNamedItem(DOMXPath $xpath, string $query, string $namedItem, int $itemNumber = 0) + { + $returnVal = ''; + $item = $xpath->query($query); + if ($item === false) { + self::fail('Unexpected false return from xpath query'); + } else { + $item2 = $item->item($itemNumber); + if ($item2 === null) { + self::fail('Unexpected null return requesting item'); + } else { + $returnValue = $item2->attributes->getNamedItem($namedItem); + } + } + + return $returnVal; + } + + public static function getLength(DOMXPath $xpath, string $query): int + { + $returnVal = 0; + $item = $xpath->query($query); + if ($item === false) { + self::fail('Unexpected false return from xpath query'); + } else { + $returnVal = $item->length; + } + + return $returnVal; + } + + public static function getAsHTML(PhpWord $phpWord): DOMDocument + { + $htmlWriter = new HTML($phpWord); + $dom = new DOMDocument(); + $dom->loadHTML($htmlWriter->getContent()); + + return $dom; + } +} diff --git a/tests/PhpWordTests/Writer/HTML/ParagraphTest.php b/tests/PhpWordTests/Writer/HTML/ParagraphTest.php new file mode 100644 index 0000000000..42c338cdb8 --- /dev/null +++ b/tests/PhpWordTests/Writer/HTML/ParagraphTest.php @@ -0,0 +1,137 @@ + 0, 'spaceAfter' => 0, 'lineHeight' => 1.08]; + $phpWord->addParagraphStyle('indented', [ + 'indentation' => ['left' => 0.50 * Converter::INCH_TO_TWIP, 'right' => 0.60 * Converter::INCH_TO_TWIP], + ]); + $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, null, $pstyle1); + $section1->addText($text, null, 'indented'); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + self::assertEquals(0, Helper::getLength($xpath, '/html/body/div/p[1]/span')); + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/p[1]', 'class')); + self::assertEquals('margin-top: 0pt; margin-bottom: 0pt; line-height: 1.08;', Helper::getTextContent($xpath, '/html/body/div/p[1]', 'style')); + self::assertEquals(0, Helper::getLength($xpath, '/html/body/div/p[2]/span')); + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/p[2]', 'style')); + self::assertEquals('indented', Helper::getTextContent($xpath, '/html/body/div/p[2]', 'class')); + + $style = Helper::getTextContent($xpath, '/html/head/style'); + self::assertNotFalse(preg_match('/^[.]indented[^\\r\\n]*/m', $style, $matches)); + self::assertEquals('.indented {margin-left: 0.5in; margin-right: 0.6in;}', $matches[0]); + } + + /** + * Tests paragraph and font styles specified togeter, both inline and named. + */ + public function testParagraphAndFontStyles(): void + { + $phpWord = new PhpWord(); + $pstyle1 = ['spaceBefore' => 0, 'spaceAfter' => 0, 'lineHeight' => 1.08]; + $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']); + $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); + $section1->addText($text, ['name' => 'Verdana', 'size' => '12'], 'indented'); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + self::assertEquals(1, Helper::getLength($xpath, '/html/body/div/p[1]/span')); + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/p[1]', 'class')); + self::assertEquals('margin-top: 0pt; margin-bottom: 0pt; line-height: 1.08;', Helper::getTextContent($xpath, '/html/body/div/p[1]', 'style')); + self::assertEquals('style1', Helper::getTextContent($xpath, '/html/body/div/p[1]/span', 'class')); + self::assertEquals(1, Helper::getLength($xpath, '/html/body/div/p[2]/span')); + self::assertEmpty(Helper::getNamedItem($xpath, '/html/body/div/p[2]', 'style')); + self::assertEquals('indented', Helper::getTextContent($xpath, '/html/body/div/p[2]', 'class')); + self::assertEquals('font-family: \'Verdana\'; font-size: 12pt;', Helper::getTextContent($xpath, '/html/body/div/p[2]/span', 'style')); + + $style = Helper::getTextContent($xpath, '/html/head/style'); + self::assertNotFalse(preg_match('/^[.]indented[^\\r\\n]*/m', $style, $matches)); + self::assertEquals('.indented {margin-left: 0.5in; margin-right: 0.6in;}', $matches[0]); + self::assertNotFalse(preg_match('/^[.]style1[^\\r\\n]*/m', $style, $matches)); + self::assertEquals('.style1 {font-family: \'Courier New\', monospace; font-size: 10pt; white-space: pre-wrap;}', $matches[0]); + } + + /** + * Tests page break before. + */ + public function testPageBreakBefore(): void + { + $phpWord = new PhpWord(); + $pstyle1 = ['lineHeight' => 1.08]; + $pstyle2 = ['lineHeight' => 1.08, 'pageBreakBefore' => true]; + + $section1 = $phpWord->addSection(); + $section1->addText('1st paragraph 1st page', null, $pstyle1); + $section1->addText('2nd paragraph 1st page', null, $pstyle1); + $section1->addText('1st paragraph 2nd page', null, $pstyle2); + $section1->addText('2nd paragraph 2nd page', null, $pstyle1); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + self::assertEquals('line-height: 1.08;', Helper::getTextContent($xpath, '/html/body/div/p[1]', 'style')); + self::assertEquals('line-height: 1.08;', Helper::getTextContent($xpath, '/html/body/div/p[2]', 'style')); + self::assertEquals('line-height: 1.08; page-break-before: always;', Helper::getTextContent($xpath, '/html/body/div/p[3]', 'style')); + self::assertEquals('line-height: 1.08;', Helper::getTextContent($xpath, '/html/body/div/p[4]', 'style')); + } + + /** + * Tests blank paragraph. + */ + public function testBlankParagraph(): void + { + $phpWord = new PhpWord(); + + $section1 = $phpWord->addSection(); + $section1->addText('Text before blank text'); + $section1->addText(''); + $section1->addText('Text after blank text'); + + $htmlWriter = new HTML($phpWord); + $body = $htmlWriter->getWriterPart('Body')->write(); + $bodylines = explode(PHP_EOL, $body); + self::assertEquals('

Text before blank text

', $bodylines[2]); + self::assertEquals('

 

', $bodylines[3]); + self::assertEquals('

Text after blank text

', $bodylines[4]); + } +} diff --git a/tests/PhpWordTests/Writer/HTML/PartTest.php b/tests/PhpWordTests/Writer/HTML/PartTest.php index 19f1147467..9515932ac8 100644 --- a/tests/PhpWordTests/Writer/HTML/PartTest.php +++ b/tests/PhpWordTests/Writer/HTML/PartTest.php @@ -17,6 +17,9 @@ namespace PhpOffice\PhpWordTests\Writer\HTML; +use DOMXPath; +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Shared\Converter; use PhpOffice\PhpWord\Writer\HTML\Part\Body; /** @@ -33,4 +36,153 @@ public function testGetParentWriterException(): void $object = new Body(); $object->getParentWriter(); } + + /** + * Tests writing multiple sections. + */ + public function testWriteSections(): void + { + $phpWord = new PhpWord(); + $phpWord->getSettings()->setThemeFontLang(new \PhpOffice\PhpWord\Style\Language('en-US')); + $section1 = $phpWord->addSection(); + $mtop = 0.5 * Converter::INCH_TO_TWIP; + $mbot = 0.5 * Converter::INCH_TO_TWIP; + $mrig = 0.75 * Converter::INCH_TO_TWIP; + $mlef = 0.75 * Converter::INCH_TO_TWIP; + $section1 + ->getStyle() + ->setPaperSize('Letter') + ->setMarginTop($mtop) + ->setMarginBottom($mbot) + ->setMarginLeft($mlef) + ->setMarginRight($mrig); + $section1->getStyle()->setPortrait(); + $section1->addText('In theory, this will be printed portrait on letter paper'); + + $section2 = $phpWord->addSection(); + $mtop = 0.6 * Converter::INCH_TO_TWIP; + $mbot = 0.6 * Converter::INCH_TO_TWIP; + $mrig = 0.65 * Converter::INCH_TO_TWIP; + $mlef = 0.65 * Converter::INCH_TO_TWIP; + $section2 + ->getStyle() + ->setPaperSize('A4') + ->setMarginTop($mtop) + ->setMarginBottom($mbot) + ->setMarginLeft($mlef) + ->setMarginRight($mrig); + $section2->getStyle()->setLandscape(); + $section2->addText('In theory, this will be printed landscape on A4 paper'); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + self::assertEquals('en-US', Helper::getTextContent($xpath, '/html', 'lang')); + self::assertEquals(2, Helper::getLength($xpath, '/html/body/div')); + self::assertEquals('page: page1', Helper::getTextContent($xpath, '/html/body/div[1]', 'style')); + self::assertEquals('page: page2', Helper::getTextContent($xpath, '/html/body/div[2]', 'style')); + + $style = Helper::getTextContent($xpath, '/html/head/style'); + self::assertNotFalse(strpos($style, 'body > div + div {page-break-before: always;}')); + self::assertNotFalse(strpos($style, 'div > *:first-child {page-break-before: auto;}')); + self::assertNotFalse(strpos($style, '@page page1 {size: Letter portrait; margin-right: 0.75in; margin-left: 0.75in; margin-top: 0.5in; margin-bottom: 0.5in; }')); + self::assertNotFalse(strpos($style, '@page page2 {size: A4 landscape; margin-right: 0.65in; margin-left: 0.65in; margin-top: 0.6in; margin-bottom: 0.6in; }')); + } + + /** + * Tests theme font East Asian. + */ + public function testThemeFontEastAsian(): void + { + $phpWord = new PhpWord(); + $phpWord->getSettings()->setThemeFontLang(new \PhpOffice\PhpWord\Style\Language('', 'hi-IN')); + $section1 = $phpWord->addSection(); + $section1->addText('??? ????? ???'); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + self::assertEquals('hi-IN', Helper::getTextContent($xpath, '/html', 'lang')); + } + + /** + * Tests theme font bidirectional. + */ + public function testThemeBidirecional(): void + { + $phpWord = new PhpWord(); + $phpWord->getSettings()->setThemeFontLang(new \PhpOffice\PhpWord\Style\Language('', '', 'he-IL')); + $section1 = $phpWord->addSection(); + $section1->addText('????'); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + self::assertEquals('he-IL', Helper::getTextContent($xpath, '/html', 'lang')); + } + + /** + * Tests writing when default paragraph style is specified. + */ + public function testDefaultParagraphStyle(): void + { + $phpWord = new PhpWord(); + $nospacebeforeafter = ['spaceBefore' => 0, 'spaceAfter' => 0]; + $phpWord->setDefaultParagraphStyle($nospacebeforeafter); + $section1 = $phpWord->addSection(); + $section1->addText('First paragraph with no space before or after'); + $section1->addText('Second paragraph with no space before or after'); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + self::assertEmpty(Helper::getNamedItem($xpath, '/html', 'lang')); + $style = Helper::getTextContent($xpath, '/html/head/style'); + self::assertNotFalse(strpos($style, 'p, .Normal {margin-top: 0pt; margin-bottom: 0pt;}')); + } + + /** + * Tests writing when default paragraph style is omitted. + */ + public function testNoDefaultParagraphStyle(): void + { + $phpWord = new PhpWord(); + $section1 = $phpWord->addSection(); + $section1->addText('First paragraph with no space before or after'); + $section1->addText('Second paragraph with no space before or after'); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + $style = Helper::getTextContent($xpath, '/html/head/style'); + self::assertFalse(strpos($style, 'Normal')); + } + + /** + * Tests title styles. + */ + public function testTitleStyles(): void + { + $phpWord = new PhpWord(); + $phpWord->setDefaultParagraphStyle(['spaceBefore' => 0, 'spaceAfter' => 0]); + $phpWord->addTitleStyle(1, ['bold' => true, 'name' => 'Calibri'], ['spaceBefore' => 10, 'spaceAfter' => 10]); + $phpWord->addTitleStyle(2, ['italic' => true, 'name' => 'Times New Roman'], ['spaceBefore' => 5, 'spaceAfter' => 5]); + $section1 = $phpWord->addSection(); + $section1->addTitle('Header 1 #1', 1); + $section1->addTitle('Header 2 #1', 2); + $section1->addText('Paragraph under header 2 #1'); + $section1->addTitle('Header 2 #2', 2); + $section1->addText('Paragraph under header 2 #2'); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + $style = Helper::getTextContent($xpath, '/html/head/style'); + self::assertNotFalse(strpos($style, 'h1 {font-family: \'Calibri\'; font-weight: bold;}')); + self::assertNotFalse(strpos($style, 'h1 {margin-top: 0.5pt; margin-bottom: 0.5pt;}')); + self::assertNotFalse(strpos($style, 'h2 {font-family: \'Times New Roman\'; font-style: italic;}')); + self::assertNotFalse(strpos($style, 'h2 {margin-top: 0.25pt; margin-bottom: 0.25pt;}')); + self::assertEquals(1, Helper::getLength($xpath, '/html/body/div/h1')); + self::assertEquals(2, Helper::getLength($xpath, '/html/body/div/h2')); + } } diff --git a/tests/PhpWordTests/Writer/HTML/StyleTest.php b/tests/PhpWordTests/Writer/HTML/StyleTest.php index 7c360e1a6b..0a6d15d3f6 100644 --- a/tests/PhpWordTests/Writer/HTML/StyleTest.php +++ b/tests/PhpWordTests/Writer/HTML/StyleTest.php @@ -17,6 +17,9 @@ namespace PhpOffice\PhpWordTests\Writer\HTML; +use DOMXPath; +use PhpOffice\PhpWord\PhpWord; + /** * Test class for PhpOffice\PhpWord\Writer\HTML\Style subnamespace. */ @@ -35,4 +38,142 @@ 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/ODText/Element/ImageTest.php b/tests/PhpWordTests/Writer/ODText/Element/ImageTest.php index e150418c9f..671fabc4d0 100644 --- a/tests/PhpWordTests/Writer/ODText/Element/ImageTest.php +++ b/tests/PhpWordTests/Writer/ODText/Element/ImageTest.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWordTests\Writer\ODText\Style; +use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Style\Image; use PhpOffice\PhpWordTests\TestHelperDOCX; @@ -32,6 +33,7 @@ class ImageTest extends \PHPUnit\Framework\TestCase */ protected function tearDown(): void { + Style::setDefaultRtl(null); TestHelperDOCX::clear(); } @@ -62,4 +64,33 @@ public function testImage1(): void self::assertTrue($doc->elementExists($path)); self::assertEquals('IM2', $doc->getElementAttribute($path, 'text:style-name')); } + + /** + * Test writing image, with non-default bidi. + */ + public function testImage2(): void + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + Style::setDefaultRtl(false); + $section = $phpWord->addSection(); + $section->addImage(__DIR__ . '/../../../_files/images/earth.jpg'); + $section->addImage(__DIR__ . '/../../../_files/images/mario.gif', ['align' => 'end']); + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + $s2a = '/office:document-content/office:automatic-styles'; + $element = "$s2a/style:style[3]"; + self::assertEquals('IM1', $doc->getElementAttribute($element, 'style:name')); + $element .= '/style:paragraph-properties'; + self::assertEquals('left', $doc->getElementAttribute($element, 'fo:text-align')); + $element = "$s2a/style:style[4]"; + self::assertEquals('IM2', $doc->getElementAttribute($element, 'style:name')); + $element .= '/style:paragraph-properties'; + self::assertEquals('right', $doc->getElementAttribute($element, 'fo:text-align')); + + $path = '/office:document-content/office:body/office:text/text:section/text:p[2]'; + self::assertTrue($doc->elementExists($path)); + self::assertEquals('IM1', $doc->getElementAttribute($path, 'text:style-name')); + $path = '/office:document-content/office:body/office:text/text:section/text:p[3]'; + self::assertTrue($doc->elementExists($path)); + self::assertEquals('IM2', $doc->getElementAttribute($path, 'text:style-name')); + } } diff --git a/tests/PhpWordTests/Writer/ODText/ElementTest.php b/tests/PhpWordTests/Writer/ODText/ElementTest.php index 45f542b3b1..0ad0325656 100644 --- a/tests/PhpWordTests/Writer/ODText/ElementTest.php +++ b/tests/PhpWordTests/Writer/ODText/ElementTest.php @@ -130,7 +130,7 @@ public function testTableElements(): void $p2t = '/office:document-content/office:body/office:text/text:section'; $tableRootElement = "$p2t/table:table"; self::assertTrue($doc->elementExists($tableRootElement)); - self::assertEquals($tableStyleName, $doc->getElementAttribute($tableRootElement, 'table:style')); + self::assertEquals($tableStyleName, $doc->getElementAttribute($tableRootElement, 'table:style-name')); self::assertTrue($doc->elementExists($tableRootElement . '/table:table-column[4]')); } diff --git a/tests/PhpWordTests/Writer/ODText/Style/FontTest.php b/tests/PhpWordTests/Writer/ODText/Style/FontTest.php index dda0110af5..34e5e506b4 100644 --- a/tests/PhpWordTests/Writer/ODText/Style/FontTest.php +++ b/tests/PhpWordTests/Writer/ODText/Style/FontTest.php @@ -74,7 +74,7 @@ public function testColors(): void self::assertEquals('This should be dark green (FGCOLOR_DARKGREEN)', $doc->getElement($span)->nodeValue); } - public function providerAllNamedColors() + public static function providerAllNamedColors() { return [ [Font::FGCOLOR_YELLOW, 'FFFF00'], diff --git a/tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php b/tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php new file mode 100644 index 0000000000..7098035eee --- /dev/null +++ b/tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php @@ -0,0 +1,153 @@ + 'end']; + $align2 = ['alignment' => 'start']; + $phpWord->setDefaultParagraphStyle($align1); + $section = $phpWord->addSection(); + $section->addText('Should use default alignment (right for this doc)'); + $section->addText('Explicit right alignment', null, $align2); + $section->addText('Explicit left alignment', null, $align1); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + $s2a = '/office:document-content/office:automatic-styles'; + self::assertTrue($doc->elementExists($s2a)); + + $element = "$s2a/style:style[4]"; + self::assertTrue($doc->elementExists($element)); + self::assertEquals('Normal', $doc->getElementAttribute($element, 'style:parent-style-name')); + $element .= '/style:paragraph-properties'; + self::assertTrue($doc->elementExists($element)); + self::assertEquals('right', $doc->getElementAttribute($element, 'fo:text-align')); + + $element = "$s2a/style:style[6]/style:paragraph-properties"; + self::assertTrue($doc->elementExists($element)); + self::assertEquals('right', $doc->getElementAttribute($element, 'fo:text-align')); + + $element = "$s2a/style:style[8]/style:paragraph-properties"; + self::assertTrue($doc->elementExists($element)); + self::assertEquals('left', $doc->getElementAttribute($element, 'fo:text-align')); + + $doc->setDefaultFile('styles.xml'); + $element = '/office:document-styles/office:styles/style:style'; + self::assertTrue($doc->elementExists($element)); + self::assertEquals('Normal', $doc->getElementAttribute($element, 'style:name')); + $element .= '/style:paragraph-properties'; + self::assertTrue($doc->elementExists($element)); + self::assertEquals('left', $doc->getElementAttribute($element, 'fo:text-align')); + } + + /** + * Test text run paragraph style using named style. + */ + public function testTextRun(): void + { + $phpWord = new PhpWord(); + Style::setDefaultRtl(false); + $phpWord->addParagraphStyle('parstyle1', ['align' => 'start']); + $phpWord->addParagraphStyle('parstyle2', ['align' => 'end']); + $section = $phpWord->addSection(); + $trx = $section->addTextRun('parstyle1'); + $trx->addText('First text in textrun. '); + $trx->addText('Second text - paragraph style is specified but ignored.', null, 'parstyle2'); + $section->addText('Third text added to section not textrun - paragraph style is specified and used.', null, 'parstyle2'); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + $s2a = '/office:document-content/office:automatic-styles'; + $element = "$s2a/style:style[3]"; + self::assertEquals('P1_parstyle1', $doc->getElementAttribute($element, 'style:name')); + self::assertEquals('parstyle1', $doc->getElementAttribute($element, 'style:parent-style-name')); + $element = "$s2a/style:style[9]"; + self::assertEquals('P4_parstyle2', $doc->getElementAttribute($element, 'style:name')); + self::assertEquals('parstyle2', $doc->getElementAttribute($element, 'style:parent-style-name')); + + $s2a = '/office:document-content/office:body/office:text/text:section'; + $element = "$s2a/text:p[2]"; + self::assertEquals('P1_parstyle1', $doc->getElementAttribute($element, 'text:style-name')); + $element = "$s2a/text:p[3]"; + self::assertEquals('P4_parstyle2', $doc->getElementAttribute($element, 'text:style-name')); + + $doc->setDefaultFile('styles.xml'); + $element = '/office:document-styles/office:styles/style:style[1]'; + self::assertEquals('parstyle1', $doc->getElementAttribute($element, 'style:name')); + $element .= '/style:paragraph-properties'; + self::assertEquals('left', $doc->getElementAttribute($element, 'fo:text-align')); + $element = '/office:document-styles/office:styles/style:style[2]'; + self::assertEquals('parstyle2', $doc->getElementAttribute($element, 'style:name')); + $element .= '/style:paragraph-properties'; + self::assertEquals('right', $doc->getElementAttribute($element, 'fo:text-align')); + } + + /** + * Test text run paragraph style using unnamed style. + */ + public function testTextRunUnnamed(): void + { + $phpWord = new PhpWord(); + Style::setDefaultRtl(false); + $parstyle1 = ['align' => 'start']; + $parstyle2 = ['align' => 'end']; + $section = $phpWord->addSection(); + $trx = $section->addTextRun($parstyle1); + $trx->addText('First text in textrun. '); + $trx->addText('Second text - paragraph style is specified but ignored.', null, $parstyle2); + $section->addText('Third text added to section not textrun - paragraph style is specified and used.', null, $parstyle2); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + $s2a = '/office:document-content/office:automatic-styles'; + $element = "$s2a/style:style[3]"; + self::assertEquals('P1', $doc->getElementAttribute($element, 'style:name')); + self::assertEquals('Normal', $doc->getElementAttribute($element, 'style:parent-style-name')); + $element .= '/style:paragraph-properties'; + self::assertEquals('left', $doc->getElementAttribute($element, 'fo:text-align')); + $element = "$s2a/style:style[9]"; + self::assertEquals('P4', $doc->getElementAttribute($element, 'style:name')); + self::assertEquals('Normal', $doc->getElementAttribute($element, 'style:parent-style-name')); + $element .= '/style:paragraph-properties'; + self::assertEquals('right', $doc->getElementAttribute($element, 'fo:text-align')); + + $s2a = '/office:document-content/office:body/office:text/text:section'; + $element = "$s2a/text:p[2]"; + self::assertEquals('P1', $doc->getElementAttribute($element, 'text:style-name')); + $element = "$s2a/text:p[3]"; + self::assertEquals('P4', $doc->getElementAttribute($element, 'text:style-name')); + } + + public function testWhenNullifed(): void + { + $dflt1 = Style::getDefaultRtl(); + self::assertFalse($dflt1); + $phpWord = new PhpWord(); + $dflt2 = Style::getDefaultRtl(); + self::assertNull($dflt2); + } +} diff --git a/tests/PhpWordTests/Writer/ODTextTest.php b/tests/PhpWordTests/Writer/ODTextTest.php index 060fda9e45..2405f9db7f 100644 --- a/tests/PhpWordTests/Writer/ODTextTest.php +++ b/tests/PhpWordTests/Writer/ODTextTest.php @@ -103,14 +103,15 @@ public function testSave(): void */ public function testSavePhpOutput(): void { - $this->setOutputCallback(function (): void { - }); $phpWord = new PhpWord(); $section = $phpWord->addSection(); $section->addText('Test'); $writer = new ODText($phpWord); + ob_start(); $writer->save('php://output'); - self::assertNotNull($this->getActualOutput()); + $contents = ob_get_contents(); + self::assertTrue(ob_end_clean()); + self::assertNotEmpty($contents); } /** diff --git a/tests/PhpWordTests/Writer/PDF/MPDFTest.php b/tests/PhpWordTests/Writer/PDF/MPDFTest.php index 5905fa4eaf..9dbbf9d5ac 100644 --- a/tests/PhpWordTests/Writer/PDF/MPDFTest.php +++ b/tests/PhpWordTests/Writer/PDF/MPDFTest.php @@ -20,6 +20,7 @@ use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Writer\PDF; +use PhpOffice\PhpWord\Writer\PDF\MPDF; /** * Test class for PhpOffice\PhpWord\Writer\PDF\MPDF. @@ -39,11 +40,16 @@ public function testConstruct(): void $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'); - $rendererName = Settings::PDF_RENDERER_MPDF; - $rendererLibraryPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/mpdf/mpdf'); - Settings::setPdfRenderer($rendererName, $rendererLibraryPath); - $writer = new PDF($phpWord); + $writer = new MPDF($phpWord); + /** @var callable */ + $callback = [self::class, 'editContent']; + $writer->setEditHtmlCallback($callback); $writer->save($file); self::assertFileExists($file); @@ -58,11 +64,30 @@ public function testSetGetAbstractRendererOptions(): void { $rendererName = Settings::PDF_RENDERER_MPDF; $rendererLibraryPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/mpdf/mpdf'); - Settings::setPdfRenderer($rendererName, $rendererLibraryPath); + Settings::setPdfRenderer($rendererName, (string) $rendererLibraryPath); Settings::setPdfRendererOptions([ 'font' => 'Arial', ]); $writer = new PDF(new PhpWord()); self::assertEquals('Arial', $writer->getFont()); } + + // add a footer + public static function editContent(string $html): string + { + $afterBody = '
{PAGENO}
' . MPDF::SIMULATED_BODY_START; + $beforeBody = ''; + $needle = ''; + $pos = strpos($html, $needle); + if ($pos !== false) { + $html = (string) substr_replace($html, "$beforeBody\n$needle", $pos, strlen($needle)); + } + $needle = ''; + $pos = strpos($html, $needle); + if ($pos !== false) { + $html = (string) substr_replace($html, "$needle\n$afterBody", $pos, strlen($needle)); + } + + return $html; + } } diff --git a/tests/PhpWordTests/Writer/PDF/TCPDFTest.php b/tests/PhpWordTests/Writer/PDF/TCPDFTest.php index c3f05b2b16..00587cb7f3 100644 --- a/tests/PhpWordTests/Writer/PDF/TCPDFTest.php +++ b/tests/PhpWordTests/Writer/PDF/TCPDFTest.php @@ -36,6 +36,7 @@ public function testConstruct(): void $file = __DIR__ . '/../../_files/tcpdf.pdf'; $phpWord = new PhpWord(); + $phpWord->setDefaultParagraphStyle(['spaceBefore' => 0, 'spaceAfter' => 0]); $section = $phpWord->addSection(); $section->addText('Test 1'); diff --git a/tests/PhpWordTests/Writer/PDFTest.php b/tests/PhpWordTests/Writer/PDFTest.php index 72fae65e7f..5a2883feed 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, $rendererLibraryPath); + Settings::setPdfRenderer($rendererName, (string) $rendererLibraryPath); $writer = new PDF(new PhpWord()); $writer->save($file); @@ -55,6 +55,6 @@ public function testConstructException(): void $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); $this->expectExceptionMessage('PDF rendering library or library path has not been defined.'); $writer = new PDF(new PhpWord()); - $writer->save(); + $writer->save('unknown.file'); } } diff --git a/tests/PhpWordTests/Writer/RTF/Element2Test.php b/tests/PhpWordTests/Writer/RTF/Element2Test.php new file mode 100644 index 0000000000..5798b4b1bf --- /dev/null +++ b/tests/PhpWordTests/Writer/RTF/Element2Test.php @@ -0,0 +1,122 @@ +write()); + } + + public function testTable(): void + { + Style::setDefaultRtl(false); + $parentWriter = new RTF(); + $element = new \PhpOffice\PhpWord\Element\Table(); + $width = 100; + $width2 = 2 * $width; + $element->addRow(); + $tce = $element->addCell($width); + $tce->addText('1'); + $tce = $element->addCell($width); + $tce->addText('2'); + $element->addRow(); + $tce = $element->addCell($width); + $tce->addText('3'); + $tce = $element->addCell($width); + $tce->addText('4'); + $table = new WriterTable($parentWriter, $element); + $expect = implode("\n", [ + '\\pard', + "\\trowd \\cellx$width \\cellx$width2 ", + '\\intbl', + '\\ql{\\cf0\\f0 1}\\par', + '\\cell', + '\\intbl', + '{\\cf0\\f0 2}\\par', + '\\cell', + '\\row', + "\\trowd \\cellx$width \\cellx$width2 ", + '\\intbl', + '\\ql{\\cf0\\f0 3}\\par', + '\\cell', + '\\intbl', + '{\\cf0\\f0 4}\par', + '\\cell', + '\\row', + '\\pard', + '', + ]); + + self::assertEquals($expect, $this->removeCr($table)); + } + + public function testTextRun(): void + { + Style::setDefaultRtl(false); + $parentWriter = new RTF(); + $element = new \PhpOffice\PhpWord\Element\TextRun(); + $element->addText('Hello '); + $element->addText('there.'); + $textrun = new WriterTextRun($parentWriter, $element); + $expect = "\\pard\\nowidctlpar \\ql{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; + self::assertEquals($expect, $this->removeCr($textrun)); + } + + public function testTextRunParagraphStyle(): void + { + Style::setDefaultRtl(false); + $parentWriter = new RTF(); + $element = new \PhpOffice\PhpWord\Element\TextRun(['spaceBefore' => 0, 'spaceAfter' => 0]); + $element->addText('Hello '); + $element->addText('there.'); + $textrun = new WriterTextRun($parentWriter, $element); + $expect = "\\pard\\nowidctlpar \\ql\\sb0\\sa0{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; + self::assertEquals($expect, $this->removeCr($textrun)); + } + + public function testTitle(): void + { + $parentWriter = new RTF(); + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + Style::setDefaultRtl(false); + $phpWord->addTitleStyle(1, [], ['spaceBefore' => 0, 'spaceAfter' => 0]); + $section = $phpWord->addSection(); + $element = $section->addTitle('First Heading', 1); + $elwrite = new WriterTitle($parentWriter, $element); + $expect = "\\pard\\nowidctlpar \\ql\\sb0\\sa0{\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}"; + self::assertEquals($expect, $this->removeCr($elwrite)); + Style::setDefaultRtl(null); + } +} diff --git a/tests/PhpWordTests/Writer/RTF/StyleTest.php b/tests/PhpWordTests/Writer/RTF/StyleTest.php index 0605e104fd..3f75f77f28 100644 --- a/tests/PhpWordTests/Writer/RTF/StyleTest.php +++ b/tests/PhpWordTests/Writer/RTF/StyleTest.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWordTests\Writer\RTF; +use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Writer\RTF; use PhpOffice\PhpWord\Writer\RTF\Style\Border; use PHPUnit\Framework\Assert; @@ -26,6 +27,11 @@ */ class StyleTest extends \PHPUnit\Framework\TestCase { + protected function tearDown(): void + { + Style::setDefaultRtl(null); + } + public function removeCr($field) { return str_replace("\r\n", "\n", $field->write()); @@ -123,6 +129,16 @@ public function testRTL(): void self::assertEquals($expect, $this->removeCr($text)); } + public function testRTL2(): void + { + Style::setDefaultRtl(true); + $parentWriter = new RTF(); + $element = new \PhpOffice\PhpWord\Element\Text('אב גד'); + $text = new \PhpOffice\PhpWord\Writer\RTF\Element\Text($parentWriter, $element); + $expect = "\\pard\\nowidctlpar \\qr{\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; + self::assertEquals($expect, $this->removeCr($text)); + } + public function testPageBreakLineHeight(): void { $parentWriter = new RTF(); @@ -132,6 +148,16 @@ public function testPageBreakLineHeight(): void self::assertEquals($expect, $this->removeCr($text)); } + public function testPageBreakLineHeight2(): void + { + Style::setDefaultRtl(false); + $parentWriter = new RTF(); + $element = new \PhpOffice\PhpWord\Element\Text('New page', null, ['lineHeight' => 1.08, 'pageBreakBefore' => true]); + $text = new \PhpOffice\PhpWord\Writer\RTF\Element\Text($parentWriter, $element); + $expect = "\\pard\\nowidctlpar \\ql\\sl259\\slmult1\\page{\\cf0\\f0 New page}\\par\n"; + self::assertEquals($expect, $this->removeCr($text)); + } + public function testPageNumberRestart(): void { //$parentWriter = new RTF(); diff --git a/tests/PhpWordTests/Writer/RTFTest.php b/tests/PhpWordTests/Writer/RTFTest.php index 9b49eaf758..c56bc9f3dc 100644 --- a/tests/PhpWordTests/Writer/RTFTest.php +++ b/tests/PhpWordTests/Writer/RTFTest.php @@ -104,13 +104,14 @@ public function testSave(): void */ public function testSavePhpOutput(): void { - $this->setOutputCallback(function (): void { - }); $phpWord = new PhpWord(); $section = $phpWord->addSection(); $section->addText(htmlspecialchars('Test', ENT_COMPAT, 'UTF-8')); $writer = new RTF($phpWord); + ob_start(); $writer->save('php://output'); - self::assertNotNull($this->getActualOutput()); + $contents = ob_get_contents(); + self::assertTrue(ob_end_clean()); + self::assertNotEmpty($contents); } } diff --git a/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php b/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php index 537fb93d1a..c87379678d 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 diff --git a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php index afb22f17b7..58aaf6df6d 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php @@ -406,12 +406,12 @@ public function testWriteImage(): void // behind $element = $doc->getElement('/w:document/w:body/w:p[2]/w:r/w:pict/v:shape'); $style = $element->getAttribute('style'); - - // Try to address CI coverage issue for PHP 7.1 and 7.2 when using regex match assertions - if (method_exists(static::class, 'assertMatchesRegularExpression')) { + if (method_exists(self::class, 'assertMatchesRegularExpression')) { self::assertMatchesRegularExpression('/z\-index:\-[0-9]*/', $style); - } else { + } elseif (method_exists(self::class, 'assertRegExp')) { self::assertRegExp('/z\-index:\-[0-9]*/', $style); + } else { + self::fail('Unsure how to test regexp'); } // square @@ -436,6 +436,20 @@ public function testWriteWatermark(): void self::assertStringStartsWith('rId', $element->getAttribute('r:id')); } + /** + * covers ::_writeTitle. + */ + public function testWriteTitle(): void + { + $phpWord = new PhpWord(); + $phpWord->addTitleStyle(1, ['bold' => true], ['spaceAfter' => 240]); + $phpWord->addSection()->addTitle('Test', 1); + $doc = TestHelperDOCX::getDocument($phpWord); + + $element = '/w:document/w:body/w:p/w:pPr/w:pStyle'; + self::assertEquals('Heading1', $doc->getElementAttribute($element, 'w:val')); + } + /** * covers ::_writeCheckbox. */ @@ -641,44 +655,6 @@ public function testWriteCellStyleCellGridSpan(): void self::assertEquals(5, $element->getAttribute('w:val')); } - /** - * covers ::_writeCellStyle. - */ - public function testWriteCellStyleCellNoWrapEnabled(): void - { - $phpWord = new PhpWord(); - $section = $phpWord->addSection(); - - $table = $section->addTable(); - $table->addRow(); - - $cell = $table->addCell(200); - $cell->getStyle()->setNoWrap(true); - - $doc = TestHelperDOCX::getDocument($phpWord); - - self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr/w:tc/w:tcPr/w:noWrap')); - } - - /** - * covers ::_writeCellStyle. - */ - public function testWriteCellStyleCellNoWrapDisabled(): void - { - $phpWord = new PhpWord(); - $section = $phpWord->addSection(); - - $table = $section->addTable(); - $table->addRow(); - - $cell = $table->addCell(200); - $cell->getStyle()->setNoWrap(false); - - $doc = TestHelperDOCX::getDocument($phpWord); - - self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr/w:tc/w:tcPr/w:noWrap')); - } - /** * Test write gutter and line numbering. */ diff --git a/tests/PhpWordTests/Writer/Word2007/Part/FooterTest.php b/tests/PhpWordTests/Writer/Word2007/Part/FooterTest.php index 97e8a646fc..0dc99e7e37 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/FooterTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/FooterTest.php @@ -17,8 +17,10 @@ namespace PhpOffice\PhpWordTests\Writer\Word2007\Part; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Writer\Word2007; use PhpOffice\PhpWord\Writer\Word2007\Part\Footer; +use PhpOffice\PhpWordTests\TestHelperDOCX; /** * Test class for PhpOffice\PhpWord\Writer\Word2007\Part\Footer. @@ -44,12 +46,17 @@ public function testWriteFooter(): void $container->addImage($imageSrc); $writer = new Word2007(); - $writer->setUseDiskCaching(true); + $dir = Settings::getTempDir() . DIRECTORY_SEPARATOR . 'phpwordcachefooter'; + if (!is_dir($dir) && !mkdir($dir)) { + self::fail('Unable to create temp directory'); + } + $writer->setUseDiskCaching(true, $dir); $object = new Footer(); $object->setParentWriter($writer); $object->setElement($container); $xml = simplexml_load_string($object->write()); self::assertInstanceOf('SimpleXMLElement', $xml); + TestHelperDOCX::deleteDir($dir); } } diff --git a/tests/PhpWordTests/Writer/Word2007/Part/HeaderTest.php b/tests/PhpWordTests/Writer/Word2007/Part/HeaderTest.php index 6832643b5e..27e9bcb9ba 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/HeaderTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/HeaderTest.php @@ -17,8 +17,10 @@ namespace PhpOffice\PhpWordTests\Writer\Word2007\Part; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Writer\Word2007; use PhpOffice\PhpWord\Writer\Word2007\Part\Header; +use PhpOffice\PhpWordTests\TestHelperDOCX; /** * Test class for PhpOffice\PhpWord\Writer\Word2007\Part\Header. @@ -44,12 +46,17 @@ public function testWriteHeader(): void $container->addWatermark($imageSrc); $writer = new Word2007(); - $writer->setUseDiskCaching(true); + $dir = Settings::getTempDir() . DIRECTORY_SEPARATOR . 'phpwordcachefooter'; + if (!is_dir($dir) && !mkdir($dir)) { + self::fail('Unable to create temp directory'); + } + $writer->setUseDiskCaching(true, $dir); $object = new Header(); $object->setParentWriter($writer); $object->setElement($container); $xml = simplexml_load_string($object->write()); self::assertInstanceOf('SimpleXMLElement', $xml); + TestHelperDOCX::deleteDir($dir); } } diff --git a/tests/PhpWordTests/Writer/Word2007/Style/DirectionTest.php b/tests/PhpWordTests/Writer/Word2007/Style/DirectionTest.php new file mode 100644 index 0000000000..a91de6590e --- /dev/null +++ b/tests/PhpWordTests/Writer/Word2007/Style/DirectionTest.php @@ -0,0 +1,61 @@ +addSection(); + $html = '

الألم الذي ربما تنجم عنه بعض ا.

'; + SharedHtml::addHtml($section, $html, false, false); + $english = '

LTR in RTL document.

'; + SharedHtml::addHtml($section, $english, false, false); + $doc = TestHelperDOCX::getDocument($word, 'Word2007'); + + $path = '/w:document/w:body/w:p[1]/w:pPr/w:bidi'; + self::assertTrue($doc->elementExists($path)); + $path = '/w:document/w:body/w:p[2]/w:pPr/w:bidi'; + self::assertFalse($doc->elementExists($path)); + + $path = '/w:document/w:body/w:p[1]/w:pPr/w:jc'; + self::assertFalse($doc->elementExists($path)); + $path = '/w:document/w:body/w:p[2]/w:pPr/w:jc'; + self::assertTrue($doc->elementExists($path)); + self::assertSame('start', $doc->getElementAttribute($path, 'w:val')); + } +} diff --git a/tests/PhpWordTests/Writer/Word2007Test.php b/tests/PhpWordTests/Writer/Word2007Test.php index 94f9caf8a1..0965222fb3 100644 --- a/tests/PhpWordTests/Writer/Word2007Test.php +++ b/tests/PhpWordTests/Writer/Word2007Test.php @@ -19,6 +19,7 @@ use finfo; use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\Writer\Word2007; use PhpOffice\PhpWordTests\AbstractWebServerEmbeddedTest; @@ -117,13 +118,18 @@ public function testSaveUseDiskCaching(): void $footnote->addText('Test'); $writer = new Word2007($phpWord); - $writer->setUseDiskCaching(true); + $dir = Settings::getTempDir() . DIRECTORY_SEPARATOR . 'phpwordcachefooter'; + if (!is_dir($dir) && !mkdir($dir)) { + self::fail('Unable to create temp directory'); + } + $writer->setUseDiskCaching(true, $dir); $file = __DIR__ . '/../_files/temp.docx'; $writer->save($file); self::assertFileExists($file); unlink($file); + TestHelperDOCX::deleteDir($dir); } /** @@ -170,16 +176,17 @@ public function testGetWriterPartNull(): void */ public function testSetGetUseDiskCaching(): void { - $this->setOutputCallback(function (): void { - }); $phpWord = new PhpWord(); $phpWord->addSection(); $object = new Word2007($phpWord); $object->setUseDiskCaching(true, PHPWORD_TESTS_BASE_DIR); $writer = new Word2007($phpWord); + ob_start(); $writer->save('php://output'); - + $contents = ob_get_contents(); + self::assertTrue(ob_end_clean()); self::assertTrue($object->isUseDiskCaching()); + self::assertNotEmpty($contents); } /** diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 330abe133c..a79ff25e66 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -22,3 +22,35 @@ if (!defined('PHPWORD_TESTS_BASE_DIR')) { define('PHPWORD_TESTS_BASE_DIR', realpath(__DIR__)); } + +function phpunit10ErrorHandler(int $errno, string $errstr, string $filename, int $lineno): bool +{ + $x = error_reporting() & $errno; + if ( + in_array( + $errno, + [ + E_DEPRECATED, + E_WARNING, + E_NOTICE, + E_USER_DEPRECATED, + E_USER_NOTICE, + E_USER_WARNING, + ], + true + ) + ) { + if (0 === $x) { + return true; // message suppressed - stop error handling + } + + throw new \Exception("$errstr $filename $lineno"); + } + + return false; // continue error handling +} + +if (!method_exists(\PHPUnit\Framework\TestCase::class, 'setOutputCallback')) { + ini_set('error_reporting', (string) E_ALL); + set_error_handler('phpunit10ErrorHandler'); +} From b4c180018eb893b9838e9be37fbb598b1e22a65a Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Mon, 18 Sep 2023 16:46:03 -0700 Subject: [PATCH 155/246] Minor Signature Incompatibilities --- src/PhpWord/Writer/ODText.php | 4 +--- src/PhpWord/Writer/RTF.php | 4 +--- src/PhpWord/Writer/Word2007.php | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/PhpWord/Writer/ODText.php b/src/PhpWord/Writer/ODText.php index 6d54706c8e..3eaf80ad4f 100644 --- a/src/PhpWord/Writer/ODText.php +++ b/src/PhpWord/Writer/ODText.php @@ -70,10 +70,8 @@ public function __construct(?PhpWord $phpWord = null) /** * Save PhpWord to file. - * - * @param string $filename */ - public function save($filename = null): void + public function save(string $filename): void { $filename = $this->getTempFile($filename); $zip = $this->getZipArchive($filename); diff --git a/src/PhpWord/Writer/RTF.php b/src/PhpWord/Writer/RTF.php index ebbf8f56c0..1d89c03643 100644 --- a/src/PhpWord/Writer/RTF.php +++ b/src/PhpWord/Writer/RTF.php @@ -56,10 +56,8 @@ public function __construct(?PhpWord $phpWord = null) /** * Save content to file. - * - * @param string $filename */ - public function save($filename = null): void + public function save(string $filename): void { $this->writeFile($this->openFile($filename), $this->getContent()); } diff --git a/src/PhpWord/Writer/Word2007.php b/src/PhpWord/Writer/Word2007.php index ae10ba5a74..ab4fd1e3eb 100644 --- a/src/PhpWord/Writer/Word2007.php +++ b/src/PhpWord/Writer/Word2007.php @@ -91,10 +91,8 @@ public function __construct(?PhpWord $phpWord = null) /** * Save document by name. - * - * @param string $filename */ - public function save($filename = null): void + public function save(string $filename): void { $filename = $this->getTempFile($filename); $zip = $this->getZipArchive($filename); From bcaac65a8729eae545814e4c68aa63f670fbe506 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Mon, 18 Sep 2023 18:09:58 -0700 Subject: [PATCH 156/246] Small Experiment involving @see --- src/PhpWord/Reader/MsDoc.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/PhpWord/Reader/MsDoc.php b/src/PhpWord/Reader/MsDoc.php index 842ba75ba8..3242d0cfdf 100644 --- a/src/PhpWord/Reader/MsDoc.php +++ b/src/PhpWord/Reader/MsDoc.php @@ -1137,7 +1137,7 @@ private function readFibContent(): void /** * Section and information about them. * - * @see : http://msdn.microsoft.com/en-us/library/dd924458%28v=office.12%29.aspx + * @see http://msdn.microsoft.com/en-us/library/dd924458%28v=office.12%29.aspx */ private function readRecordPlcfSed(): void { @@ -1151,7 +1151,7 @@ private function readRecordPlcfSed(): void $posMem += 4; // PlcfSed : aSed - //@see : http://msdn.microsoft.com/en-us/library/dd950194%28v=office.12%29.aspx + //@see http://msdn.microsoft.com/en-us/library/dd950194%28v=office.12%29.aspx $numSed = $this->getNumInLcb($this->arrayFib['lcbPlcfSed'], 12); $aSed = []; @@ -1183,7 +1183,7 @@ private function readRecordPlcfSed(): void /** * Specifies the fonts that are used in the document. * - * @see : http://msdn.microsoft.com/en-us/library/dd943880%28v=office.12%29.aspx + * @see http://msdn.microsoft.com/en-us/library/dd943880%28v=office.12%29.aspx */ private function readRecordSttbfFfn(): void { @@ -1474,7 +1474,7 @@ private function readRecordPlcfBteChpx(): void $offset = $offsetBase; // ChpxFkp - // @see : http://msdn.microsoft.com/en-us/library/dd910989%28v=office.12%29.aspx + // @see http://msdn.microsoft.com/en-us/library/dd910989%28v=office.12%29.aspx $numRGFC = self::getInt1d($this->dataWorkDocument, $offset + 511); $arrayRGFC = []; for ($inc = 0; $inc <= $numRGFC; ++$inc) { @@ -1497,7 +1497,7 @@ private function readRecordPlcfBteChpx(): void if ($rgb > 0) { // Chp Structure - // @see : http://msdn.microsoft.com/en-us/library/dd772849%28v=office.12%29.aspx + // @see http://msdn.microsoft.com/en-us/library/dd772849%28v=office.12%29.aspx $posRGB = $offsetBase + $rgb * 2; $cb = self::getInt1d($this->dataWorkDocument, $posRGB); @@ -1937,7 +1937,7 @@ private function readPrl($data, $pos, $cbNum) // $icoFore = ($operand >> 11) && bindec('11111'); break; // sprmCCv - //@see : http://msdn.microsoft.com/en-us/library/dd952824%28v=office.12%29.aspx + //@see http://msdn.microsoft.com/en-us/library/dd952824%28v=office.12%29.aspx case 0x70: $red = str_pad(dechex(self::getInt1d($this->dataWorkDocument, $pos)), 2, '0', STR_PAD_LEFT); ++$pos; @@ -2048,7 +2048,7 @@ private function readPrl($data, $pos, $cbNum) // HFD > clsid $sprmCPicLocation += 16; // HFD > hyperlink - //@see : http://msdn.microsoft.com/en-us/library/dd909835%28v=office.12%29.aspx + //@see http://msdn.microsoft.com/en-us/library/dd909835%28v=office.12%29.aspx $streamVersion = self::getInt4d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 4; $data = self::getInt4d($this->dataData, $sprmCPicLocation); @@ -2116,8 +2116,8 @@ private function readPrl($data, $pos, $cbNum) }*/ } else { // Pictures - //@see : http://msdn.microsoft.com/en-us/library/dd925458%28v=office.12%29.aspx - //@see : http://msdn.microsoft.com/en-us/library/dd926136%28v=office.12%29.aspx + //@see http://msdn.microsoft.com/en-us/library/dd925458%28v=office.12%29.aspx + //@see http://msdn.microsoft.com/en-us/library/dd926136%28v=office.12%29.aspx // PICF : lcb $sprmCPicLocation += 4; // PICF : cbHeader @@ -2204,13 +2204,13 @@ private function readPrl($data, $pos, $cbNum) $sprmCPicLocation += $shapeRH['recLen']; } // picture : rgfb - //@see : http://msdn.microsoft.com/en-us/library/dd950560%28v=office.12%29.aspx + //@see http://msdn.microsoft.com/en-us/library/dd950560%28v=office.12%29.aspx $fileBlockRH = $this->loadRecordHeader($this->dataData, $sprmCPicLocation); while ($fileBlockRH['recType'] == 0xF007 || ($fileBlockRH['recType'] >= 0xF018 && $fileBlockRH['recType'] <= 0xF117)) { $sprmCPicLocation += 8; switch ($fileBlockRH['recType']) { // OfficeArtFBSE - //@see : http://msdn.microsoft.com/en-us/library/dd944923%28v=office.12%29.aspx + //@see http://msdn.microsoft.com/en-us/library/dd944923%28v=office.12%29.aspx case 0xF007: // btWin32 ++$sprmCPicLocation; @@ -2245,7 +2245,7 @@ private function readPrl($data, $pos, $cbNum) } } // embeddedBlip - //@see : http://msdn.microsoft.com/en-us/library/dd910081%28v=office.12%29.aspx + //@see http://msdn.microsoft.com/en-us/library/dd910081%28v=office.12%29.aspx $embeddedBlipRH = $this->loadRecordHeader($this->dataData, $sprmCPicLocation); switch ($embeddedBlipRH['recType']) { case self::OFFICEARTBLIPJPG: From 4fe91e0febee6797f8ef91b797ac3730aa8abe1d Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Fri, 29 Sep 2023 12:55:07 -0700 Subject: [PATCH 157/246] Remove Redundancies in Doc Blocks --- src/PhpWord/Element/AbstractElement.php | 2 -- src/PhpWord/Element/Comment.php | 4 ---- src/PhpWord/Element/Section.php | 2 -- src/PhpWord/Media.php | 1 - src/PhpWord/Metadata/Settings.php | 2 -- src/PhpWord/Reader/MsDoc.php | 1 + src/PhpWord/Reader/Word2007/AbstractPart.php | 3 --- src/PhpWord/Shared/XMLReader.php | 6 ------ src/PhpWord/TemplateProcessor.php | 2 -- src/PhpWord/Writer/ODText.php | 2 -- src/PhpWord/Writer/RTF.php | 2 -- src/PhpWord/Writer/Word2007/Part/AbstractPart.php | 2 -- src/PhpWord/Writer/Word2007/Part/Settings.php | 6 ------ tests/PhpWordTests/SettingsTest.php | 2 ++ tests/PhpWordTests/Style/TextBoxTest.php | 1 + 15 files changed, 4 insertions(+), 34 deletions(-) diff --git a/src/PhpWord/Element/AbstractElement.php b/src/PhpWord/Element/AbstractElement.php index 90a1f8e46d..9f9c2e82aa 100644 --- a/src/PhpWord/Element/AbstractElement.php +++ b/src/PhpWord/Element/AbstractElement.php @@ -345,8 +345,6 @@ public function getParent() * Set parent container. * * Passed parameter should be a container, except for Table (contain Row) and Row (contain Cell) - * - * @param \PhpOffice\PhpWord\Element\AbstractElement $container */ public function setParentContainer(self $container): void { diff --git a/src/PhpWord/Element/Comment.php b/src/PhpWord/Element/Comment.php index 6972f82379..7e7c5241fa 100644 --- a/src/PhpWord/Element/Comment.php +++ b/src/PhpWord/Element/Comment.php @@ -79,8 +79,6 @@ public function getInitials() /** * Sets the element where this comment starts. - * - * @param \PhpOffice\PhpWord\Element\AbstractElement $value */ public function setStartElement(AbstractElement $value): void { @@ -102,8 +100,6 @@ public function getStartElement() /** * Sets the element where this comment ends. - * - * @param \PhpOffice\PhpWord\Element\AbstractElement $value */ public function setEndElement(AbstractElement $value): void { diff --git a/src/PhpWord/Element/Section.php b/src/PhpWord/Element/Section.php index 68af674016..dbba7f5ccb 100644 --- a/src/PhpWord/Element/Section.php +++ b/src/PhpWord/Element/Section.php @@ -154,8 +154,6 @@ public function getFootnoteProperties() /** * Set the footnote properties. - * - * @param FootnoteProperties $footnoteProperties */ public function setFootnoteProperties(?FootnoteProperties $footnoteProperties = null): void { diff --git a/src/PhpWord/Media.php b/src/PhpWord/Media.php index 35aeeb9658..31487a91fe 100644 --- a/src/PhpWord/Media.php +++ b/src/PhpWord/Media.php @@ -41,7 +41,6 @@ class Media * @param string $container section|headerx|footerx|footnote|endnote * @param string $mediaType image|object|link * @param string $source - * @param \PhpOffice\PhpWord\Element\Image $image * * @return int */ diff --git a/src/PhpWord/Metadata/Settings.php b/src/PhpWord/Metadata/Settings.php index 93359144dc..5aeac09f8c 100644 --- a/src/PhpWord/Metadata/Settings.php +++ b/src/PhpWord/Metadata/Settings.php @@ -275,8 +275,6 @@ public function getRevisionView() /** * Set the Visibility of Annotation Types. - * - * @param TrackChangesView $trackChangesView */ public function setRevisionView(?TrackChangesView $trackChangesView = null): void { diff --git a/src/PhpWord/Reader/MsDoc.php b/src/PhpWord/Reader/MsDoc.php index 3242d0cfdf..4cf755e3fa 100644 --- a/src/PhpWord/Reader/MsDoc.php +++ b/src/PhpWord/Reader/MsDoc.php @@ -1932,6 +1932,7 @@ private function readPrl($data, $pos, $cbNum) // $operand = self::getInt2d($data, $pos); $pos += 2; $cbNum -= 2; + // $ipat = ($operand >> 0) && bindec('111111'); // $icoBack = ($operand >> 6) && bindec('11111'); // $icoFore = ($operand >> 11) && bindec('11111'); diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index e9272ae71d..95799387ed 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -285,8 +285,6 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par /** * Returns the depth of the Heading, returns 0 for a Title. * - * @param array $paragraphStyle - * * @return null|number */ private function getHeadingDepth(?array $paragraphStyle = null) @@ -752,7 +750,6 @@ private function findPossibleAttribute(XMLReader $xmlReader, DOMElement $node, $ /** * Read style definition. * - * @param DOMElement $parentNode * @param array $styleDefs * * @ignoreScrutinizerPatch diff --git a/src/PhpWord/Shared/XMLReader.php b/src/PhpWord/Shared/XMLReader.php index 9acde47d1f..c508b3d320 100644 --- a/src/PhpWord/Shared/XMLReader.php +++ b/src/PhpWord/Shared/XMLReader.php @@ -97,7 +97,6 @@ public function getDomFromString($content) * Get elements. * * @param string $path - * @param DOMElement $contextNode * * @return DOMNodeList */ @@ -139,7 +138,6 @@ public function registerNamespace($prefix, $namespaceURI) * Get element. * * @param string $path - * @param DOMElement $contextNode * * @return null|DOMElement */ @@ -157,7 +155,6 @@ public function getElement($path, ?DOMElement $contextNode = null) * Get element attribute. * * @param string $attribute - * @param DOMElement $contextNode * @param string $path * * @return null|string @@ -185,7 +182,6 @@ public function getAttribute($attribute, ?DOMElement $contextNode = null, $path * Get element value. * * @param string $path - * @param DOMElement $contextNode * * @return null|string */ @@ -203,7 +199,6 @@ public function getValue($path, ?DOMElement $contextNode = null) * Count elements. * * @param string $path - * @param DOMElement $contextNode * * @return int */ @@ -218,7 +213,6 @@ public function countElements($path, ?DOMElement $contextNode = null) * Element exists. * * @param string $path - * @param DOMElement $contextNode * * @return bool */ diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 5198ff1229..5624c93560 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -284,7 +284,6 @@ protected static function ensureUtf8Encoded($subject) /** * @param string $search - * @param \PhpOffice\PhpWord\Element\AbstractElement $complexType */ public function setComplexValue($search, Element\AbstractElement $complexType): void { @@ -312,7 +311,6 @@ public function setComplexValue($search, Element\AbstractElement $complexType): /** * @param string $search - * @param \PhpOffice\PhpWord\Element\AbstractElement $complexType */ public function setComplexBlock($search, Element\AbstractElement $complexType): void { diff --git a/src/PhpWord/Writer/ODText.php b/src/PhpWord/Writer/ODText.php index 3eaf80ad4f..616119e5cc 100644 --- a/src/PhpWord/Writer/ODText.php +++ b/src/PhpWord/Writer/ODText.php @@ -38,8 +38,6 @@ class ODText extends AbstractWriter implements WriterInterface /** * Create new ODText writer. - * - * @param \PhpOffice\PhpWord\PhpWord $phpWord */ public function __construct(?PhpWord $phpWord = null) { diff --git a/src/PhpWord/Writer/RTF.php b/src/PhpWord/Writer/RTF.php index 1d89c03643..0a04d4f53e 100644 --- a/src/PhpWord/Writer/RTF.php +++ b/src/PhpWord/Writer/RTF.php @@ -35,8 +35,6 @@ class RTF extends AbstractWriter implements WriterInterface /** * Create new instance. - * - * @param \PhpOffice\PhpWord\PhpWord $phpWord */ public function __construct(?PhpWord $phpWord = null) { diff --git a/src/PhpWord/Writer/Word2007/Part/AbstractPart.php b/src/PhpWord/Writer/Word2007/Part/AbstractPart.php index def05e537f..ef823f104d 100644 --- a/src/PhpWord/Writer/Word2007/Part/AbstractPart.php +++ b/src/PhpWord/Writer/Word2007/Part/AbstractPart.php @@ -48,8 +48,6 @@ abstract public function write(); /** * Set parent writer. - * - * @param \PhpOffice\PhpWord\Writer\AbstractWriter $writer */ public function setParentWriter(?AbstractWriter $writer = null): void { diff --git a/src/PhpWord/Writer/Word2007/Part/Settings.php b/src/PhpWord/Writer/Word2007/Part/Settings.php index d1f6296912..85a7fe2c50 100644 --- a/src/PhpWord/Writer/Word2007/Part/Settings.php +++ b/src/PhpWord/Writer/Word2007/Part/Settings.php @@ -218,8 +218,6 @@ private function setDocumentProtection($documentProtection): void /** * Set the Proof state. - * - * @param ProofState $proofState */ private function setProofState(?ProofState $proofState = null): void { @@ -235,8 +233,6 @@ private function setProofState(?ProofState $proofState = null): void /** * Set the Revision View. - * - * @param TrackChangesView $trackChangesView */ private function setRevisionView(?TrackChangesView $trackChangesView = null): void { @@ -254,8 +250,6 @@ private function setRevisionView(?TrackChangesView $trackChangesView = null): vo /** * Sets the language. - * - * @param Language $language */ private function setThemeFontLang(?Language $language = null): void { diff --git a/tests/PhpWordTests/SettingsTest.php b/tests/PhpWordTests/SettingsTest.php index 3868c3d813..15b79189a1 100644 --- a/tests/PhpWordTests/SettingsTest.php +++ b/tests/PhpWordTests/SettingsTest.php @@ -23,6 +23,7 @@ * Test class for PhpOffice\PhpWord\Settings. * * @coversDefaultClass \PhpOffice\PhpWord\Settings + * * @runTestsInSeparateProcesses */ class SettingsTest extends TestCase @@ -173,6 +174,7 @@ public function testPhpTempDirIsUsedByDefault(): void /** * @covers ::getTempDir * @covers ::setTempDir + * * @depends testPhpTempDirIsUsedByDefault */ public function testTempDirCanBeSet(): void diff --git a/tests/PhpWordTests/Style/TextBoxTest.php b/tests/PhpWordTests/Style/TextBoxTest.php index 284829aaba..c6647c5084 100644 --- a/tests/PhpWordTests/Style/TextBoxTest.php +++ b/tests/PhpWordTests/Style/TextBoxTest.php @@ -24,6 +24,7 @@ * Test class for PhpOffice\PhpWord\Style\Image. * * @coversDefaultClass \PhpOffice\PhpWord\Style\Image + * * @runTestsInSeparateProcesses */ class TextBoxTest extends TestCase From 52a7cbc935639c354ff6e008e463878090540462 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Wed, 18 Oct 2023 20:46:35 -0700 Subject: [PATCH 158/246] Indentation Changes Makes no sense to multiply by 720 when supplied in array to Paragraph, but left unchanged when supplied directly. Skip multiplication. --- phpstan-baseline.neon | 25 --------------------- src/PhpWord/Style/Paragraph.php | 6 ++--- src/PhpWord/Writer/HTML/Style/Paragraph.php | 2 +- tests/PhpWordTests/Style/ParagraphTest.php | 13 ++++++++--- 4 files changed, 14 insertions(+), 32 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 8c75ddf8a3..80923df489 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1760,36 +1760,11 @@ parameters: count: 1 path: tests/PhpWordTests/Style/FontTest.php - - - message: "#^Binary operation \"\\*\" between 1\\|120\\|240\\|'atLeast'\\|'auto'\\|'Normal'\\|'numStyle'\\|bool and 720 results in an error\\.$#" - count: 1 - path: tests/PhpWordTests/Style/ParagraphTest.php - - message: "#^Cannot call method setLineHeight\\(\\) on PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\|string\\.$#" count: 1 path: tests/PhpWordTests/Style/ParagraphTest.php - - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\Style\\\\ParagraphTest\\:\\:findGetter\\(\\) has no return type specified\\.$#" - count: 1 - path: tests/PhpWordTests/Style/ParagraphTest.php - - - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\Style\\\\ParagraphTest\\:\\:findGetter\\(\\) has parameter \\$key with no type specified\\.$#" - count: 1 - path: tests/PhpWordTests/Style/ParagraphTest.php - - - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\Style\\\\ParagraphTest\\:\\:findGetter\\(\\) has parameter \\$object with no type specified\\.$#" - count: 1 - path: tests/PhpWordTests/Style/ParagraphTest.php - - - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\Style\\\\ParagraphTest\\:\\:findGetter\\(\\) has parameter \\$value with no type specified\\.$#" - count: 1 - path: tests/PhpWordTests/Style/ParagraphTest.php - - message: "#^Parameter \\#2 \\$value of method PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle\\:\\:setStyleValue\\(\\) expects array\\|int\\|string, bool given\\.$#" count: 1 diff --git a/src/PhpWord/Style/Paragraph.php b/src/PhpWord/Style/Paragraph.php index cfd1b5b974..262bcb4e8b 100644 --- a/src/PhpWord/Style/Paragraph.php +++ b/src/PhpWord/Style/Paragraph.php @@ -199,9 +199,9 @@ class Paragraph extends Border public function setStyleValue($key, $value) { $key = Text::removeUnderscorePrefix($key); - if ('indent' == $key || 'hanging' == $key) { - $value = $value * 720; // 720 twips is 0.5 inch - } + //if ('indent' == $key || 'hanging' == $key) { + // $value = $value * 720; // 720 twips is 0.5 inch + //} return parent::setStyleValue($key, $value); } diff --git a/src/PhpWord/Writer/HTML/Style/Paragraph.php b/src/PhpWord/Writer/HTML/Style/Paragraph.php index 73286bda8b..ea234aefe0 100644 --- a/src/PhpWord/Writer/HTML/Style/Paragraph.php +++ b/src/PhpWord/Writer/HTML/Style/Paragraph.php @@ -95,7 +95,7 @@ public function write() } $ind = $style->getIndentation(); if ($ind != null) { - $tcpdf = $this->getParentWriter()->isTcpdf(); + $tcpdf = ($this->getParentWriter() === null) ? false : $this->getParentWriter()->isTcpdf(); // @phpstan-ignore-line $left = $ind->getLeft(); $inches = $left * 1.0 / \PhpOffice\PhpWord\Shared\Converter::INCH_TO_TWIP; $css[$tcpdf ? 'text-indent' : 'margin-left'] = ((string) $inches) . 'in'; diff --git a/tests/PhpWordTests/Style/ParagraphTest.php b/tests/PhpWordTests/Style/ParagraphTest.php index 2263e9938e..f874b087b8 100644 --- a/tests/PhpWordTests/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Style/ParagraphTest.php @@ -91,13 +91,20 @@ public function testSetStyleValueNormal(): void foreach ($attributes as $key => $value) { $get = $this->findGetter($key, $value, $object); $object->setStyleValue("$key", $value); - if ('indent' == $key || 'hanging' == $key) { - $value = $value * 720; - } + //if ('indent' == $key || 'hanging' == $key) { + // $value = $value * 720; + //} self::assertEquals($value, $object->$get()); } } + /** + * @param string $key + * @param mixed $value + * @param object $object + * + * @return string + */ private function findGetter($key, $value, $object) { if (is_bool($value)) { From 942f14859d0662a676417048026e1e432bea751a Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Thu, 19 Oct 2023 07:37:29 -0700 Subject: [PATCH 159/246] Very Minor Improvement --- src/PhpWord/Writer/HTML/Element/Text.php | 3 +++ src/PhpWord/Writer/HTML/Style/Paragraph.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/PhpWord/Writer/HTML/Element/Text.php b/src/PhpWord/Writer/HTML/Element/Text.php index e6c9d00134..35aa00d2d8 100644 --- a/src/PhpWord/Writer/HTML/Element/Text.php +++ b/src/PhpWord/Writer/HTML/Element/Text.php @@ -221,6 +221,9 @@ private function getParagraphStyle() $pStyleIsObject = ($paragraphStyle instanceof Paragraph); if ($pStyleIsObject) { $styleWriter = new ParagraphStyleWriter($paragraphStyle); + /** @var HTML */ + $temp = $this->parentWriter; + $styleWriter->setParentWriter($temp); $style = $styleWriter->write(); } elseif (is_string($paragraphStyle)) { $style = $paragraphStyle; diff --git a/src/PhpWord/Writer/HTML/Style/Paragraph.php b/src/PhpWord/Writer/HTML/Style/Paragraph.php index ea234aefe0..73286bda8b 100644 --- a/src/PhpWord/Writer/HTML/Style/Paragraph.php +++ b/src/PhpWord/Writer/HTML/Style/Paragraph.php @@ -95,7 +95,7 @@ public function write() } $ind = $style->getIndentation(); if ($ind != null) { - $tcpdf = ($this->getParentWriter() === null) ? false : $this->getParentWriter()->isTcpdf(); // @phpstan-ignore-line + $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'; From 4231051783cf1eac3a27a866a4dcc1aa57115b53 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 8 Nov 2023 13:56:15 +0100 Subject: [PATCH 160/246] Changes by @Progi1984 --- docs/changes/1.x/1.2.0.md | 20 +- docs/usage/styles/font.md | 4 +- docs/usage/writers.md | 36 +++- phpstan-baseline.neon | 15 ++ samples/Sample_52_RTLDefault.php | 5 +- src/PhpWord/Metadata/Settings.php | 14 +- src/PhpWord/PhpWord.php | 111 +++++----- src/PhpWord/Settings.php | 17 ++ src/PhpWord/Shared/Handler.php | 46 ---- src/PhpWord/Shared/Text.php | 12 +- src/PhpWord/Shared/Validate.php | 76 +++++++ src/PhpWord/Style.php | 42 ++-- src/PhpWord/Style/Font.php | 117 +++------- src/PhpWord/Style/Paragraph.php | 10 +- src/PhpWord/Style/Table.php | 3 +- src/PhpWord/TemplateProcessor.php | 8 +- src/PhpWord/Writer/HTML.php | 98 ++++++--- .../Writer/HTML/Element/AbstractElement.php | 6 +- src/PhpWord/Writer/HTML/Element/Link.php | 4 +- src/PhpWord/Writer/HTML/Element/ListItem.php | 2 +- src/PhpWord/Writer/HTML/Element/PageBreak.php | 4 +- src/PhpWord/Writer/HTML/Element/Table.php | 69 +----- src/PhpWord/Writer/HTML/Element/Text.php | 70 +++--- src/PhpWord/Writer/HTML/Element/Title.php | 2 +- src/PhpWord/Writer/HTML/Part/Body.php | 5 +- src/PhpWord/Writer/HTML/Part/Head.php | 89 +++++--- src/PhpWord/Writer/HTML/Style/Font.php | 13 +- src/PhpWord/Writer/HTML/Style/Paragraph.php | 40 ++-- src/PhpWord/Writer/HTML/Style/Table.php | 82 +++++++ src/PhpWord/Writer/ODText/Style/Paragraph.php | 3 +- src/PhpWord/Writer/PDF.php | 10 +- src/PhpWord/Writer/PDF/TCPDF.php | 30 +-- src/PhpWord/Writer/RTF/Element/Table.php | 3 +- src/PhpWord/Writer/RTF/Element/Title.php | 11 +- src/PhpWord/Writer/RTF/Part/Document.php | 2 - src/PhpWord/Writer/RTF/Style/Paragraph.php | 6 +- src/PhpWord/Writer/Word2007/Element/TOC.php | 8 +- .../Writer/Word2007/Element/TOC.php.bak | 202 ------------------ tests/PhpWordTests/Element/CellTest.php | 10 +- tests/PhpWordTests/Element/FooterTest.php | 4 +- tests/PhpWordTests/Element/HeaderTest.php | 4 +- .../PhpWordTests/Element/ListItemRunTest.php | 2 +- tests/PhpWordTests/Element/SectionTest.php | 10 +- tests/PhpWordTests/Element/TextRunTest.php | 2 +- tests/PhpWordTests/Element/Utf8Decode.php | 29 --- .../PhpWordTests/Escaper/RtfEscaper3Test.php | 12 +- tests/PhpWordTests/SettingsTest.php | 16 ++ tests/PhpWordTests/Shared/HandlerTest.php | 79 ------- tests/PhpWordTests/Shared/TextTest.php | 3 +- tests/PhpWordTests/Shared/ValidateTest.php | 75 +++++++ tests/PhpWordTests/Style/FontTest.php | 36 +++- tests/PhpWordTests/Style/ParagraphTest.php | 36 +++- tests/PhpWordTests/Style/TableTest.php | 30 +++ .../Writer/HTML/DirectionTest.php | 6 +- .../Writer/HTML/Element/PageBreakTest.php | 73 +++++++ .../Writer/HTML/Element/TableTest.php | 165 ++++++++++++++ tests/PhpWordTests/Writer/HTML/FontTest.php | 28 ++- tests/PhpWordTests/Writer/HTML/Helper.php | 4 +- .../Writer/HTML/ParagraphTest.php | 2 +- tests/PhpWordTests/Writer/HTML/StyleTest.php | 143 +------------ tests/PhpWordTests/Writer/HTMLTest.php | 37 +++- .../Writer/ODText/Element/ImageTest.php | 6 +- .../Writer/ODText/Style/Paragraph2Test.php | 11 +- tests/PhpWordTests/Writer/PDF/MPDFTest.php | 54 +++-- tests/PhpWordTests/Writer/PDFTest.php | 2 +- .../PhpWordTests/Writer/RTF/Element2Test.php | 14 +- tests/PhpWordTests/Writer/RTF/StyleTest.php | 8 +- .../Writer/Word2007/Element/TOCTest.php | 2 +- .../Writer/Word2007/Style/DirectionTest.php | 6 +- tests/bootstrap.php | 5 + 70 files changed, 1171 insertions(+), 1038 deletions(-) delete mode 100644 src/PhpWord/Shared/Handler.php create mode 100644 src/PhpWord/Shared/Validate.php create mode 100644 src/PhpWord/Writer/HTML/Style/Table.php delete mode 100644 src/PhpWord/Writer/Word2007/Element/TOC.php.bak delete mode 100644 tests/PhpWordTests/Element/Utf8Decode.php delete mode 100644 tests/PhpWordTests/Shared/HandlerTest.php create mode 100644 tests/PhpWordTests/Shared/ValidateTest.php create mode 100644 tests/PhpWordTests/Writer/HTML/Element/PageBreakTest.php create mode 100644 tests/PhpWordTests/Writer/HTML/Element/TableTest.php diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index 16d16a47d0..d65f27490b 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -15,6 +15,20 @@ - 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 + - Added Support for Language, both for document overall and individual text elements ### Bug fixes @@ -41,4 +55,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/phpstan-baseline.neon b/phpstan-baseline.neon index 80923df489..e7918d9174 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1850,6 +1850,11 @@ parameters: count: 1 path: tests/PhpWordTests/Writer/HTML/ElementTest.php + - + message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" + count: 3 + path: tests/PhpWordTests/Writer/HTML/Element/PageBreakTest.php + - message: "#^Method PhpOffice\\\\PhpWordTests\\\\Writer\\\\ODText\\\\Style\\\\FontTest\\:\\:providerAllNamedColors\\(\\) has no return type specified\\.$#" count: 1 @@ -1905,6 +1910,11 @@ parameters: count: 1 path: tests/PhpWordTests/Writer/PDF/MPDFTest.php + - + message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDF/MPDFTest.php + - message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" count: 2 @@ -1915,6 +1925,11 @@ parameters: count: 1 path: tests/PhpWordTests/Writer/PDF/TCPDFTest.php + - + message: "#^Parameter \\#2 \\$libraryBaseDir of static method PhpOffice\\\\PhpWord\\\\Settings\\:\\:setPdfRenderer\\(\\) expects string, string\\|false given\\.$#" + count: 1 + path: tests/PhpWordTests/Writer/PDFTest.php + - message: "#^Method PhpOffice\\\\PhpWordTests\\\\Writer\\\\RTF\\\\ElementTest\\:\\:removeCr\\(\\) has no return type specified\\.$#" count: 1 diff --git a/samples/Sample_52_RTLDefault.php b/samples/Sample_52_RTLDefault.php index 080df5571b..164ddd4379 100644 --- a/samples/Sample_52_RTLDefault.php +++ b/samples/Sample_52_RTLDefault.php @@ -5,12 +5,11 @@ use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Shared\Html as SharedHtml; -use PhpOffice\PhpWord\Style; // Suggested by issue 2427. echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new PhpWord(); -Style::setDefaultRtl(true); +Settings::setDefaultRtl(true); $phpWord->setDefaultFontName('DejaVu Sans'); // for good rendition of PDF $rendererName = Settings::PDF_RENDERER_MPDF; $rendererLibraryPath = $vendorDirPath . '/mpdf/mpdf'; @@ -31,4 +30,4 @@ if (!CLI) { include_once 'Sample_Footer.php'; } -Style::setDefaultRtl(null); +Settings::setDefaultRtl(false); 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..a7aa95ce45 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -77,6 +77,7 @@ public function __construct() // Reset Media and styles Media::resetElements(); Style::resetStyles(); + Settings::setDefaultRtl(null); // Collection $collections = ['Bookmarks', 'Titles', 'Footnotes', 'Endnotes', 'Charts', 'Comments']; @@ -256,68 +257,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 +326,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/Settings.php b/src/PhpWord/Settings.php index d79cea6795..984486ccfe 100644 --- a/src/PhpWord/Settings.php +++ b/src/PhpWord/Settings.php @@ -131,6 +131,13 @@ class Settings */ private static $defaultPaper = self::DEFAULT_PAPER; + /** + * Is RTL by default ? + * + * @var ?bool + */ + private static $defaultRtl; + /** * The user defined temporary directory. * @@ -387,6 +394,16 @@ public static function setDefaultFontSize($value): bool return false; } + public static function setDefaultRtl(?bool $defaultRtl): void + { + self::$defaultRtl = $defaultRtl; + } + + public static function isDefaultRtl(): ?bool + { + return self::$defaultRtl; + } + /** * Load setting from phpword.yml or phpword.yml.dist. */ 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; } /** @@ -837,7 +848,7 @@ public function setParagraph($value = null) */ public function isRTL() { - return $this->rtl ?? Style::getDefaultRtl(); + return $this->rtl ?? Settings::isDefaultRtl(); } /** @@ -953,113 +964,43 @@ 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 - * - * @return self + * @param null|string $value Should be one of pre-wrap, normal, nowrap, pre, pre-line, initial, inherit */ - public function setHtmlWhiteSpace($value) + public function setWhiteSpace(?string $value): self { - $this->htmlWhiteSpace = self::validateWhiteSpace($value); + $this->whiteSpace = Validate::validateCSSWhiteSpace($value); return $this; } /** * Get html css white-space 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; } /** * Set generic font for fallback for html. * * @param string $value generic font name - * - * @return self */ - public function setHtmlGenericFont($value) + public function setFallbackFont(?string $value): self { - $this->htmlGenericFont = self::validateGenericFont($value); + $this->fallbackFont = Validate::validateCSSGenericFont($value); return $this; } /** * Get html fallback generic font. - * - * @return string */ - public function getHtmlGenericFont() + public function getFallbackFont(): string { - return $this->htmlGenericFont; + return $this->fallbackFont; } } diff --git a/src/PhpWord/Style/Paragraph.php b/src/PhpWord/Style/Paragraph.php index 262bcb4e8b..c77617403d 100644 --- a/src/PhpWord/Style/Paragraph.php +++ b/src/PhpWord/Style/Paragraph.php @@ -18,10 +18,10 @@ namespace PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Exception\InvalidStyleException; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Shared\Text; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\SimpleType\TextAlignment; -use PhpOffice\PhpWord\Style; /** * Paragraph style. @@ -199,9 +199,9 @@ class Paragraph extends Border public function setStyleValue($key, $value) { $key = Text::removeUnderscorePrefix($key); - //if ('indent' == $key || 'hanging' == $key) { - // $value = $value * 720; // 720 twips is 0.5 inch - //} + if ('indent' == $key || 'hanging' == $key) { + $value = $value * 720; // 720 twips is 0.5 inch + } return parent::setStyleValue($key, $value); } @@ -764,7 +764,7 @@ public function setContextualSpacing($contextualSpacing) */ public function isBidi() { - return $this->bidi ?? Style::getDefaultRtl(); + return $this->bidi ?? Settings::isDefaultRtl(); } /** diff --git a/src/PhpWord/Style/Table.php b/src/PhpWord/Style/Table.php index d1ad6d8a3e..3adb1a38f5 100644 --- a/src/PhpWord/Style/Table.php +++ b/src/PhpWord/Style/Table.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\SimpleType\JcTable; use PhpOffice\PhpWord\SimpleType\TblWidth; @@ -773,7 +774,7 @@ public function setColumnWidths(?array $value = null): void */ public function isBidiVisual() { - return $this->bidiVisual ?? Style::getDefaultRtl(); + return $this->bidiVisual ?? Settings::isDefaultRtl(); } /** 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..647890591d 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,48 @@ public function addNote($noteId, $noteMark): void $this->notes[$noteId] = $noteMark; } + /** + * Get generic name for default font for html. + */ + public function getDefaultGenericFont(): string + { + return $this->defaultGenericFont; + } + + /** + * Set generic name for default font for html. + */ + public function setDefaultGenericFont(string $value): self + { + $this->defaultGenericFont = Validate::validateCSSGenericFont($value); + + return $this; + } + + /** + * Get default white space style for html. + */ + public function getDefaultWhiteSpace(): string + { + return $this->defaultWhiteSpace; + } + + /** + * Set default white space style for html. + */ + 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/AbstractElement.php b/src/PhpWord/Writer/HTML/Element/AbstractElement.php index ae203d70d2..7c7bde3189 100644 --- a/src/PhpWord/Writer/HTML/Element/AbstractElement.php +++ b/src/PhpWord/Writer/HTML/Element/AbstractElement.php @@ -18,7 +18,7 @@ namespace PhpOffice\PhpWord\Writer\HTML\Element; use PhpOffice\PhpWord\Element\AbstractElement as Element; -use PhpOffice\PhpWord\Writer\AbstractWriter; +use PhpOffice\PhpWord\Writer\HTML; /** * Abstract HTML element writer. @@ -30,7 +30,7 @@ abstract class AbstractElement /** * Parent writer. * - * @var \PhpOffice\PhpWord\Writer\AbstractWriter + * @var HTML */ protected $parentWriter; @@ -58,7 +58,7 @@ abstract public function write(); * * @param bool $withoutP */ - public function __construct(AbstractWriter $parentWriter, Element $element, $withoutP = false) + public function __construct(HTML $parentWriter, Element $element, $withoutP = false) { $this->parentWriter = $parentWriter; $this->element = $element; 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..c7a23d2fe1 100644 --- a/src/PhpWord/Writer/HTML/Element/Table.php +++ b/src/PhpWord/Writer/HTML/Element/Table.php @@ -17,6 +17,8 @@ namespace PhpOffice\PhpWord\Writer\HTML\Element; +use PhpOffice\PhpWord\Writer\HTML\Style\Table as TableStyleWriter; + /** * Table element HTML writer. * @@ -39,7 +41,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 +53,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') { @@ -111,10 +113,8 @@ public function write() * Translates Table style in CSS equivalent. * * @param null|\PhpOffice\PhpWord\Style\Cell|\PhpOffice\PhpWord\Style\Table|string $tableStyle - * - * @return string */ - private static function getTableStyle($tableStyle = null) + private function getTableStyle($tableStyle = null): string { if ($tableStyle == null) { return ''; @@ -125,67 +125,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..5af9f2ab63 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 $cssClassStyle */ + $cssClassStyle = Style::getStyle($fontStyle); + if ($cssClassStyle !== null && 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..0f3f86e3d2 100644 --- a/src/PhpWord/Writer/HTML/Part/Head.php +++ b/src/PhpWord/Writer/HTML/Part/Head.php @@ -18,15 +18,15 @@ 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 +67,7 @@ public function write() if ($docProps->$method() != '') { $content .= '' . PHP_EOL; } @@ -80,25 +80,25 @@ public function write() /** * Get styles. - * - * @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..07d91f5487 100644 --- a/src/PhpWord/Writer/HTML/Style/Paragraph.php +++ b/src/PhpWord/Writer/HTML/Style/Paragraph.php @@ -17,7 +17,9 @@ namespace PhpOffice\PhpWord\Writer\HTML\Style; +use PhpOffice\PhpWord\Shared\Converter; use PhpOffice\PhpWord\SimpleType\Jc; +use PhpOffice\PhpWord\Writer\PDF\TCPDF; /** * Paragraph style HTML writer. @@ -49,30 +51,29 @@ public function write() break; case Jc::END: - $textAlign = ($style->isBidi()) ? 'left' : 'right'; + $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'; + $textAlign = $style->isBidi() ? 'right' : 'left'; break; } @@ -89,23 +90,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/ODText/Style/Paragraph.php b/src/PhpWord/Writer/ODText/Style/Paragraph.php index 666294efee..4459c76c01 100644 --- a/src/PhpWord/Writer/ODText/Style/Paragraph.php +++ b/src/PhpWord/Writer/ODText/Style/Paragraph.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWord\Writer\ODText\Style; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Shared\Converter; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\Style; @@ -125,7 +126,7 @@ public function write(): void } $alignment = $style->getAlignment(); $bidi = $style->isBidi(); - $defaultRtl = Style::getDefaultRtl(); + $defaultRtl = Settings::isDefaultRtl(); if ($alignment === '' && $bidi !== null) { $alignment = Jc::START; } diff --git a/src/PhpWord/Writer/PDF.php b/src/PhpWord/Writer/PDF.php index b24e66efb8..f937f599c1 100644 --- a/src/PhpWord/Writer/PDF.php +++ b/src/PhpWord/Writer/PDF.php @@ -20,6 +20,7 @@ use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Settings; +use PhpOffice\PhpWord\Writer\PDF\AbstractRenderer; /** * PDF Writer. @@ -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..1bb1974244 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(); @@ -85,12 +75,14 @@ protected function prepareToWrite(\TCPDF $pdf): void if ($normal instanceof Style\Paragraph) { $before = $normal->getSpaceBefore(); $after = $normal->getSpaceAfter(); - $height = $normal->getLineHeight() ?? ''; if (is_numeric($before) && is_numeric($after)) { - $tagvs = [ - 'p' => [['n' => $before, 'h' => $height], ['n' => $after, 'h' => $height]], - ]; - $pdf->setHtmlVSpace($tagvs); + $height = $normal->getLineHeight() ?? ''; + $pdf->setHtmlVSpace([ + 'p' => [ + ['n' => $before, 'h' => $height], + ['n' => $after, 'h' => $height], + ], + ]); } } } diff --git a/src/PhpWord/Writer/RTF/Element/Table.php b/src/PhpWord/Writer/RTF/Element/Table.php index 45211a9202..b7b370bd5a 100644 --- a/src/PhpWord/Writer/RTF/Element/Table.php +++ b/src/PhpWord/Writer/RTF/Element/Table.php @@ -20,6 +20,7 @@ use PhpOffice\PhpWord\Element\Cell as CellElement; use PhpOffice\PhpWord\Element\Row as RowElement; use PhpOffice\PhpWord\Element\Table as TableElement; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Style; /** @@ -47,7 +48,7 @@ public function write() $content = ''; $style = $this->element->getStyle(); - $bidiStyle = (is_object($style) && method_exists($style, 'isBidiVisual')) ? $style->isBidiVisual() : Style::getDefaultRtl(); + $bidiStyle = (is_object($style) && method_exists($style, 'isBidiVisual')) ? $style->isBidiVisual() : Settings::isDefaultRtl(); $bidi = $bidiStyle ? '\rtlrow' : ''; $rows = $element->getRows(); $rowCount = count($rows); diff --git a/src/PhpWord/Writer/RTF/Element/Title.php b/src/PhpWord/Writer/RTF/Element/Title.php index a387f273ca..fb11da7849 100644 --- a/src/PhpWord/Writer/RTF/Element/Title.php +++ b/src/PhpWord/Writer/RTF/Element/Title.php @@ -38,7 +38,7 @@ protected function getStyles(): void $sect = $element->getParent(); if ($sect instanceof \PhpOffice\PhpWord\Element\Section) { $elems = $sect->getElements(); - if (self::isEqual($elems[0], $element)) { + if ($elems[0] === $element) { $pstyle = clone $pstyle; $pstyle->setPageBreakBefore(false); } @@ -48,15 +48,6 @@ protected function getStyles(): void } } - /** - * @param mixed $comparand1 - * @param mixed $comparand2 - */ - private static function isEqual($comparand1, $comparand2): bool - { - return $comparand1 === $comparand2; - } - /** * Write element. * 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/Element/CellTest.php b/tests/PhpWordTests/Element/CellTest.php index a80328edea..700e16d58e 100644 --- a/tests/PhpWordTests/Element/CellTest.php +++ b/tests/PhpWordTests/Element/CellTest.php @@ -68,7 +68,7 @@ public function testAddText(): void public function testAddTextNotUTF8(): void { $oCell = new Cell(); - $element = $oCell->addText(Utf8Decode::decode('ééé')); + $element = $oCell->addText(utf8decode('ééé')); self::assertCount(1, $oCell->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Text', $element); @@ -81,7 +81,7 @@ public function testAddTextNotUTF8(): void public function testAddLink(): void { $oCell = new Cell(); - $element = $oCell->addLink(Utf8Decode::decode('ééé'), Utf8Decode::decode('ééé')); + $element = $oCell->addLink(utf8decode('ééé'), utf8decode('ééé')); self::assertCount(1, $oCell->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Link', $element); @@ -117,7 +117,7 @@ public function testAddListItem(): void public function testAddListItemNotUTF8(): void { $oCell = new Cell(); - $element = $oCell->addListItem(Utf8Decode::decode('ééé')); + $element = $oCell->addListItem(utf8decode('ééé')); self::assertCount(1, $oCell->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\ListItem', $element); @@ -219,7 +219,7 @@ public function testAddPreserveTextNotUTF8(): void { $oCell = new Cell(); $oCell->setDocPart('Header', 1); - $element = $oCell->addPreserveText(Utf8Decode::decode('ééé')); + $element = $oCell->addPreserveText(utf8decode('ééé')); self::assertCount(1, $oCell->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\PreserveText', $element); @@ -255,7 +255,7 @@ public function testCreateTextRun(): void public function testAddCheckBox(): void { $oCell = new Cell(); - $element = $oCell->addCheckBox(Utf8Decode::decode('ééé'), Utf8Decode::decode('ééé')); + $element = $oCell->addCheckBox(utf8decode('ééé'), utf8decode('ééé')); self::assertCount(1, $oCell->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\CheckBox', $element); diff --git a/tests/PhpWordTests/Element/FooterTest.php b/tests/PhpWordTests/Element/FooterTest.php index fcd2448611..87a857b702 100644 --- a/tests/PhpWordTests/Element/FooterTest.php +++ b/tests/PhpWordTests/Element/FooterTest.php @@ -57,7 +57,7 @@ public function testAddText(): void public function testAddTextNotUTF8(): void { $oFooter = new Footer(1); - $element = $oFooter->addText(Utf8Decode::decode('ééé')); + $element = $oFooter->addText(utf8decode('ééé')); self::assertCount(1, $oFooter->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Text', $element); @@ -143,7 +143,7 @@ public function testAddPreserveText(): void public function testAddPreserveTextNotUTF8(): void { $oFooter = new Footer(1); - $element = $oFooter->addPreserveText(Utf8Decode::decode('ééé')); + $element = $oFooter->addPreserveText(utf8decode('ééé')); self::assertCount(1, $oFooter->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\PreserveText', $element); diff --git a/tests/PhpWordTests/Element/HeaderTest.php b/tests/PhpWordTests/Element/HeaderTest.php index 5a6f63ed9d..12bf5df3e2 100644 --- a/tests/PhpWordTests/Element/HeaderTest.php +++ b/tests/PhpWordTests/Element/HeaderTest.php @@ -60,7 +60,7 @@ public function testAddText(): void public function testAddTextNotUTF8(): void { $oHeader = new Header(1); - $element = $oHeader->addText(Utf8Decode::decode('ééé')); + $element = $oHeader->addText(utf8decode('ééé')); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Text', $element); self::assertCount(1, $oHeader->getElements()); @@ -153,7 +153,7 @@ public function testAddPreserveText(): void public function testAddPreserveTextNotUTF8(): void { $oHeader = new Header(1); - $element = $oHeader->addPreserveText(Utf8Decode::decode('ééé')); + $element = $oHeader->addPreserveText(utf8decode('ééé')); self::assertCount(1, $oHeader->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\PreserveText', $element); diff --git a/tests/PhpWordTests/Element/ListItemRunTest.php b/tests/PhpWordTests/Element/ListItemRunTest.php index 387725cb31..f22c171018 100644 --- a/tests/PhpWordTests/Element/ListItemRunTest.php +++ b/tests/PhpWordTests/Element/ListItemRunTest.php @@ -114,7 +114,7 @@ public function testAddText(): void public function testAddTextNotUTF8(): void { $oListItemRun = new ListItemRun(); - $element = $oListItemRun->addText(Utf8Decode::decode('ééé')); + $element = $oListItemRun->addText(utf8decode('ééé')); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Text', $element); self::assertCount(1, $oListItemRun->getElements()); diff --git a/tests/PhpWordTests/Element/SectionTest.php b/tests/PhpWordTests/Element/SectionTest.php index 7bcc3bb9a6..f978188349 100644 --- a/tests/PhpWordTests/Element/SectionTest.php +++ b/tests/PhpWordTests/Element/SectionTest.php @@ -75,18 +75,18 @@ public function testAddElements(): void $section = new Section(0); $section->setPhpWord(new PhpWord()); - $section->addText(Utf8Decode::decode('ä')); - $section->addLink(Utf8Decode::decode('http://xn--4caaa.com/'), Utf8Decode::decode('ä')); + $section->addText(utf8decode('ä')); + $section->addLink(utf8decode('http://xn--4caaa.com/'), utf8decode('ä')); $section->addTextBreak(); $section->addPageBreak(); $section->addTable(); - $section->addListItem(Utf8Decode::decode('ä')); + $section->addListItem(utf8decode('ä')); $section->addObject($objectSource); $section->addImage($imageSource); - $section->addTitle(Utf8Decode::decode('ä'), 1); + $section->addTitle(utf8decode('ä'), 1); $section->addTextRun(); $section->addFootnote(); - $section->addCheckBox(Utf8Decode::decode('chkä'), Utf8Decode::decode('Contentä')); + $section->addCheckBox(utf8decode('chkä'), utf8decode('Contentä')); $section->addTOC(); $elementCollection = $section->getElements(); diff --git a/tests/PhpWordTests/Element/TextRunTest.php b/tests/PhpWordTests/Element/TextRunTest.php index f3c50624ec..d1318199f9 100644 --- a/tests/PhpWordTests/Element/TextRunTest.php +++ b/tests/PhpWordTests/Element/TextRunTest.php @@ -99,7 +99,7 @@ public function testAddText(): void public function testAddTextNotUTF8(): void { $oTextRun = new TextRun(); - $element = $oTextRun->addText(Utf8Decode::decode('ééé')); + $element = $oTextRun->addText(utf8decode('ééé')); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Text', $element); self::assertCount(1, $oTextRun->getElements()); diff --git a/tests/PhpWordTests/Element/Utf8Decode.php b/tests/PhpWordTests/Element/Utf8Decode.php deleted file mode 100644 index 8f3a1cb1ad..0000000000 --- a/tests/PhpWordTests/Element/Utf8Decode.php +++ /dev/null @@ -1,29 +0,0 @@ -expect('Special characters \\{ open brace \\} close brace \\\\ backslash'); self::assertEquals($expect, $this->escapestring($str)); @@ -65,7 +65,7 @@ public function testSpecial(): void */ public function testAccent(): void { - Style::setDefaultRtl(false); + Settings::setDefaultRtl(false); $str = 'Voilà - string with accented char'; $expect = $this->expect('Voil\\uc0{\\u224} - string with accented char'); self::assertEquals($expect, $this->escapestring($str)); @@ -76,7 +76,7 @@ public function testAccent(): void */ public function testHebrew(): void { - Style::setDefaultRtl(true); + Settings::setDefaultRtl(true); $str = 'Hebrew - שלום'; $expect = $this->expect('Hebrew - \\uc0{\\u1513}\\uc0{\\u1500}\\uc0{\\u1493}\\uc0{\\u1501}', true); self::assertEquals($expect, $this->escapestring($str)); @@ -87,7 +87,7 @@ public function testHebrew(): void */ public function testTab(): void { - Style::setDefaultRtl(false); + Settings::setDefaultRtl(false); $str = "Here's a tab\tfollowed by more characters."; $expect = $this->expect("Here's a tab{\\tab}followed by more characters."); self::assertEquals($expect, $this->escapestring($str)); diff --git a/tests/PhpWordTests/SettingsTest.php b/tests/PhpWordTests/SettingsTest.php index 15b79189a1..46c72eab28 100644 --- a/tests/PhpWordTests/SettingsTest.php +++ b/tests/PhpWordTests/SettingsTest.php @@ -53,6 +53,9 @@ class SettingsTest extends TestCase private $zipClass; + /** @var bool */ + private $defaultRtl; + protected function setUp(): void { $this->compatibility = Settings::hasCompatibility(); @@ -66,6 +69,7 @@ protected function setUp(): void $this->pdfRendererPath = Settings::getPdfRendererPath(); $this->tempDir = Settings::getTempDir(); $this->zipClass = Settings::getZipClass(); + $this->defaultRtl = Settings::isDefaultRtl(); } protected function tearDown(): void @@ -81,6 +85,7 @@ protected function tearDown(): void Settings::setPdfRendererPath($this->pdfRendererPath); Settings::setTempDir($this->tempDir); Settings::setZipClass($this->zipClass); + Settings::setDefaultRtl($this->defaultRtl); } /** @@ -103,6 +108,17 @@ public function testSetGetOutputEscapingEnabled(): void self::assertTrue(Settings::isOutputEscapingEnabled()); } + public function testSetGetDefaultRtl(): void + { + self::assertNull(Settings::isDefaultRtl()); + Settings::setDefaultRtl(true); + self::assertTrue(Settings::isDefaultRtl()); + Settings::setDefaultRtl(false); + self::assertFalse(Settings::isDefaultRtl()); + Settings::setDefaultRtl(null); + self::assertNull(Settings::isDefaultRtl()); + } + /** * Test set/get zip class. */ 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/TextTest.php b/tests/PhpWordTests/Shared/TextTest.php index 56d7681bcd..ee49573722 100644 --- a/tests/PhpWordTests/Shared/TextTest.php +++ b/tests/PhpWordTests/Shared/TextTest.php @@ -18,7 +18,6 @@ namespace PhpOffice\PhpWordTests\Shared; use PhpOffice\PhpWord\Shared\Text; -use PhpOffice\PhpWordTests\Element\Utf8Decode; /** * Test class for Text. @@ -67,7 +66,7 @@ public function testIsUTF8(): void { self::assertTrue(Text::isUTF8('')); self::assertTrue(Text::isUTF8('éééé')); - self::assertFalse(Text::isUTF8(Utf8Decode::decode('éééé'))); + self::assertFalse(Text::isUTF8(utf8decode('éééé'))); } /** diff --git a/tests/PhpWordTests/Shared/ValidateTest.php b/tests/PhpWordTests/Shared/ValidateTest.php new file mode 100644 index 0000000000..b736427150 --- /dev/null +++ b/tests/PhpWordTests/Shared/ValidateTest.php @@ -0,0 +1,75 @@ + null, 'lang' => null, 'hidden' => false, - 'htmlWhiteSpace' => '', - 'htmlGenericFont' => '', + 'whiteSpace' => '', + 'fallbackFont' => '', ]; foreach ($attributes as $key => $default) { $get = is_bool($default) ? "is{$key}" : "get{$key}"; @@ -123,8 +124,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) { @@ -196,4 +197,31 @@ public function testSetLangAsString(): void self::assertInstanceOf('PhpOffice\PhpWord\Style\Language', $object->getLang()); self::assertEquals(Language::FR_BE, $object->getLang()->getLatin()); } + + public function testRTL(): void + { + $object = new Font(); + self::assertNull($object->isRTL()); + self::assertInstanceOf(Font::class, $object->setRTL(true)); + self::assertTrue($object->isRTL()); + self::assertInstanceOf(Font::class, $object->setRTL(false)); + self::assertFalse($object->isRTL()); + } + + public function testRTLSettings(): void + { + Settings::setDefaultRtl(null); + $object = new Font(); + self::assertNull($object->isRTL()); + + Settings::setDefaultRtl(true); + $object = new Font(); + self::assertTrue($object->isRTL()); + + Settings::setDefaultRtl(false); + $object = new Font(); + self::assertFalse($object->isRTL()); + + Settings::setDefaultRtl(null); + } } diff --git a/tests/PhpWordTests/Style/ParagraphTest.php b/tests/PhpWordTests/Style/ParagraphTest.php index f874b087b8..3f44c8eb2d 100644 --- a/tests/PhpWordTests/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Style/ParagraphTest.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWordTests\Style; use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\SimpleType\LineSpacingRule; use PhpOffice\PhpWord\Style\Paragraph; use PhpOffice\PhpWord\Style\Tab; @@ -91,9 +92,9 @@ public function testSetStyleValueNormal(): void foreach ($attributes as $key => $value) { $get = $this->findGetter($key, $value, $object); $object->setStyleValue("$key", $value); - //if ('indent' == $key || 'hanging' == $key) { - // $value = $value * 720; - //} + if (('indent' == $key || 'hanging' == $key) && is_numeric($value)) { + $value = $value * 720; + } self::assertEquals($value, $object->$get()); } } @@ -194,4 +195,33 @@ public function testLineHeightException(): void $object = new Paragraph(); $object->setLineHeight('a'); } + + public function testBidiVisual(): void + { + $object = new Paragraph(); + self::assertNull($object->isBidi()); + self::assertInstanceOf(Paragraph::class, $object->setBidi(true)); + self::assertTrue($object->isBidi()); + self::assertInstanceOf(Paragraph::class, $object->setBidi(false)); + self::assertFalse($object->isBidi()); + self::assertInstanceOf(Paragraph::class, $object->setBidi(null)); + self::assertNull($object->isBidi()); + } + + public function testBidiVisualSettings(): void + { + Settings::setDefaultRtl(null); + $object = new Paragraph(); + self::assertNull($object->isBidi()); + + Settings::setDefaultRtl(true); + $object = new Paragraph(); + self::assertTrue($object->isBidi()); + + Settings::setDefaultRtl(false); + $object = new Paragraph(); + self::assertFalse($object->isBidi()); + + Settings::setDefaultRtl(null); + } } diff --git a/tests/PhpWordTests/Style/TableTest.php b/tests/PhpWordTests/Style/TableTest.php index 393271ca97..2bdb48be1f 100644 --- a/tests/PhpWordTests/Style/TableTest.php +++ b/tests/PhpWordTests/Style/TableTest.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWordTests\Style; use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\SimpleType\JcTable; use PhpOffice\PhpWord\SimpleType\TblWidth; use PhpOffice\PhpWord\Style\Table; @@ -101,6 +102,35 @@ public function testSetGetNormal(): void } } + public function testBidiVisual(): void + { + $object = new Table(); + self::assertNull($object->isBidiVisual()); + self::assertInstanceOf(Table::class, $object->setBidiVisual(true)); + self::assertTrue($object->isBidiVisual()); + self::assertInstanceOf(Table::class, $object->setBidiVisual(false)); + self::assertFalse($object->isBidiVisual()); + self::assertInstanceOf(Table::class, $object->setBidiVisual(null)); + self::assertNull($object->isBidiVisual()); + } + + public function testBidiVisualSettings(): void + { + Settings::setDefaultRtl(null); + $object = new Table(); + self::assertNull($object->isBidiVisual()); + + Settings::setDefaultRtl(true); + $object = new Table(); + self::assertTrue($object->isBidiVisual()); + + Settings::setDefaultRtl(false); + $object = new Table(); + self::assertFalse($object->isBidiVisual()); + + Settings::setDefaultRtl(null); + } + /** * Test border color. * diff --git a/tests/PhpWordTests/Writer/HTML/DirectionTest.php b/tests/PhpWordTests/Writer/HTML/DirectionTest.php index d14c0cfad8..4f0755b87f 100644 --- a/tests/PhpWordTests/Writer/HTML/DirectionTest.php +++ b/tests/PhpWordTests/Writer/HTML/DirectionTest.php @@ -18,8 +18,8 @@ namespace PhpOffice\PhpWordTests\Writer\HTML; use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Shared\Html as SharedHtml; -use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Writer\HTML; /** @@ -29,7 +29,7 @@ class DirectionTest extends \PHPUnit\Framework\TestCase { protected function tearDown(): void { - Style::setDefaultRtl(null); + Settings::setDefaultRtl(null); } /** @@ -38,7 +38,7 @@ protected function tearDown(): void public function testDirection(): void { $doc = new PhpWord(); - Style::setDefaultRtl(true); + Settings::setDefaultRtl(true); $section = $doc->addSection(); $html = '

الألم الذي ربما تنجم عنه بعض ا.

'; SharedHtml::addHtml($section, $html, false, false); diff --git a/tests/PhpWordTests/Writer/HTML/Element/PageBreakTest.php b/tests/PhpWordTests/Writer/HTML/Element/PageBreakTest.php new file mode 100644 index 0000000000..37ef71aa07 --- /dev/null +++ b/tests/PhpWordTests/Writer/HTML/Element/PageBreakTest.php @@ -0,0 +1,73 @@ + 
' . 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..032b7b69cd --- /dev/null +++ b/tests/PhpWordTests/Writer/HTML/Element/TableTest.php @@ -0,0 +1,165 @@ +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..0ad5dd46a0 100644 --- a/tests/PhpWordTests/Writer/HTML/StyleTest.php +++ b/tests/PhpWordTests/Writer/HTML/StyleTest.php @@ -17,9 +17,6 @@ namespace PhpOffice\PhpWordTests\Writer\HTML; -use DOMXPath; -use PhpOffice\PhpWord\PhpWord; - /** * Test class for PhpOffice\PhpWord\Writer\HTML\Style subnamespace. */ @@ -30,7 +27,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 +35,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..700dd2ed3b 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,41 @@ 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/ODText/Element/ImageTest.php b/tests/PhpWordTests/Writer/ODText/Element/ImageTest.php index 671fabc4d0..a71615498c 100644 --- a/tests/PhpWordTests/Writer/ODText/Element/ImageTest.php +++ b/tests/PhpWordTests/Writer/ODText/Element/ImageTest.php @@ -17,7 +17,7 @@ namespace PhpOffice\PhpWordTests\Writer\ODText\Style; -use PhpOffice\PhpWord\Style; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Style\Image; use PhpOffice\PhpWordTests\TestHelperDOCX; @@ -33,7 +33,7 @@ class ImageTest extends \PHPUnit\Framework\TestCase */ protected function tearDown(): void { - Style::setDefaultRtl(null); + Settings::setDefaultRtl(null); TestHelperDOCX::clear(); } @@ -71,7 +71,7 @@ public function testImage1(): void public function testImage2(): void { $phpWord = new \PhpOffice\PhpWord\PhpWord(); - Style::setDefaultRtl(false); + Settings::setDefaultRtl(false); $section = $phpWord->addSection(); $section->addImage(__DIR__ . '/../../../_files/images/earth.jpg'); $section->addImage(__DIR__ . '/../../../_files/images/mario.gif', ['align' => 'end']); diff --git a/tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php b/tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php index 7098035eee..b638b380b6 100644 --- a/tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php +++ b/tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWordTests\Writer\ODText\Style; use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Style; use PhpOffice\PhpWordTests\TestHelperDOCX; @@ -29,7 +30,7 @@ class Paragraph2Test extends \PHPUnit\Framework\TestCase public function testTextAlign(): void { $phpWord = new PhpWord(); - Style::setDefaultRtl(true); + Settings::setDefaultRtl(true); $align1 = ['alignment' => 'end']; $align2 = ['alignment' => 'start']; $phpWord->setDefaultParagraphStyle($align1); @@ -72,7 +73,7 @@ public function testTextAlign(): void public function testTextRun(): void { $phpWord = new PhpWord(); - Style::setDefaultRtl(false); + Settings::setDefaultRtl(false); $phpWord->addParagraphStyle('parstyle1', ['align' => 'start']); $phpWord->addParagraphStyle('parstyle2', ['align' => 'end']); $section = $phpWord->addSection(); @@ -113,7 +114,7 @@ public function testTextRun(): void public function testTextRunUnnamed(): void { $phpWord = new PhpWord(); - Style::setDefaultRtl(false); + Settings::setDefaultRtl(false); $parstyle1 = ['align' => 'start']; $parstyle2 = ['align' => 'end']; $section = $phpWord->addSection(); @@ -144,10 +145,10 @@ public function testTextRunUnnamed(): void public function testWhenNullifed(): void { - $dflt1 = Style::getDefaultRtl(); + $dflt1 = Settings::isDefaultRtl(); self::assertFalse($dflt1); $phpWord = new PhpWord(); - $dflt2 = Style::getDefaultRtl(); + $dflt2 = Settings::isDefaultRtl(); self::assertNull($dflt2); } } 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/RTF/Element2Test.php b/tests/PhpWordTests/Writer/RTF/Element2Test.php index 5798b4b1bf..d82a3095d7 100644 --- a/tests/PhpWordTests/Writer/RTF/Element2Test.php +++ b/tests/PhpWordTests/Writer/RTF/Element2Test.php @@ -17,7 +17,7 @@ namespace PhpOffice\PhpWordTests\Writer\RTF; -use PhpOffice\PhpWord\Style; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Writer\RTF; use PhpOffice\PhpWord\Writer\RTF\Element\Table as WriterTable; use PhpOffice\PhpWord\Writer\RTF\Element\TextRun as WriterTextRun; @@ -30,7 +30,7 @@ class Element2Test extends \PHPUnit\Framework\TestCase { protected function tearDown(): void { - Style::setDefaultRtl(null); + Settings::setDefaultRtl(null); } /** @param WriterTable|WriterTextRun|WriterTitle $field */ @@ -41,7 +41,7 @@ public function removeCr($field): string public function testTable(): void { - Style::setDefaultRtl(false); + Settings::setDefaultRtl(false); $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Table(); $width = 100; @@ -84,7 +84,7 @@ public function testTable(): void public function testTextRun(): void { - Style::setDefaultRtl(false); + Settings::setDefaultRtl(false); $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\TextRun(); $element->addText('Hello '); @@ -96,7 +96,7 @@ public function testTextRun(): void public function testTextRunParagraphStyle(): void { - Style::setDefaultRtl(false); + Settings::setDefaultRtl(false); $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\TextRun(['spaceBefore' => 0, 'spaceAfter' => 0]); $element->addText('Hello '); @@ -110,13 +110,13 @@ public function testTitle(): void { $parentWriter = new RTF(); $phpWord = new \PhpOffice\PhpWord\PhpWord(); - Style::setDefaultRtl(false); + Settings::setDefaultRtl(false); $phpWord->addTitleStyle(1, [], ['spaceBefore' => 0, 'spaceAfter' => 0]); $section = $phpWord->addSection(); $element = $section->addTitle('First Heading', 1); $elwrite = new WriterTitle($parentWriter, $element); $expect = "\\pard\\nowidctlpar \\ql\\sb0\\sa0{\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}"; self::assertEquals($expect, $this->removeCr($elwrite)); - Style::setDefaultRtl(null); + Settings::setDefaultRtl(null); } } diff --git a/tests/PhpWordTests/Writer/RTF/StyleTest.php b/tests/PhpWordTests/Writer/RTF/StyleTest.php index 3f75f77f28..8f09fec40c 100644 --- a/tests/PhpWordTests/Writer/RTF/StyleTest.php +++ b/tests/PhpWordTests/Writer/RTF/StyleTest.php @@ -17,7 +17,7 @@ namespace PhpOffice\PhpWordTests\Writer\RTF; -use PhpOffice\PhpWord\Style; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Writer\RTF; use PhpOffice\PhpWord\Writer\RTF\Style\Border; use PHPUnit\Framework\Assert; @@ -29,7 +29,7 @@ class StyleTest extends \PHPUnit\Framework\TestCase { protected function tearDown(): void { - Style::setDefaultRtl(null); + Settings::setDefaultRtl(null); } public function removeCr($field) @@ -131,7 +131,7 @@ public function testRTL(): void public function testRTL2(): void { - Style::setDefaultRtl(true); + Settings::setDefaultRtl(true); $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('אב גד'); $text = new \PhpOffice\PhpWord\Writer\RTF\Element\Text($parentWriter, $element); @@ -150,7 +150,7 @@ public function testPageBreakLineHeight(): void public function testPageBreakLineHeight2(): void { - Style::setDefaultRtl(false); + Settings::setDefaultRtl(false); $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('New page', null, ['lineHeight' => 1.08, 'pageBreakBefore' => true]); $text = new \PhpOffice\PhpWord\Writer\RTF\Element\Text($parentWriter, $element); 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 diff --git a/tests/PhpWordTests/Writer/Word2007/Style/DirectionTest.php b/tests/PhpWordTests/Writer/Word2007/Style/DirectionTest.php index a91de6590e..b5e93d2374 100644 --- a/tests/PhpWordTests/Writer/Word2007/Style/DirectionTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Style/DirectionTest.php @@ -18,8 +18,8 @@ namespace PhpOffice\PhpWordTests\Writer\Word2007\Style; use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Shared\Html as SharedHtml; -use PhpOffice\PhpWord\Style; use PhpOffice\PhpWordTests\TestHelperDOCX; class DirectionTest extends \PHPUnit\Framework\TestCase @@ -29,7 +29,7 @@ class DirectionTest extends \PHPUnit\Framework\TestCase */ protected function tearDown(): void { - Style::setDefaultRtl(null); + Settings::setDefaultRtl(null); TestHelperDOCX::clear(); } @@ -39,7 +39,7 @@ protected function tearDown(): void public function testDirection(): void { $word = new PhpWord(); - Style::setDefaultRtl(true); + Settings::setDefaultRtl(true); $section = $word->addSection(); $html = '

الألم الذي ربما تنجم عنه بعض ا.

'; SharedHtml::addHtml($section, $html, false, false); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index a79ff25e66..845e59db70 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -50,6 +50,11 @@ function phpunit10ErrorHandler(int $errno, string $errstr, string $filename, int return false; // continue error handling } +function utf8decode(string $value, string $toEncoding = 'ISO-8859-1'): string +{ + return function_exists('mb_convert_encoding') ? mb_convert_encoding($value, $toEncoding, 'UTF-8') : utf8_decode($value); +} + if (!method_exists(\PHPUnit\Framework\TestCase::class, 'setOutputCallback')) { ini_set('error_reporting', (string) E_ALL); set_error_handler('phpunit10ErrorHandler'); From 4139111cdc63ecbbaec970f7a60a9cfe350c1f43 Mon Sep 17 00:00:00 2001 From: Filippo Toso Date: Wed, 6 Sep 2023 17:01:42 +0200 Subject: [PATCH 161/246] Word2007 Reader : Fixed reading of Office365 DocX file --- docs/changes/1.x/1.2.0.md | 1 + src/PhpWord/Shared/XMLReader.php | 2 +- tests/PhpWordTests/Shared/XMLReaderTest.php | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index d65f27490b..1b8e1daea9 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -38,6 +38,7 @@ - Fixed PHP 8.2 deprecated about Allow access to an undefined property by [@DAdq26](https://github.com/DAdq26) in GH-2440 - Template Processor : Fixed choose dimention for Float Value by [@gdevilbat](https://github.com/gdevilbat) in GH-2449 - HTML Parser : Fix image parsing from url without extension by [@JokubasR](https://github.com/JokubasR) in GH-2459 +- Word2007 Reader : Fixed reading of Office365 DocX file by [@filippotoso](https://github.com/filippotoso) & [@lfglopes](https://github.com/lfglopes) in [#2506](https://github.com/PHPOffice/PHPWord/pull/2506) ### Miscellaneous diff --git a/src/PhpWord/Shared/XMLReader.php b/src/PhpWord/Shared/XMLReader.php index c508b3d320..1c95a64426 100644 --- a/src/PhpWord/Shared/XMLReader.php +++ b/src/PhpWord/Shared/XMLReader.php @@ -62,7 +62,7 @@ public function getDomFromZip($zipFile, $xmlFile) $zip = new ZipArchive(); $zip->open($zipFile); - $content = $zip->getFromName($xmlFile); + $content = $zip->getFromName(ltrim($xmlFile, '/')); $zip->close(); if ($content === false) { diff --git a/tests/PhpWordTests/Shared/XMLReaderTest.php b/tests/PhpWordTests/Shared/XMLReaderTest.php index 9ba8e4548b..4cbe92a5e2 100644 --- a/tests/PhpWordTests/Shared/XMLReaderTest.php +++ b/tests/PhpWordTests/Shared/XMLReaderTest.php @@ -58,6 +58,21 @@ public function testDomFromZip(): void self::assertFalse($reader->getDomFromZip($archiveFile, 'non_existing_xml_file.xml')); } + /** + * Office 365 add some slash before the path of XML file. + */ + public function testDomFromZipOffice365(): void + { + $archiveFile = __DIR__ . '/../_files/xml/reader.zip'; + + $reader = new XMLReader(); + $reader->getDomFromZip($archiveFile, '/test.xml'); + + self::assertTrue($reader->elementExists('/element/child')); + + self::assertFalse($reader->getDomFromZip($archiveFile, 'non_existing_xml_file.xml')); + } + /** * Test that read from non existing archive throws exception. */ From 913ac5a4da9daaf5ce716d4cee3e79b76f85201e Mon Sep 17 00:00:00 2001 From: Nextpage <92269411+nxtpge@users.noreply.github.com> Date: Sun, 4 Jun 2023 11:26:11 +0200 Subject: [PATCH 162/246] Template : Set a checkbox --- docs/changes/1.x/1.2.0.md | 1 + docs/usage/template.md | 25 +++ mkdocs.yml | 1 + samples/Sample_42_TemplateSetCheckbox.php | 21 +++ ...TLDefault.php => Sample_43_RTLDefault.php} | 0 .../Sample_42_TemplateSetCheckbox.docx | Bin 0 -> 13161 bytes src/PhpWord/TemplateProcessor.php | 21 +++ tests/PhpWordTests/TemplateProcessorTest.php | 153 ++++++++++++++++++ 8 files changed, 222 insertions(+) create mode 100644 samples/Sample_42_TemplateSetCheckbox.php rename samples/{Sample_52_RTLDefault.php => Sample_43_RTLDefault.php} (100%) create mode 100644 samples/resources/Sample_42_TemplateSetCheckbox.docx diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index 1b8e1daea9..d52fa01e7e 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -29,6 +29,7 @@ - PDF Writer : Added support for PageBreak - PDF Writer : Added callback for modifying the HTML - Added Support for Language, both for document overall and individual text elements +- Template : Set a checkbox by [@nxtpge](https://github.com/nxtpge) in [#2509](https://github.com/PHPOffice/PHPWord/pull/2509) ### Bug fixes diff --git a/docs/usage/template.md b/docs/usage/template.md index 17612357fd..a0c885e75e 100644 --- a/docs/usage/template.md +++ b/docs/usage/template.md @@ -38,6 +38,31 @@ You can also set multiple values by passing all of them in an array. $templateProcessor->setValues(array('firstname' => 'John', 'lastname' => 'Doe')); ``` +## setCheckbox + +Given a template containing a checkbox control with the title or tag named: + +``` clean +${checkbox} +``` +The following will check the checkbox: + +``` php +setCheckbox('checkbox', true); +``` + +!!! note annotate "To add a checkbox and set its title or tag in a template" + + 1. Go to **Developer** tab > **Controls** group + 2. Select the **Check Box Content Control** + 3. Right-click on your checkbox + 4. Click on **Properties** + 5. Set the title or the tag + + These steps may change regarding the version of Microsoft Word used. + ## setMacroOpeningChars You can define a custom opening macro. The following will set ``{#`` as the opening search pattern. diff --git a/mkdocs.yml b/mkdocs.yml index 5618dec88c..a58ebfdad6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -55,6 +55,7 @@ nav: - Comment: 'usage/elements/comment.md' - Field: 'usage/elements/field.md' - Footnote & Endnote: 'usage/elements/note.md' + - Formula: 'usage/elements/formula.md' - Image: 'usage/elements/image.md' - Line: 'usage/elements/line.md' - Link: 'usage/elements/link.md' diff --git a/samples/Sample_42_TemplateSetCheckbox.php b/samples/Sample_42_TemplateSetCheckbox.php new file mode 100644 index 0000000000..9386a191b0 --- /dev/null +++ b/samples/Sample_42_TemplateSetCheckbox.php @@ -0,0 +1,21 @@ +setCheckbox('checkbox', true); +$templateProcessor->setCheckbox('checkbox2', false); + +echo date('H:i:s'), ' Saving the result document...', EOL; +$templateProcessor->saveAs(__DIR__ . "/results/{$filename}"); + +echo getEndingNotes(['Word2007' => 'docx'], "results/{$filename}"); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/samples/Sample_52_RTLDefault.php b/samples/Sample_43_RTLDefault.php similarity index 100% rename from samples/Sample_52_RTLDefault.php rename to samples/Sample_43_RTLDefault.php diff --git a/samples/resources/Sample_42_TemplateSetCheckbox.docx b/samples/resources/Sample_42_TemplateSetCheckbox.docx new file mode 100644 index 0000000000000000000000000000000000000000..9abc486b697bfe11d0ec3a17f82539d61ead58fa GIT binary patch literal 13161 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 Hzn%R*;!B@5 literal 0 HcmV?d00001 diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index f740212a2c..1ad901d480 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -372,6 +372,27 @@ public function setValues(array $values): void } } + public function setCheckbox(string $search, bool $checked): void + { + $search = static::ensureMacroCompleted($search); + $blockType = 'w:sdt'; + + $where = $this->findContainingXmlBlockForMacro($search, $blockType); + if (!is_array($where)) { + return; + } + + $block = $this->getSlice($where['start'], $where['end']); + + $val = $checked ? '1' : '0'; + $block = preg_replace('/()/', '$1"' . $val . '"$2', $block); + + $text = $checked ? '☒' : '☐'; + $block = preg_replace('/().*?(<\/w:t>)/', '$1' . $text . '$2', $block); + + $this->replaceXmlBlock($search, $block, $blockType); + } + /** * @param string $search */ diff --git a/tests/PhpWordTests/TemplateProcessorTest.php b/tests/PhpWordTests/TemplateProcessorTest.php index 843ac798e2..f2d2cfbf13 100644 --- a/tests/PhpWordTests/TemplateProcessorTest.php +++ b/tests/PhpWordTests/TemplateProcessorTest.php @@ -610,6 +610,159 @@ public function testSetValuesWithCustomMacro(): void self::assertStringContainsString('Hello John Doe', $templateProcessor->getMainPart()); } + /** + * @covers ::setCheckbox + */ + public function testSetCheckbox(): void + { + $mainPart = ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + '; + + $result = ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + '; + + $templateProcessor = new TestableTemplateProcesor($mainPart); + $templateProcessor->setCheckbox('checkbox', true); + $templateProcessor->setCheckbox('checkbox2', false); + + self::assertEquals(preg_replace('/>\s+<', $result), preg_replace('/>\s+<', $templateProcessor->getMainPart())); + } + + /** + * @covers ::setCheckbox + */ + public function testSetCheckboxWithCustomMacro(): void + { + $mainPart = ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + '; + + $result = ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + '; + + $templateProcessor = new TestableTemplateProcesor($mainPart); + $templateProcessor->setMacroChars('{#', '#}'); + $templateProcessor->setCheckbox('checkbox', true); + $templateProcessor->setCheckbox('checkbox2', false); + + self::assertEquals(preg_replace('/>\s+<', $result), preg_replace('/>\s+<', $templateProcessor->getMainPart())); + } + /** * @covers ::setImageValue */ From a209906f3d64d4327afbf09b49c6466c209e13db Mon Sep 17 00:00:00 2001 From: milkyway Date: Tue, 7 Nov 2023 07:11:06 +0100 Subject: [PATCH 163/246] Added field 'FILENAME' --- docs/changes/1.x/1.2.0.md | 1 + docs/usage/elements/field.md | 3 +- samples/Sample_27_Field.php | 3 + src/PhpWord/Element/Field.php | 6 ++ src/PhpWord/Writer/ODText/Element/Field.php | 15 ++++- src/PhpWord/Writer/RTF/Element/Field.php | 19 +++++- src/PhpWord/Writer/Word2007/Element/Field.php | 22 ++++--- .../Writer/ODText/Element/FieldTest.php | 64 +++++++++++++++++++ tests/PhpWordTests/Writer/RTF/ElementTest.php | 18 ++++++ .../Writer/Word2007/ElementTest.php | 38 +++++++++++ 10 files changed, 175 insertions(+), 14 deletions(-) create mode 100644 tests/PhpWordTests/Writer/ODText/Element/FieldTest.php diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index d52fa01e7e..c7ad030b3e 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -30,6 +30,7 @@ - PDF Writer : Added callback for modifying the HTML - Added Support for Language, both for document overall and individual text elements - Template : Set a checkbox by [@nxtpge](https://github.com/nxtpge) in [#2509](https://github.com/PHPOffice/PHPWord/pull/2509) +- ODText / RTF / Word2007 Writer : Add field FILENAME by [@milkyway-git](https://github.com/milkyway-git) in [#2510](https://github.com/PHPOffice/PHPWord/pull/2510) ### Bug fixes diff --git a/docs/usage/elements/field.md b/docs/usage/elements/field.md index 10492cc742..fe8e9756fc 100644 --- a/docs/usage/elements/field.md +++ b/docs/usage/elements/field.md @@ -7,6 +7,7 @@ Currently the following fields are supported: - DATE - XE - INDEX +- FILENAME ``` php addField('XE', array(), array(), $fieldText); //this actually adds the index $section->addField('INDEX', array(), array('\\e " " \\h "A" \\c "3"'), 'right click to update index'); -``` \ No newline at end of file +``` diff --git a/samples/Sample_27_Field.php b/samples/Sample_27_Field.php index d250946169..fd441ba022 100644 --- a/samples/Sample_27_Field.php +++ b/samples/Sample_27_Field.php @@ -26,6 +26,9 @@ $section->addText('Number of pages field:'); $section->addField('NUMPAGES', ['numformat' => '0,00', 'format' => 'Arabic'], ['PreserveFormat']); + +$section->addText('Filename field:'); +$section->addField('FILENAME', ['format' => 'Upper'], ['Path', 'PreserveFormat']); $section->addTextBreak(); $textrun = $section->addTextRun(); diff --git a/src/PhpWord/Element/Field.php b/src/PhpWord/Element/Field.php index 68a5296d7a..b371bb80d7 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -85,6 +85,12 @@ class Field extends AbstractElement 'properties' => ['StyleIdentifier' => ''], 'options' => ['PreserveFormat'], ], + 'FILENAME' => [ + 'properties' => [ + 'format' => ['Upper', 'Lower', 'FirstCap', 'Caps'], + ], + 'options' => ['Path', 'PreserveFormat'], + ], ]; /** diff --git a/src/PhpWord/Writer/ODText/Element/Field.php b/src/PhpWord/Writer/ODText/Element/Field.php index 1bfdbc9301..46f62b0f02 100644 --- a/src/PhpWord/Writer/ODText/Element/Field.php +++ b/src/PhpWord/Writer/ODText/Element/Field.php @@ -15,7 +15,7 @@ * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ // Not fully implemented -// - supports only PAGE and NUMPAGES +// - supports only PAGE, NUMPAGES, DATE and FILENAME // - supports only default formats and options // - supports style only if specified by name // - spaces before and after field may be dropped @@ -44,6 +44,7 @@ public function write(): void case 'date': case 'page': case 'numpages': + case 'filename': $this->writeDefault($element, $type); break; @@ -78,6 +79,18 @@ private function writeDefault(\PhpOffice\PhpWord\Element\Field $element, $type): $xmlWriter->startElement('text:page-count'); $xmlWriter->endElement(); + break; + case 'filename': + $xmlWriter->startElement('text:file-name'); + $xmlWriter->writeAttribute('text:fixed', 'false'); + $options = $element->getOptions(); + if ($options != null && in_array('Path', $options)) { + $xmlWriter->writeAttribute('text:display', 'full'); + } else { + $xmlWriter->writeAttribute('text:display', 'name'); + } + $xmlWriter->endElement(); + break; } $xmlWriter->endElement(); // text:span diff --git a/src/PhpWord/Writer/RTF/Element/Field.php b/src/PhpWord/Writer/RTF/Element/Field.php index 37f203aca8..34024f5e51 100644 --- a/src/PhpWord/Writer/RTF/Element/Field.php +++ b/src/PhpWord/Writer/RTF/Element/Field.php @@ -17,10 +17,12 @@ namespace PhpOffice\PhpWord\Writer\RTF\Element; +use PhpOffice\PhpWord\Element\Field as ElementField; + /** * Field element writer. * - * Note: for now, only date, page and numpages fields are implemented for RTF. + * Note: for now, only date, page, numpages and filename fields are implemented for RTF. */ class Field extends Text { @@ -30,7 +32,7 @@ class Field extends Text public function write() { $element = $this->element; - if (!$element instanceof \PhpOffice\PhpWord\Element\Field) { + if (!$element instanceof ElementField) { return; } @@ -66,7 +68,18 @@ protected function writeNumpages() return 'NUMPAGES'; } - protected function writeDate(\PhpOffice\PhpWord\Element\Field $element) + protected function writeFilename(ElementField $element): string + { + $content = 'FILENAME'; + $options = $element->getOptions(); + if ($options != null && in_array('Path', $options)) { + $content .= ' \\\\p'; + } + + return $content; + } + + protected function writeDate(ElementField $element) { $content = ''; $content .= 'DATE'; diff --git a/src/PhpWord/Writer/Word2007/Element/Field.php b/src/PhpWord/Writer/Word2007/Element/Field.php index 6fdb48b0f4..4d7c2a0b46 100644 --- a/src/PhpWord/Writer/Word2007/Element/Field.php +++ b/src/PhpWord/Writer/Word2007/Element/Field.php @@ -166,15 +166,15 @@ private function buildPropertiesAndOptions(\PhpOffice\PhpWord\Element\Field $ele foreach ($properties as $propkey => $propval) { switch ($propkey) { case 'format': - $propertiesAndOptions .= '\* ' . $propval . ' '; + $propertiesAndOptions .= '\\* ' . $propval . ' '; break; case 'numformat': - $propertiesAndOptions .= '\# ' . $propval . ' '; + $propertiesAndOptions .= '\\# ' . $propval . ' '; break; case 'dateformat': - $propertiesAndOptions .= '\@ "' . $propval . '" '; + $propertiesAndOptions .= '\\@ "' . $propval . '" '; break; case 'macroname': @@ -192,27 +192,31 @@ private function buildPropertiesAndOptions(\PhpOffice\PhpWord\Element\Field $ele foreach ($options as $option) { switch ($option) { case 'PreserveFormat': - $propertiesAndOptions .= '\* MERGEFORMAT '; + $propertiesAndOptions .= '\\* MERGEFORMAT '; break; case 'LunarCalendar': - $propertiesAndOptions .= '\h '; + $propertiesAndOptions .= '\\h '; break; case 'SakaEraCalendar': - $propertiesAndOptions .= '\s '; + $propertiesAndOptions .= '\\s '; break; case 'LastUsedFormat': - $propertiesAndOptions .= '\l '; + $propertiesAndOptions .= '\\l '; break; case 'Bold': - $propertiesAndOptions .= '\b '; + $propertiesAndOptions .= '\\b '; break; case 'Italic': - $propertiesAndOptions .= '\i '; + $propertiesAndOptions .= '\\i '; + + break; + case 'Path': + $propertiesAndOptions .= '\\p '; break; default: diff --git a/tests/PhpWordTests/Writer/ODText/Element/FieldTest.php b/tests/PhpWordTests/Writer/ODText/Element/FieldTest.php new file mode 100644 index 0000000000..2d9bb7c87d --- /dev/null +++ b/tests/PhpWordTests/Writer/ODText/Element/FieldTest.php @@ -0,0 +1,64 @@ +addSection(); + $section->addField('FILENAME'); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + + self::assertTrue($doc->elementExists('/office:document-content/office:body/office:text/text:section/text:span/text:file-name')); + self::assertEquals('false', $doc->getElementAttribute('/office:document-content/office:body/office:text/text:section/text:span/text:file-name', 'text:fixed')); + self::assertEquals('name', $doc->getElementAttribute('/office:document-content/office:body/office:text/text:section/text:span/text:file-name', 'text:display')); + } + + public function testFieldFilenameOptionPath(): void + { + $phpWord = new PhpWord(); + + $section = $phpWord->addSection(); + $section->addField('FILENAME', [], ['Path']); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + + self::assertTrue($doc->elementExists('/office:document-content/office:body/office:text/text:section/text:span/text:file-name')); + self::assertEquals('false', $doc->getElementAttribute('/office:document-content/office:body/office:text/text:section/text:span/text:file-name', 'text:fixed')); + self::assertEquals('full', $doc->getElementAttribute('/office:document-content/office:body/office:text/text:section/text:span/text:file-name', 'text:display')); + } +} diff --git a/tests/PhpWordTests/Writer/RTF/ElementTest.php b/tests/PhpWordTests/Writer/RTF/ElementTest.php index 7c1549371d..fd0842cd6c 100644 --- a/tests/PhpWordTests/Writer/RTF/ElementTest.php +++ b/tests/PhpWordTests/Writer/RTF/ElementTest.php @@ -45,6 +45,24 @@ public function testUnmatchedElements(): void } } + public function testFilenameField(): void + { + $parentWriter = new RTF(); + $element = new \PhpOffice\PhpWord\Element\Field('FILENAME'); + $field = new \PhpOffice\PhpWord\Writer\RTF\Element\Field($parentWriter, $element); + + self::assertEquals("{\\field{\\*\\fldinst FILENAME}{\\fldrslt}}\\par\n", $this->removeCr($field)); + } + + public function testFilenameFieldOptionsPath(): void + { + $parentWriter = new RTF(); + $element = new \PhpOffice\PhpWord\Element\Field('FILENAME', [], ['Path']); + $field = new \PhpOffice\PhpWord\Writer\RTF\Element\Field($parentWriter, $element); + + self::assertEquals("{\\field{\\*\\fldinst FILENAME \\\\p}{\\fldrslt}}\\par\n", $this->removeCr($field)); + } + public function testPageField(): void { $parentWriter = new RTF(); diff --git a/tests/PhpWordTests/Writer/Word2007/ElementTest.php b/tests/PhpWordTests/Writer/Word2007/ElementTest.php index 3bcd842fbd..3ed3e7a91b 100644 --- a/tests/PhpWordTests/Writer/Word2007/ElementTest.php +++ b/tests/PhpWordTests/Writer/Word2007/ElementTest.php @@ -306,6 +306,44 @@ public function testStyledFieldElement(): void self::assertEquals($stnam, $doc->getElementAttribute($sty . '/w:rStyle', 'w:val')); } + public function testFieldElementFilename(): void + { + $phpWord = new PhpWord(); + $stnam = 'h1'; + $phpWord->addFontStyle($stnam, ['name' => 'Courier New', 'size' => 8]); + $section = $phpWord->addSection(); + + $fld = $section->addField('FILENAME'); + $fld->setFontStyle($stnam); + $doc = TestHelperDOCX::getDocument($phpWord); + + $element = '/w:document/w:body/w:p/w:r[2]/w:instrText'; + self::assertTrue($doc->elementExists($element)); + self::assertEquals(' FILENAME ', $doc->getElement($element)->textContent); + $sty = '/w:document/w:body/w:p/w:r[2]/w:rPr'; + self::assertTrue($doc->elementExists($sty)); + self::assertEquals($stnam, $doc->getElementAttribute($sty . '/w:rStyle', 'w:val')); + } + + public function testFieldElementFilenameOptionsPath(): void + { + $phpWord = new PhpWord(); + $stnam = 'h1'; + $phpWord->addFontStyle($stnam, ['name' => 'Courier New', 'size' => 8]); + $section = $phpWord->addSection(); + + $fld = $section->addField('FILENAME', [], ['Path']); + $fld->setFontStyle($stnam); + $doc = TestHelperDOCX::getDocument($phpWord); + + $element = '/w:document/w:body/w:p/w:r[2]/w:instrText'; + self::assertTrue($doc->elementExists($element)); + self::assertEquals(' FILENAME \p ', $doc->getElement($element)->textContent); + $sty = '/w:document/w:body/w:p/w:r[2]/w:rPr'; + self::assertTrue($doc->elementExists($sty)); + self::assertEquals($stnam, $doc->getElementAttribute($sty . '/w:rStyle', 'w:val')); + } + public function testFieldElementWithComplexText(): void { $phpWord = new PhpWord(); From d65be9830f9bdb00ccbcc737b5af4726859d4f9c Mon Sep 17 00:00:00 2001 From: Ethan Merchant <49330364+spatialfree@users.noreply.github.com> Date: Tue, 24 Oct 2023 11:48:56 -0400 Subject: [PATCH 164/246] Word2007 Reader : Check for null on $fontDefaultStyle --- docs/changes/1.x/1.2.0.md | 1 + src/PhpWord/Reader/Word2007/Styles.php | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index c7ad030b3e..9900e7b663 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -41,6 +41,7 @@ - Template Processor : Fixed choose dimention for Float Value by [@gdevilbat](https://github.com/gdevilbat) in GH-2449 - HTML Parser : Fix image parsing from url without extension by [@JokubasR](https://github.com/JokubasR) in GH-2459 - Word2007 Reader : Fixed reading of Office365 DocX file by [@filippotoso](https://github.com/filippotoso) & [@lfglopes](https://github.com/lfglopes) in [#2506](https://github.com/PHPOffice/PHPWord/pull/2506) +- Word2007 Reader : Check for null on $fontDefaultStyle by [@spatialfree](https://github.com/spatialfree) in [#2513](https://github.com/PHPOffice/PHPWord/pull/2513) ### Miscellaneous diff --git a/src/PhpWord/Reader/Word2007/Styles.php b/src/PhpWord/Reader/Word2007/Styles.php index 4566398ad2..760adf9493 100644 --- a/src/PhpWord/Reader/Word2007/Styles.php +++ b/src/PhpWord/Reader/Word2007/Styles.php @@ -39,14 +39,16 @@ public function read(PhpWord $phpWord): void $fontDefaults = $xmlReader->getElement('w:docDefaults/w:rPrDefault'); if ($fontDefaults !== null) { $fontDefaultStyle = $this->readFontStyle($xmlReader, $fontDefaults); - if (array_key_exists('name', $fontDefaultStyle)) { - $phpWord->setDefaultFontName($fontDefaultStyle['name']); - } - if (array_key_exists('size', $fontDefaultStyle)) { - $phpWord->setDefaultFontSize($fontDefaultStyle['size']); - } - if (array_key_exists('lang', $fontDefaultStyle)) { - $phpWord->getSettings()->setThemeFontLang(new Language($fontDefaultStyle['lang'])); + if ($fontDefaultStyle) { + if (array_key_exists('name', $fontDefaultStyle)) { + $phpWord->setDefaultFontName($fontDefaultStyle['name']); + } + if (array_key_exists('size', $fontDefaultStyle)) { + $phpWord->setDefaultFontSize($fontDefaultStyle['size']); + } + if (array_key_exists('lang', $fontDefaultStyle)) { + $phpWord->getSettings()->setThemeFontLang(new Language($fontDefaultStyle['lang'])); + } } } From bdcd10492165a14cee552586819c70541da5c4d3 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Wed, 22 Nov 2023 09:20:24 -0800 Subject: [PATCH 165/246] Improve ODText Content Reader Fix #2493. There is much that the ODT Reader ignores. This change adds support for the `text:section`, `text:span`, `text:s`, and `text:tab` tags, thereby handling multiple sections, text runs, tab characters, and multiple spaces. There will still be many omissions (e.g. styles and tables), but you will now often be able to access the text content of valid ODT documents. The issue suggests variations in a simple file created on its own by LibreOffice, and a similar file created by PhpWord. Both are unit-tested. A `getText` method is added to TextRun to facilitate testing (and can be useful on its own). It will return the concatenated texts of all elements of the text run. --- docs/changes/1.x/1.2.0.md | 1 + phpstan-baseline.neon | 5 -- src/PhpWord/Element/TextRun.php | 12 +++ src/PhpWord/Reader/ODText/Content.php | 81 +++++++++++++++-- .../Reader/ODText/ODTextSectionTest.php | 83 ++++++++++++++++++ .../_files/documents/word.2493.nosection.odt | Bin 0 -> 3066 bytes 6 files changed, 171 insertions(+), 11 deletions(-) create mode 100644 tests/PhpWordTests/Reader/ODText/ODTextSectionTest.php create mode 100644 tests/PhpWordTests/_files/documents/word.2493.nosection.odt diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index 9900e7b663..30d3b35202 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -31,6 +31,7 @@ - Added Support for Language, both for document overall and individual text elements - Template : Set a checkbox by [@nxtpge](https://github.com/nxtpge) in [#2509](https://github.com/PHPOffice/PHPWord/pull/2509) - ODText / RTF / Word2007 Writer : Add field FILENAME by [@milkyway-git](https://github.com/milkyway-git) in [#2510](https://github.com/PHPOffice/PHPWord/pull/2510) +- ODText Reader : Improve Section Reader by [@oleibman](https://github.com/oleibman) in [#2507](https://github.com/PHPOffice/PHPWord/pull/2507) ### Bug fixes diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index e7918d9174..2e44745b3d 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -165,11 +165,6 @@ parameters: count: 1 path: src/PhpWord/Reader/HTML.php - - - message: "#^Call to an undefined method DOMNode\\:\\:getAttribute\\(\\)\\.$#" - count: 2 - path: src/PhpWord/Reader/ODText/Content.php - - message: "#^Offset 'textNodes' on array\\{changed\\: PhpOffice\\\\PhpWord\\\\Element\\\\TrackChange, textNodes\\: DOMNodeList\\\\} in isset\\(\\) always exists and is not nullable\\.$#" count: 1 diff --git a/src/PhpWord/Element/TextRun.php b/src/PhpWord/Element/TextRun.php index fc8727592a..33c55f6584 100644 --- a/src/PhpWord/Element/TextRun.php +++ b/src/PhpWord/Element/TextRun.php @@ -78,4 +78,16 @@ public function setParagraphStyle($style = null) return $this->paragraphStyle; } + + public function getText(): string + { + $outstr = ''; + foreach ($this->getElements() as $element) { + if ($element instanceof Text) { + $outstr .= $element->getText(); + } + } + + return $outstr; + } } diff --git a/src/PhpWord/Reader/ODText/Content.php b/src/PhpWord/Reader/ODText/Content.php index 45cb0704db..15c76c27b9 100644 --- a/src/PhpWord/Reader/ODText/Content.php +++ b/src/PhpWord/Reader/ODText/Content.php @@ -18,7 +18,10 @@ namespace PhpOffice\PhpWord\Reader\ODText; use DateTime; +use DOMElement; +use DOMNodeList; use PhpOffice\Math\Reader\MathML; +use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Shared\XMLReader; @@ -30,6 +33,9 @@ */ class Content extends AbstractPart { + /** @var ?Section */ + private $section; + /** * Read content.xml. */ @@ -41,17 +47,28 @@ public function read(PhpWord $phpWord): void $trackedChanges = []; $nodes = $xmlReader->getElements('office:body/office:text/*'); + $this->section = null; + $this->processNodes($nodes, $xmlReader, $phpWord); + $this->section = null; + } + + /** @param DOMNodeList $nodes */ + public function processNodes(DOMNodeList $nodes, XMLReader $xmlReader, PhpWord $phpWord): void + { if ($nodes->length > 0) { - $section = $phpWord->addSection(); foreach ($nodes as $node) { // $styleName = $xmlReader->getAttribute('text:style-name', $node); switch ($node->nodeName) { case 'text:h': // Heading $depth = $xmlReader->getAttribute('text:outline-level', $node); - $section->addTitle($node->nodeValue, $depth); + $this->getSection($phpWord)->addTitle($node->nodeValue, $depth); break; case 'text:p': // Paragraph + $styleName = $xmlReader->getAttribute('text:style-name', $node); + if (substr($styleName, 0, 2) === 'SB') { + break; + } $element = $xmlReader->getElement('draw:frame/draw:object', $node); if ($element) { $mathFile = str_replace('./', '', $element->getAttribute('xlink:href')) . '/content.xml'; @@ -65,11 +82,13 @@ public function read(PhpWord $phpWord): void $reader = new MathML(); $math = $reader->read($mathXML); - $section->addFormula($math); + $this->getSection($phpWord)->addFormula($math); } } } else { $children = $node->childNodes; + $spans = false; + /** @var DOMElement $child */ foreach ($children as $child) { switch ($child->nodeName) { case 'text:change-start': @@ -89,16 +108,49 @@ public function read(PhpWord $phpWord): void $changed = $trackedChanges[$changeId]; } + break; + case 'text:span': + $spans = true; + break; } } - $element = $section->addText($node->nodeValue); + if ($spans) { + $element = $this->getSection($phpWord)->addTextRun(); + foreach ($children as $child) { + switch ($child->nodeName) { + case 'text:span': + /** @var DOMElement $child2 */ + foreach ($child->childNodes as $child2) { + switch ($child2->nodeName) { + case '#text': + $element->addText($child2->nodeValue); + + break; + case 'text:tab': + $element->addText("\t"); + + break; + case 'text:s': + $spaces = (int) $child2->getAttribute('text:c') ?: 1; + $element->addText(str_repeat(' ', $spaces)); + + break; + } + } + + break; + } + } + } else { + $element = $this->getSection($phpWord)->addText($node->nodeValue); + } if (isset($changed) && is_array($changed)) { $element->setTrackChange($changed['changed']); if (isset($changed['textNodes'])) { foreach ($changed['textNodes'] as $changedNode) { - $element = $section->addText($changedNode->nodeValue); + $element = $this->getSection($phpWord)->addText($changedNode->nodeValue); $element->setTrackChange($changed['changed']); } } @@ -110,7 +162,7 @@ public function read(PhpWord $phpWord): void $listItems = $xmlReader->getElements('text:list-item/text:p', $node); foreach ($listItems as $listItem) { // $listStyleName = $xmlReader->getAttribute('text:style-name', $listItem); - $section->addListItem($listItem->nodeValue, 0); + $this->getSection($phpWord)->addListItem($listItem->nodeValue, 0); } break; @@ -129,9 +181,26 @@ public function read(PhpWord $phpWord): void $trackedChanges[$changedRegion->getAttribute('text:id')] = ['changed' => $changed, 'textNodes' => $textNodes]; } + break; + case 'text:section': // Section + // $sectionStyleName = $xmlReader->getAttribute('text:style-name', $listItem); + $this->section = $phpWord->addSection(); + $children = $node->childNodes; + $this->processNodes($children, $xmlReader, $phpWord); + break; } } } } + + private function getSection(PhpWord $phpWord): Section + { + $section = $this->section; + if ($section === null) { + $section = $this->section = $phpWord->addSection(); + } + + return $section; + } } diff --git a/tests/PhpWordTests/Reader/ODText/ODTextSectionTest.php b/tests/PhpWordTests/Reader/ODText/ODTextSectionTest.php new file mode 100644 index 0000000000..0a1a4512db --- /dev/null +++ b/tests/PhpWordTests/Reader/ODText/ODTextSectionTest.php @@ -0,0 +1,83 @@ +filename !== '') { + unlink($this->filename); + $this->filename = ''; + } + } + + public function testWriteThenReadSection(): void + { + $dir = 'tests/PhpWordTests/_files'; + Settings::setOutputEscapingEnabled(true); + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $inputText = ['days', 'monday', 'tuesday']; + $inputText[] = "Tab\tthen two spaces then done."; + foreach ($inputText as $text) { + $section->addText($text); + } + $writer = IOFactory::createWriter($phpWord, 'ODText'); + $this->filename = "$dir/sectiontest.odt"; + $writer->save($this->filename); + + $reader = IOFactory::createReader('ODText'); + $phpWord2 = $reader->load($this->filename); + $outputText = []; + foreach ($phpWord2->getSections() as $section) { + foreach ($section->getElements() as $element) { + if (is_object($element) && method_exists($element, 'getText')) { + $outputText[] = $element->getText(); + } + } + } + self::assertSame($inputText, $outputText); + } + + public function testReadNoSections(): void + { + $dir = 'tests/PhpWordTests/_files/documents'; + $inputText = ['days', 'monday', 'tuesday']; + + $reader = IOFactory::createReader('ODText'); + $filename = "$dir/word.2493.nosection.odt"; + $phpWord2 = $reader->load($filename); + $outputText = []; + foreach ($phpWord2->getSections() as $section) { + foreach ($section->getElements() as $element) { + if (is_object($element) && method_exists($element, 'getText')) { + $outputText[] = $element->getText(); + } + } + } + self::assertSame($inputText, $outputText); + } +} diff --git a/tests/PhpWordTests/_files/documents/word.2493.nosection.odt b/tests/PhpWordTests/_files/documents/word.2493.nosection.odt new file mode 100644 index 0000000000000000000000000000000000000000..eb0fa2076433c91a29fd7a2b4db0762c80c7e09d GIT binary patch literal 3066 zcmZ`*2{e>#8-9@`OO&OBO8Bxb`Nvjh?1VxllqE4VGPW7Z*o~!#A;!M%24l-MmZXeq zW6ds2L?mR1QOQ62|98Is>-^vSp6A@}dCz@4=Y8J$z3%HW(x*Gd1sp~{05!Ajlw}pB z-XAU|>Vm`IP$bF?YU}3a470OE!dzXXy;8}zdZL>)v^XN`h zu@?kx0juovLPLTy>ov&lD>K)zY>kg^v;tYEfh`B+`LO06`Q+zxqYgBKO;vs20;RT91F9;kdI!~Ccdy|}CJ8SloH!4~zCtfIxLDIpt% ztoO=uc)~w#P2>t$JUKs_>x`DTdJTf;Qr|mq)%aYC&ecW*v9A=LWFhRAYK;o8*LC;H z4PU#J%3_P(yf|IU6thsBZ(>W@B!eDp$5moK7x=2H$Si+`lOmewRV6u%f7(a2!M<2*6PZ~^} zqDiZtqV|4iC}e1JW$72e@_@S>Y^Bfpy!PN}^*&px^rji#myRFSS2*K&s=U1KYg{fn z*j?VBU&nz}Qmhzt49-2Zf3GZ>-;#<`9a)rFx>B6BhXBts7z#ztH{UTq4L{epy|{4k zb^X?AzV6f-#S7cSnEfxpW9ulH7$)M3qK>D+x1Cg*apN(dZ)SDm`>}apN3@yZb&$r- z=!pq&`HZ*2ibl4HZoB6(r7?bqzYu(@do-XG`I{I}52$B1C*QM3WV~mTBX^8yt^Cb>pAN*$ZoVGA7l_`r7O7uT*)M-)0AHU6MW|u>!?~rywoj{VjkG#&532;s z`5F|-E1DfIUdMMnzy0xT#pk(Zh+H;GrN|TCv^T+ll=ZICwnR(4)D~GDyhQ$EVgj9Z z$Z!zX_qn>1 zLfNJZELgg7O|bffeDa?ss~sbGtDeD=NDZ+ETwa{`v{_}>!1>*;Prk1yZcoxgC*GAS zkzncpyGs^)KDS-lJm5NH^#eclqxB;=d~pQmS)fx)+UFi9636cSz!u_0bGk)JQxlWK zi^M z4kbd3=fc^l4-`!A4+z5WX8FOzgF_VpAFti~rtYo% zRq(n9A$PQ%Kdc~~*62<05;!C>A(lP1t?s1UuL9wlV#`7+TM5fhrPAunD_cRrgqKBo zWt%d%YH=K@m4%7rbqQXiIr;KIP>H_Og!T!1SH- zfA0?1)>{#L3;?#NGmn`%^AJdsGZb;uAG2x9v^+<^y4e}#@4CIoR!GTm1rcU0kwKD1 zfrq;>)l2>*#f-R79U4aP_gZUtfvMJ%Zq}05Kbc5kj1`b;W z5dP3&32jH!K=F-}i)nst&hQTpKApSvr7P*eqRtL^A`LdxC+B4@fpiWuMZ`#J$K?wU z#KfKUAUvnr7X|`M%fL)Td6531gfGscdqpskkd_Kn3cHB{I<0~W{ZmSC8kh8yp}hz3EU3Vl2d`* z<<*v z(r>z2kU^l#DRsKZb0X&)FL>ejE(#zg(R&Pn-8p&7P^y|ajQ%mDO!J*4%V;uEWpz`Q zpU-xXTa=q_w}+EeYj;m8_EBLS4SGBb7eT36ydh%QaA%w&!*{Pl%lx!7=x1`TEyO~a zlM;8%ZjCd}nk-&eJ^Q|Gr;_d|_VRT#{e#|D_WbCMyc(8Kdc< zUEn%*%8Ku5LFRgs&>DlW@cP+2r7YgCRKmdMwmf*x#_7jU&Uaz$Mw98_u`}}bSf3;%xxF>e}*>IS0+tgFS;!ke`lip z(XhC9BE89Q?-KrX^%B5PI#|L1s|$=&ClDw1Y3^gm5+Wi$jCoi3Wxcp{E_KO0iQ8V> z+YM=g`hw;|4s^6IWdLyAm7)1-_d@q-8Li=0$p(6wU@KduPb^VVqWj=Zc05rfEAhgkuZ Date: Sun, 17 Dec 2023 00:20:25 -0800 Subject: [PATCH 166/246] Correct Font Size Calculated by MsDoc Reader Fix #2526. Most of that issue has already been fixed. The one remaining problem was a deprecation message handling font size. The code used `dechex($operand / 2)`, and issued the deprecation message whenever `$operand` was odd because `dechex` is designed only for integer conversion. `$operand` is actually 2 times the point size, so it will be odd only when the point size is some integer plus half a point (no other fractions are allowed). At any rate, it seems that `dechex` should not be used here in the first place; font size is a numeric value, not a hex string. There are many problems with MsDoc Reader at the moment. This PR is narrowly focused on the problem at hand. Its test is, at least, more detailed than the existing MsDoc Reader test, which does nothing more than confirm that read successfully creates a PhpWord object. The new test verifies that the font size is as expected, but does not validate any other aspect of the read. --- src/PhpWord/Reader/MsDoc.php | 2 +- tests/PhpWordTests/Reader/MsDocTest.php | 16 ++++++++++++++++ .../PhpWordTests/_files/documents/word.2526.doc | Bin 0 -> 24576 bytes 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 tests/PhpWordTests/_files/documents/word.2526.doc diff --git a/src/PhpWord/Reader/MsDoc.php b/src/PhpWord/Reader/MsDoc.php index 4cf755e3fa..2599e42350 100644 --- a/src/PhpWord/Reader/MsDoc.php +++ b/src/PhpWord/Reader/MsDoc.php @@ -1871,7 +1871,7 @@ private function readPrl($data, $pos, $cbNum) break; // sprmCHps case 0x43: - $oStylePrl->styleFont['size'] = dechex($operand / 2); + $oStylePrl->styleFont['size'] = $operand / 2; break; // sprmCIss diff --git a/tests/PhpWordTests/Reader/MsDocTest.php b/tests/PhpWordTests/Reader/MsDocTest.php index deb8b9badd..f5f75ab790 100644 --- a/tests/PhpWordTests/Reader/MsDocTest.php +++ b/tests/PhpWordTests/Reader/MsDocTest.php @@ -60,6 +60,22 @@ public function testLoad(): void self::assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); } + public function testLoadHalfPointFont(): void + { + $filename = __DIR__ . '/../_files/documents/word.2526.doc'; + $phpWord = IOFactory::load($filename, 'MsDoc'); + $sections = $phpWord->getSections(); + self::assertCount(1, $sections); + $elements = $sections[0]->getElements(); + self::assertArrayHasKey(0, $elements); + $element0 = $elements[0]; + if (method_exists($element0, 'getFontStyle')) { + self::assertSame(19.5, $element0->getFontStyle()->getSize()); + } else { + self::fail('Unexpected no font style for first element'); + } + } + /** * Test exception on not existing file. */ diff --git a/tests/PhpWordTests/_files/documents/word.2526.doc b/tests/PhpWordTests/_files/documents/word.2526.doc new file mode 100644 index 0000000000000000000000000000000000000000..94fc5ed8fd566e4cdaa44b6f1eb8b520773454d1 GIT binary patch literal 24576 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 is)sro_y=Ph`kir6W13Ib^PNe3&!RC Date: Sun, 17 Dec 2023 14:03:54 -0800 Subject: [PATCH 167/246] Suggestions from @Progi1984 --- docs/changes/1.x/1.3.0.md | 14 ++++++++++++++ tests/PhpWordTests/Reader/MsDocTest.php | 2 +- .../{word.2526.doc => reader.font-halfpoint.doc} | Bin 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 docs/changes/1.x/1.3.0.md rename tests/PhpWordTests/_files/documents/{word.2526.doc => reader.font-halfpoint.doc} (100%) diff --git a/docs/changes/1.x/1.3.0.md b/docs/changes/1.x/1.3.0.md new file mode 100644 index 0000000000..e85d9ff892 --- /dev/null +++ b/docs/changes/1.x/1.3.0.md @@ -0,0 +1,14 @@ +# [1.2.0](https://github.com/PHPOffice/PHPWord/tree/1.2.0) (WIP) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.2.0...1.3.0) + +## Enhancements + +### Bug fixes + +- MsDoc Reader : Correct Font Size Calculation by [@oleibman](https://github.com/oleibman) Issue [#2526](https://github.com/PHPOffice/PHPWord/issues/2526) PR [#2531](https://github.com/PHPOffice/PHPWord/pull/2531) + +### Miscellaneous + + +### BC Breaks diff --git a/tests/PhpWordTests/Reader/MsDocTest.php b/tests/PhpWordTests/Reader/MsDocTest.php index f5f75ab790..cf4db6d0d9 100644 --- a/tests/PhpWordTests/Reader/MsDocTest.php +++ b/tests/PhpWordTests/Reader/MsDocTest.php @@ -62,7 +62,7 @@ public function testLoad(): void public function testLoadHalfPointFont(): void { - $filename = __DIR__ . '/../_files/documents/word.2526.doc'; + $filename = __DIR__ . '/../_files/documents/reader.font-halfpoint.doc '; $phpWord = IOFactory::load($filename, 'MsDoc'); $sections = $phpWord->getSections(); self::assertCount(1, $sections); diff --git a/tests/PhpWordTests/_files/documents/word.2526.doc b/tests/PhpWordTests/_files/documents/reader.font-halfpoint.doc similarity index 100% rename from tests/PhpWordTests/_files/documents/word.2526.doc rename to tests/PhpWordTests/_files/documents/reader.font-halfpoint.doc From ea7a670589a3a1775fe07f9e69350f012985787c Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Sun, 17 Dec 2023 14:09:32 -0800 Subject: [PATCH 168/246] Typo Tolerated By Windows but Not By Unix --- tests/PhpWordTests/Reader/MsDocTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PhpWordTests/Reader/MsDocTest.php b/tests/PhpWordTests/Reader/MsDocTest.php index cf4db6d0d9..b62d545de0 100644 --- a/tests/PhpWordTests/Reader/MsDocTest.php +++ b/tests/PhpWordTests/Reader/MsDocTest.php @@ -62,7 +62,7 @@ public function testLoad(): void public function testLoadHalfPointFont(): void { - $filename = __DIR__ . '/../_files/documents/reader.font-halfpoint.doc '; + $filename = __DIR__ . '/../_files/documents/reader.font-halfpoint.doc'; $phpWord = IOFactory::load($filename, 'MsDoc'); $sections = $phpWord->getSections(); self::assertCount(1, $sections); From 0709ae36dd79d49ab3b91bf0cde5e65d0b28c9eb Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Sun, 17 Dec 2023 14:16:40 -0800 Subject: [PATCH 169/246] Correct Title Line of Change Log --- docs/changes/1.x/1.3.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changes/1.x/1.3.0.md b/docs/changes/1.x/1.3.0.md index e85d9ff892..e3514080ac 100644 --- a/docs/changes/1.x/1.3.0.md +++ b/docs/changes/1.x/1.3.0.md @@ -1,4 +1,4 @@ -# [1.2.0](https://github.com/PHPOffice/PHPWord/tree/1.2.0) (WIP) +# [1.3.0](https://github.com/PHPOffice/PHPWord/tree/1.3.0) (WIP) [Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.2.0...1.3.0) From bb74fb168e4ae2033337dae303c4156426559b92 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 23:32:29 +0000 Subject: [PATCH 170/246] Bump dompdf/dompdf from 2.0.3 to 2.0.4 Bumps [dompdf/dompdf](https://github.com/dompdf/dompdf) from 2.0.3 to 2.0.4. - [Release notes](https://github.com/dompdf/dompdf/releases) - [Commits](https://github.com/dompdf/dompdf/compare/v2.0.3...v2.0.4) --- updated-dependencies: - dependency-name: dompdf/dompdf dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- composer.lock | 42 ++++++++++++++++++++------------------- docs/changes/1.x/1.2.0.md | 2 +- docs/changes/1.x/1.3.0.md | 14 ------------- docs/changes/2.x/2.0.0.md | 15 ++++++++++++++ mkdocs.yml | 4 +++- 5 files changed, 41 insertions(+), 36 deletions(-) delete mode 100644 docs/changes/1.x/1.3.0.md create mode 100644 docs/changes/2.x/2.0.0.md diff --git a/composer.lock b/composer.lock index 0f140f1e5a..d1a795a886 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "23680170abecc52de95d0833296ced64", + "content-hash": "8d0272c1442e11290de55a7947fc849c", "packages": [ { "name": "phpoffice/math", @@ -548,16 +548,16 @@ }, { "name": "dompdf/dompdf", - "version": "v2.0.3", + "version": "v2.0.4", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "e8d2d5e37e8b0b30f0732a011295ab80680d7e85" + "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/e8d2d5e37e8b0b30f0732a011295ab80680d7e85", - "reference": "e8d2d5e37e8b0b30f0732a011295ab80680d7e85", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/093f2d9739cec57428e39ddadedfd4f3ae862c0f", + "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f", "shasum": "" }, "require": { @@ -604,9 +604,9 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v2.0.3" + "source": "https://github.com/dompdf/dompdf/tree/v2.0.4" }, - "time": "2023-02-07T12:51:48+00:00" + "time": "2023-12-12T20:19:39+00:00" }, { "name": "friendsofphp/php-cs-fixer", @@ -699,16 +699,16 @@ }, { "name": "masterminds/html5", - "version": "2.8.0", + "version": "2.8.1", "source": { "type": "git", "url": "https://github.com/Masterminds/html5-php.git", - "reference": "3c5d5a56d56f48a1ca08a0670f0f80c1dad368f3" + "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/3c5d5a56d56f48a1ca08a0670f0f80c1dad368f3", - "reference": "3c5d5a56d56f48a1ca08a0670f0f80c1dad368f3", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf", + "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf", "shasum": "" }, "require": { @@ -760,9 +760,9 @@ ], "support": { "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.8.0" + "source": "https://github.com/Masterminds/html5-php/tree/2.8.1" }, - "time": "2023-04-26T07:27:39+00:00" + "time": "2023-05-10T11:58:31+00:00" }, { "name": "mpdf/mpdf", @@ -1322,16 +1322,16 @@ }, { "name": "phenx/php-svg-lib", - "version": "0.5.0", + "version": "0.5.1", "source": { "type": "git", "url": "https://github.com/dompdf/php-svg-lib.git", - "reference": "76876c6cf3080bcb6f249d7d59705108166a6685" + "reference": "8a8a1ebcf6aea861ef30197999f096f7bd4b4456" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/76876c6cf3080bcb6f249d7d59705108166a6685", - "reference": "76876c6cf3080bcb6f249d7d59705108166a6685", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/8a8a1ebcf6aea861ef30197999f096f7bd4b4456", + "reference": "8a8a1ebcf6aea861ef30197999f096f7bd4b4456", "shasum": "" }, "require": { @@ -1362,9 +1362,9 @@ "homepage": "https://github.com/PhenX/php-svg-lib", "support": { "issues": "https://github.com/dompdf/php-svg-lib/issues", - "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.0" + "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.1" }, - "time": "2022-09-06T12:16:56+00:00" + "time": "2023-12-11T20:56:08+00:00" }, { "name": "php-cs-fixer/diff", @@ -5060,7 +5060,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "phpstan/phpstan-phpunit": 0 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index 30d3b35202..265d25b033 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -1,4 +1,4 @@ -# [1.2.0](https://github.com/PHPOffice/PHPWord/tree/1.2.0) (WIP) +# [1.2.0](https://github.com/PHPOffice/PHPWord/tree/1.2.0) [Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.1.0...1.2.0) diff --git a/docs/changes/1.x/1.3.0.md b/docs/changes/1.x/1.3.0.md deleted file mode 100644 index e3514080ac..0000000000 --- a/docs/changes/1.x/1.3.0.md +++ /dev/null @@ -1,14 +0,0 @@ -# [1.3.0](https://github.com/PHPOffice/PHPWord/tree/1.3.0) (WIP) - -[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.2.0...1.3.0) - -## Enhancements - -### Bug fixes - -- MsDoc Reader : Correct Font Size Calculation by [@oleibman](https://github.com/oleibman) Issue [#2526](https://github.com/PHPOffice/PHPWord/issues/2526) PR [#2531](https://github.com/PHPOffice/PHPWord/pull/2531) - -### Miscellaneous - - -### BC Breaks diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md new file mode 100644 index 0000000000..cac743cd13 --- /dev/null +++ b/docs/changes/2.x/2.0.0.md @@ -0,0 +1,15 @@ +# [2.0.0](https://github.com/PHPOffice/PHPWord/tree/2.0.0) (WIP) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.2.0...2.0.0) + +## Enhancements + +### Bug fixes + +- MsDoc Reader : Correct Font Size Calculation by [@oleibman](https://github.com/oleibman) fixing [#2526](https://github.com/PHPOffice/PHPWord/issues/2526) in [#2531](https://github.com/PHPOffice/PHPWord/pull/2531) + +### Miscellaneous + +- Bump dompdf/dompdf from 2.0.3 to 2.0.4 by [@dependabot](https://github.com/dependabot) in [#2530](https://github.com/PHPOffice/PHPWord/pull/2530) + +### BC Breaks diff --git a/mkdocs.yml b/mkdocs.yml index a58ebfdad6..6eb4d42911 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -86,8 +86,10 @@ nav: - How to: 'howto.md' - Credits: 'credits.md' - Releases: + - '2.x': + - '2.0.0 (WIP)': 'changes/2.x/2.0.0.md' - '1.x': - - '1.2.0 (WIP)': 'changes/1.x/1.2.0.md' + - '1.2.0': 'changes/1.x/1.2.0.md' - '1.1.0': 'changes/1.x/1.1.0.md' - '1.0.0': 'changes/1.x/1.0.0.md' - '0.x': From 9f1d7c75978698f5dbd669b7f10ee2808995ecf5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Dec 2023 11:16:57 +0000 Subject: [PATCH 171/246] Bump phpunit/phpunit from 9.6.13 to 9.6.14 Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.13 to 9.6.14. - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/9.6.14/ChangeLog-9.6.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.6.13...9.6.14) --- updated-dependencies: - dependency-name: phpunit/phpunit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 24 ++++++++++++------------ docs/changes/2.x/2.0.0.md | 1 + 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/composer.lock b/composer.lock index d1a795a886..f69b296d9a 100644 --- a/composer.lock +++ b/composer.lock @@ -1938,16 +1938,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.13", + "version": "9.6.14", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be" + "reference": "43653e6ad7adc22e7b667dd561bf8fcb74c10cf0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f3d767f7f9e191eab4189abe41ab37797e30b1be", - "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/43653e6ad7adc22e7b667dd561bf8fcb74c10cf0", + "reference": "43653e6ad7adc22e7b667dd561bf8fcb74c10cf0", "shasum": "" }, "require": { @@ -2021,7 +2021,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.13" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.14" }, "funding": [ { @@ -2037,7 +2037,7 @@ "type": "tidelift" } ], - "time": "2023-09-19T05:39:22+00:00" + "time": "2023-12-01T06:10:48+00:00" }, { "name": "psr/cache", @@ -5009,16 +5009,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.2.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", "shasum": "" }, "require": { @@ -5047,7 +5047,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + "source": "https://github.com/theseer/tokenizer/tree/1.2.2" }, "funding": [ { @@ -5055,7 +5055,7 @@ "type": "github" } ], - "time": "2021-07-28T10:34:58+00:00" + "time": "2023-11-20T00:12:19+00:00" } ], "aliases": [], diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index cac743cd13..7bb462acfe 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -11,5 +11,6 @@ ### Miscellaneous - Bump dompdf/dompdf from 2.0.3 to 2.0.4 by [@dependabot](https://github.com/dependabot) in [#2530](https://github.com/PHPOffice/PHPWord/pull/2530) +- Bump phpunit/phpunit from 9.6.13 to 9.6.14 by [@dependabot](https://github.com/dependabot) in [#2519](https://github.com/PHPOffice/PHPWord/pull/2519) ### BC Breaks From d60f1e01678ee1eaa61b7a193ab33abf7b4a5b11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Dec 2023 08:41:02 +0000 Subject: [PATCH 172/246] Bump mpdf/mpdf from 8.2.0 to 8.2.2 Bumps [mpdf/mpdf](https://github.com/mpdf/mpdf) from 8.2.0 to 8.2.2. - [Release notes](https://github.com/mpdf/mpdf/releases) - [Changelog](https://github.com/mpdf/mpdf/blob/development/CHANGELOG.md) - [Commits](https://github.com/mpdf/mpdf/compare/v8.2.0...v8.2.2) --- updated-dependencies: - dependency-name: mpdf/mpdf dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 40 +++++++++++++++++++-------------------- docs/changes/2.x/2.0.0.md | 1 + 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/composer.lock b/composer.lock index f69b296d9a..a281bac14b 100644 --- a/composer.lock +++ b/composer.lock @@ -766,16 +766,16 @@ }, { "name": "mpdf/mpdf", - "version": "v8.2.0", + "version": "v8.2.2", "source": { "type": "git", "url": "https://github.com/mpdf/mpdf.git", - "reference": "170a236a588d177c2aa7447ce490a030ca68e6f4" + "reference": "596a87b876d7793be7be060a8ac13424de120dd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mpdf/mpdf/zipball/170a236a588d177c2aa7447ce490a030ca68e6f4", - "reference": "170a236a588d177c2aa7447ce490a030ca68e6f4", + "url": "https://api.github.com/repos/mpdf/mpdf/zipball/596a87b876d7793be7be060a8ac13424de120dd5", + "reference": "596a87b876d7793be7be060a8ac13424de120dd5", "shasum": "" }, "require": { @@ -785,7 +785,7 @@ "mpdf/psr-log-aware-trait": "^2.0 || ^3.0", "myclabs/deep-copy": "^1.7", "paragonie/random_compat": "^1.4|^2.0|^9.99.99", - "php": "^5.6 || ^7.0 || ~8.0.0 || ~8.1.0 || ~8.2.0", + "php": "^5.6 || ^7.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", "psr/http-message": "^1.0 || ^2.0", "psr/log": "^1.0 || ^2.0 || ^3.0", "setasign/fpdi": "^2.1" @@ -843,20 +843,20 @@ "type": "custom" } ], - "time": "2023-09-01T11:44:52+00:00" + "time": "2023-11-07T13:52:14+00:00" }, { "name": "mpdf/psr-http-message-shim", - "version": "2.0.0", + "version": "v2.0.1", "source": { "type": "git", "url": "https://github.com/mpdf/psr-http-message-shim.git", - "reference": "1cf4c0b68b8461cea27411ff961482ce7687e34f" + "reference": "f25a0153d645e234f9db42e5433b16d9b113920f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mpdf/psr-http-message-shim/zipball/1cf4c0b68b8461cea27411ff961482ce7687e34f", - "reference": "1cf4c0b68b8461cea27411ff961482ce7687e34f", + "url": "https://api.github.com/repos/mpdf/psr-http-message-shim/zipball/f25a0153d645e234f9db42e5433b16d9b113920f", + "reference": "f25a0153d645e234f9db42e5433b16d9b113920f", "shasum": "" }, "require": { @@ -889,9 +889,9 @@ "description": "Shim to allow support of different psr/message versions.", "support": { "issues": "https://github.com/mpdf/psr-http-message-shim/issues", - "source": "https://github.com/mpdf/psr-http-message-shim/tree/2.0.0" + "source": "https://github.com/mpdf/psr-http-message-shim/tree/v2.0.1" }, - "time": "2023-09-01T06:08:18+00:00" + "time": "2023-10-02T14:34:03+00:00" }, { "name": "mpdf/psr-log-aware-trait", @@ -3308,16 +3308,16 @@ }, { "name": "setasign/fpdi", - "version": "v2.5.0", + "version": "v2.6.0", "source": { "type": "git", "url": "https://github.com/Setasign/FPDI.git", - "reference": "ecf0459643ec963febfb9a5d529dcd93656006a4" + "reference": "a6db878129ec6c7e141316ee71872923e7f1b7ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Setasign/FPDI/zipball/ecf0459643ec963febfb9a5d529dcd93656006a4", - "reference": "ecf0459643ec963febfb9a5d529dcd93656006a4", + "url": "https://api.github.com/repos/Setasign/FPDI/zipball/a6db878129ec6c7e141316ee71872923e7f1b7ad", + "reference": "a6db878129ec6c7e141316ee71872923e7f1b7ad", "shasum": "" }, "require": { @@ -3329,8 +3329,8 @@ }, "require-dev": { "phpunit/phpunit": "~5.7", - "setasign/fpdf": "~1.8", - "setasign/tfpdf": "~1.31", + "setasign/fpdf": "~1.8.6", + "setasign/tfpdf": "~1.33", "squizlabs/php_codesniffer": "^3.5", "tecnickcom/tcpdf": "~6.2" }, @@ -3368,7 +3368,7 @@ ], "support": { "issues": "https://github.com/Setasign/FPDI/issues", - "source": "https://github.com/Setasign/FPDI/tree/v2.5.0" + "source": "https://github.com/Setasign/FPDI/tree/v2.6.0" }, "funding": [ { @@ -3376,7 +3376,7 @@ "type": "tidelift" } ], - "time": "2023-09-28T10:46:27+00:00" + "time": "2023-12-11T16:03:32+00:00" }, { "name": "symfony/config", diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 7bb462acfe..6105dc4e25 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -12,5 +12,6 @@ - Bump dompdf/dompdf from 2.0.3 to 2.0.4 by [@dependabot](https://github.com/dependabot) in [#2530](https://github.com/PHPOffice/PHPWord/pull/2530) - Bump phpunit/phpunit from 9.6.13 to 9.6.14 by [@dependabot](https://github.com/dependabot) in [#2519](https://github.com/PHPOffice/PHPWord/pull/2519) +- Bump mpdf/mpdf from 8.2.0 to 8.2.2 by [@dependabot](https://github.com/dependabot) in [#2518](https://github.com/PHPOffice/PHPWord/pull/2518) ### BC Breaks From a3020196f31dc910d4470d353391a8a7d942f062 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 11:49:37 +0000 Subject: [PATCH 173/246] Bump phpmd/phpmd from 2.14.1 to 2.15.0 Bumps [phpmd/phpmd](https://github.com/phpmd/phpmd) from 2.14.1 to 2.15.0. - [Release notes](https://github.com/phpmd/phpmd/releases) - [Changelog](https://github.com/phpmd/phpmd/blob/master/CHANGELOG) - [Commits](https://github.com/phpmd/phpmd/compare/2.14.1...2.15.0) --- updated-dependencies: - dependency-name: phpmd/phpmd dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- composer.lock | 59 +++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/composer.lock b/composer.lock index a281bac14b..6f7395a174 100644 --- a/composer.lock +++ b/composer.lock @@ -1104,28 +1104,28 @@ }, { "name": "pdepend/pdepend", - "version": "2.15.1", + "version": "2.16.2", "source": { "type": "git", "url": "https://github.com/pdepend/pdepend.git", - "reference": "d12f25bcdfb7754bea458a4a5cb159d55e9950d0" + "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pdepend/pdepend/zipball/d12f25bcdfb7754bea458a4a5cb159d55e9950d0", - "reference": "d12f25bcdfb7754bea458a4a5cb159d55e9950d0", + "url": "https://api.github.com/repos/pdepend/pdepend/zipball/f942b208dc2a0868454d01b29f0c75bbcfc6ed58", + "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58", "shasum": "" }, "require": { "php": ">=5.3.7", - "symfony/config": "^2.3.0|^3|^4|^5|^6.0", - "symfony/dependency-injection": "^2.3.0|^3|^4|^5|^6.0", - "symfony/filesystem": "^2.3.0|^3|^4|^5|^6.0" + "symfony/config": "^2.3.0|^3|^4|^5|^6.0|^7.0", + "symfony/dependency-injection": "^2.3.0|^3|^4|^5|^6.0|^7.0", + "symfony/filesystem": "^2.3.0|^3|^4|^5|^6.0|^7.0", + "symfony/polyfill-mbstring": "^1.19" }, "require-dev": { "easy-doc/easy-doc": "0.0.0|^1.2.3", "gregwar/rst": "^1.0", - "phpunit/phpunit": "^4.8.36|^5.7.27", "squizlabs/php_codesniffer": "^2.0.0" }, "bin": [ @@ -1155,7 +1155,7 @@ ], "support": { "issues": "https://github.com/pdepend/pdepend/issues", - "source": "https://github.com/pdepend/pdepend/tree/2.15.1" + "source": "https://github.com/pdepend/pdepend/tree/2.16.2" }, "funding": [ { @@ -1163,7 +1163,7 @@ "type": "tidelift" } ], - "time": "2023-09-28T12:00:56+00:00" + "time": "2023-12-17T18:09:59+00:00" }, { "name": "phar-io/manifest", @@ -1421,22 +1421,22 @@ }, { "name": "phpmd/phpmd", - "version": "2.14.1", + "version": "2.15.0", "source": { "type": "git", "url": "https://github.com/phpmd/phpmd.git", - "reference": "442fc2c34edcd5198b442d8647c7f0aec3afabe8" + "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpmd/phpmd/zipball/442fc2c34edcd5198b442d8647c7f0aec3afabe8", - "reference": "442fc2c34edcd5198b442d8647c7f0aec3afabe8", + "url": "https://api.github.com/repos/phpmd/phpmd/zipball/74a1f56e33afad4128b886e334093e98e1b5e7c0", + "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0", "shasum": "" }, "require": { "composer/xdebug-handler": "^1.0 || ^2.0 || ^3.0", "ext-xml": "*", - "pdepend/pdepend": "^2.15.1", + "pdepend/pdepend": "^2.16.1", "php": ">=5.3.9" }, "require-dev": { @@ -1445,7 +1445,6 @@ "ext-simplexml": "*", "gregwar/rst": "^1.0", "mikey179/vfsstream": "^1.6.8", - "phpunit/phpunit": "^4.8.36 || ^5.7.27", "squizlabs/php_codesniffer": "^2.9.2 || ^3.7.2" }, "bin": [ @@ -1493,7 +1492,7 @@ "support": { "irc": "irc://irc.freenode.org/phpmd", "issues": "https://github.com/phpmd/phpmd/issues", - "source": "https://github.com/phpmd/phpmd/tree/2.14.1" + "source": "https://github.com/phpmd/phpmd/tree/2.15.0" }, "funding": [ { @@ -1501,7 +1500,7 @@ "type": "tidelift" } ], - "time": "2023-09-28T13:07:44+00:00" + "time": "2023-12-11T08:22:20+00:00" }, { "name": "phpstan/phpstan", @@ -3380,16 +3379,16 @@ }, { "name": "symfony/config", - "version": "v5.4.26", + "version": "v5.4.31", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "8109892f27beed9252bd1f1c1880aeb4ad842650" + "reference": "dd5ea39de228813aba0c23c3a4153da2a4cf3cd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/8109892f27beed9252bd1f1c1880aeb4ad842650", - "reference": "8109892f27beed9252bd1f1c1880aeb4ad842650", + "url": "https://api.github.com/repos/symfony/config/zipball/dd5ea39de228813aba0c23c3a4153da2a4cf3cd9", + "reference": "dd5ea39de228813aba0c23c3a4153da2a4cf3cd9", "shasum": "" }, "require": { @@ -3439,7 +3438,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com/", "support": { - "source": "https://github.com/symfony/config/tree/v5.4.26" + "source": "https://github.com/symfony/config/tree/v5.4.31" }, "funding": [ { @@ -3455,7 +3454,7 @@ "type": "tidelift" } ], - "time": "2023-07-19T20:21:11+00:00" + "time": "2023-11-09T08:22:43+00:00" }, { "name": "symfony/console", @@ -3557,16 +3556,16 @@ }, { "name": "symfony/dependency-injection", - "version": "v5.4.29", + "version": "v5.4.34", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "338638ed8c9d5c7fcb136a73f5c7043465ae2f05" + "reference": "75d568165a65fa7d8124869ec7c3a90424352e6c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/338638ed8c9d5c7fcb136a73f5c7043465ae2f05", - "reference": "338638ed8c9d5c7fcb136a73f5c7043465ae2f05", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/75d568165a65fa7d8124869ec7c3a90424352e6c", + "reference": "75d568165a65fa7d8124869ec7c3a90424352e6c", "shasum": "" }, "require": { @@ -3626,7 +3625,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com/", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v5.4.29" + "source": "https://github.com/symfony/dependency-injection/tree/v5.4.34" }, "funding": [ { @@ -3642,7 +3641,7 @@ "type": "tidelift" } ], - "time": "2023-09-20T06:23:43+00:00" + "time": "2023-12-28T09:31:38+00:00" }, { "name": "symfony/deprecation-contracts", From c73d1ce25647b416fa0ccdd2f7f6c30204d09d58 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Sat, 6 Jan 2024 18:06:47 +0100 Subject: [PATCH 174/246] Updated Changelog --- docs/changes/2.x/2.0.0.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 6105dc4e25..d5565c76f7 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -13,5 +13,6 @@ - Bump dompdf/dompdf from 2.0.3 to 2.0.4 by [@dependabot](https://github.com/dependabot) in [#2530](https://github.com/PHPOffice/PHPWord/pull/2530) - Bump phpunit/phpunit from 9.6.13 to 9.6.14 by [@dependabot](https://github.com/dependabot) in [#2519](https://github.com/PHPOffice/PHPWord/pull/2519) - Bump mpdf/mpdf from 8.2.0 to 8.2.2 by [@dependabot](https://github.com/dependabot) in [#2518](https://github.com/PHPOffice/PHPWord/pull/2518) +- Bump phpmd/phpmd from 2.14.1 to 2.15.0 by [@dependabot](https://github.com/dependabot) in [#2538](https://github.com/PHPOffice/PHPWord/pull/2538) ### BC Breaks From 7f110d0944e11513e30b18b4757a2fdbe7b863c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 6 Jan 2024 17:26:14 +0000 Subject: [PATCH 175/246] Bump phpunit/phpunit from 9.6.14 to 9.6.15 Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.14 to 9.6.15. - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/9.6.15/ChangeLog-9.6.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.6.14...9.6.15) --- updated-dependencies: - dependency-name: phpunit/phpunit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 66 +++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/composer.lock b/composer.lock index 6f7395a174..6ce71d2a3f 100644 --- a/composer.lock +++ b/composer.lock @@ -998,16 +998,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.17.1", + "version": "v4.18.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", "shasum": "" }, "require": { @@ -1048,9 +1048,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" }, - "time": "2023-08-13T19:53:39+00:00" + "time": "2023-12-10T21:03:43+00:00" }, { "name": "paragonie/random_compat", @@ -1618,23 +1618,23 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.29", + "version": "9.2.30", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" + "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", - "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089", + "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.15", + "nikic/php-parser": "^4.18 || ^5.0", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -1684,7 +1684,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30" }, "funding": [ { @@ -1692,7 +1692,7 @@ "type": "github" } ], - "time": "2023-09-19T04:57:46+00:00" + "time": "2023-12-22T06:47:57+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1937,16 +1937,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.14", + "version": "9.6.15", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "43653e6ad7adc22e7b667dd561bf8fcb74c10cf0" + "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/43653e6ad7adc22e7b667dd561bf8fcb74c10cf0", - "reference": "43653e6ad7adc22e7b667dd561bf8fcb74c10cf0", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/05017b80304e0eb3f31d90194a563fd53a6021f1", + "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1", "shasum": "" }, "require": { @@ -2020,7 +2020,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.14" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.15" }, "funding": [ { @@ -2036,7 +2036,7 @@ "type": "tidelift" } ], - "time": "2023-12-01T06:10:48+00:00" + "time": "2023-12-01T16:55:19+00:00" }, { "name": "psr/cache", @@ -2584,20 +2584,20 @@ }, { "name": "sebastian/complexity", - "version": "2.0.2", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", "shasum": "" }, "require": { - "nikic/php-parser": "^4.7", + "nikic/php-parser": "^4.18 || ^5.0", "php": ">=7.3" }, "require-dev": { @@ -2629,7 +2629,7 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" }, "funding": [ { @@ -2637,7 +2637,7 @@ "type": "github" } ], - "time": "2020-10-26T15:52:27+00:00" + "time": "2023-12-22T06:19:30+00:00" }, { "name": "sebastian/diff", @@ -2911,20 +2911,20 @@ }, { "name": "sebastian/lines-of-code", - "version": "1.0.3", + "version": "1.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", "shasum": "" }, "require": { - "nikic/php-parser": "^4.6", + "nikic/php-parser": "^4.18 || ^5.0", "php": ">=7.3" }, "require-dev": { @@ -2956,7 +2956,7 @@ "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" }, "funding": [ { @@ -2964,7 +2964,7 @@ "type": "github" } ], - "time": "2020-11-28T06:42:11+00:00" + "time": "2023-12-22T06:20:34+00:00" }, { "name": "sebastian/object-enumerator", From aa478ac1ce075f469c085b92f4650d2bd1349a5a Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Sat, 6 Jan 2024 18:27:50 +0100 Subject: [PATCH 176/246] Updated Changelog --- docs/changes/2.x/2.0.0.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index d5565c76f7..2aaabc5987 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -14,5 +14,6 @@ - Bump phpunit/phpunit from 9.6.13 to 9.6.14 by [@dependabot](https://github.com/dependabot) in [#2519](https://github.com/PHPOffice/PHPWord/pull/2519) - Bump mpdf/mpdf from 8.2.0 to 8.2.2 by [@dependabot](https://github.com/dependabot) in [#2518](https://github.com/PHPOffice/PHPWord/pull/2518) - Bump phpmd/phpmd from 2.14.1 to 2.15.0 by [@dependabot](https://github.com/dependabot) in [#2538](https://github.com/PHPOffice/PHPWord/pull/2538) +- Bump phpunit/phpunit from 9.6.14 to 9.6.15 by [@dependabot](https://github.com/dependabot) in [#2537](https://github.com/PHPOffice/PHPWord/pull/2537) ### BC Breaks From 41b71eda4790d55bbad62bd34cb53eacf3576009 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 11:49:26 +0000 Subject: [PATCH 177/246] Bump symfony/process from 5.4.28 to 5.4.34 Bumps [symfony/process](https://github.com/symfony/process) from 5.4.28 to 5.4.34. - [Release notes](https://github.com/symfony/process/releases) - [Changelog](https://github.com/symfony/process/blob/7.0/CHANGELOG.md) - [Commits](https://github.com/symfony/process/compare/v5.4.28...v5.4.34) --- updated-dependencies: - dependency-name: symfony/process dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 6ce71d2a3f..6eb3324ccb 100644 --- a/composer.lock +++ b/composer.lock @@ -4643,16 +4643,16 @@ }, { "name": "symfony/process", - "version": "v5.4.28", + "version": "v5.4.34", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "45261e1fccad1b5447a8d7a8e67aa7b4a9798b7b" + "reference": "8fa22178dfc368911dbd513b431cd9b06f9afe7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/45261e1fccad1b5447a8d7a8e67aa7b4a9798b7b", - "reference": "45261e1fccad1b5447a8d7a8e67aa7b4a9798b7b", + "url": "https://api.github.com/repos/symfony/process/zipball/8fa22178dfc368911dbd513b431cd9b06f9afe7a", + "reference": "8fa22178dfc368911dbd513b431cd9b06f9afe7a", "shasum": "" }, "require": { @@ -4685,7 +4685,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com/", "support": { - "source": "https://github.com/symfony/process/tree/v5.4.28" + "source": "https://github.com/symfony/process/tree/v5.4.34" }, "funding": [ { @@ -4701,7 +4701,7 @@ "type": "tidelift" } ], - "time": "2023-08-07T10:36:04+00:00" + "time": "2023-12-02T08:41:43+00:00" }, { "name": "symfony/service-contracts", From be41bb67f77ea2f94c7139546545611a2afaf97c Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Sat, 6 Jan 2024 18:47:38 +0100 Subject: [PATCH 178/246] Updated Changelog --- docs/changes/2.x/2.0.0.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 2aaabc5987..2ee54698cc 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -15,5 +15,6 @@ - Bump mpdf/mpdf from 8.2.0 to 8.2.2 by [@dependabot](https://github.com/dependabot) in [#2518](https://github.com/PHPOffice/PHPWord/pull/2518) - Bump phpmd/phpmd from 2.14.1 to 2.15.0 by [@dependabot](https://github.com/dependabot) in [#2538](https://github.com/PHPOffice/PHPWord/pull/2538) - Bump phpunit/phpunit from 9.6.14 to 9.6.15 by [@dependabot](https://github.com/dependabot) in [#2537](https://github.com/PHPOffice/PHPWord/pull/2537) +- Bump symfony/process from 5.4.28 to 5.4.34 by [@dependabot](https://github.com/dependabot) in [#2536](https://github.com/PHPOffice/PHPWord/pull/2536) ### BC Breaks From a0569140aabe24e64e94a5d27713cc9eaa0d4949 Mon Sep 17 00:00:00 2001 From: Gordon Franke Date: Thu, 7 Dec 2023 08:52:02 +0100 Subject: [PATCH 179/246] bug: TemplateProcessor fix multiline values --- docs/changes/2.x/2.0.0.md | 2 ++ src/PhpWord/TemplateProcessor.php | 17 +++++++++++++++++ tests/PhpWordTests/TemplateProcessorTest.php | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 2ee54698cc..a8c3cd596e 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -8,6 +8,8 @@ - MsDoc Reader : Correct Font Size Calculation by [@oleibman](https://github.com/oleibman) fixing [#2526](https://github.com/PHPOffice/PHPWord/issues/2526) in [#2531](https://github.com/PHPOffice/PHPWord/pull/2531) +- bug: TemplateProcessor fix multiline values [@gimler](https://github.com/gimler) fixing [#268](https://github.com/PHPOffice/PHPWord/issues/268), [#2323](https://github.com/PHPOffice/PHPWord/issues/2323) and [#2486](https://github.com/PHPOffice/PHPWord/issues/2486) in [#2522](https://github.com/PHPOffice/PHPWord/pull/2522) + ### Miscellaneous - Bump dompdf/dompdf from 2.0.3 to 2.0.4 by [@dependabot](https://github.com/dependabot) in [#2530](https://github.com/PHPOffice/PHPWord/pull/2530) diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 1ad901d480..27577499e5 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -357,6 +357,15 @@ public function setValue($search, $replace, $limit = self::MAXIMUM_REPLACEMENTS_ $replace = $xmlEscaper->escape($replace); } + // convert carriage returns + if (is_array($replace)) { + foreach ($replace as &$item) { + $item = $this->replaceCarriageReturns($item); + } + } else { + $replace = $this->replaceCarriageReturns($replace); + } + $this->tempDocumentHeaders = $this->setValueForPart($search, $replace, $this->tempDocumentHeaders, $limit); $this->tempDocumentMainPart = $this->setValueForPart($search, $replace, $this->tempDocumentMainPart, $limit); $this->tempDocumentFooters = $this->setValueForPart($search, $replace, $this->tempDocumentFooters, $limit); @@ -1305,6 +1314,14 @@ protected function indexClonedVariables($count, $xmlBlock) return $results; } + /** + * Replace carriage returns with xml. + */ + public function replaceCarriageReturns(string $string): string + { + return str_replace(["\r\n", "\r", "\n"], '', $string); + } + /** * Replaces variables with values from array, array keys are the variable names. * diff --git a/tests/PhpWordTests/TemplateProcessorTest.php b/tests/PhpWordTests/TemplateProcessorTest.php index f2d2cfbf13..65d5cfe9d8 100644 --- a/tests/PhpWordTests/TemplateProcessorTest.php +++ b/tests/PhpWordTests/TemplateProcessorTest.php @@ -591,6 +591,24 @@ public function testSetValues(): void self::assertStringContainsString('Hello John Doe', $templateProcessor->getMainPart()); } + /** + * @covers ::setValues + */ + public function testSetValuesMultiLine(): void + { + $mainPart = ' + + + Address: ${address} + + '; + + $templateProcessor = new TestableTemplateProcesor($mainPart); + $templateProcessor->setValues(['address' => "Peter Pan\nNeverland"]); + + self::assertStringContainsString('Address: Peter PanNeverland', $templateProcessor->getMainPart()); + } + /** * @covers ::setValues */ From 9bf816b084b77b9ff473316d682fc35bf21ceed7 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Sun, 7 Jan 2024 12:27:24 -0800 Subject: [PATCH 180/246] Allow `rgb()` When Converting Html (#2512) * Allow `rgb()` When Converting Html Fix #2508. Program currently expects `#xxxxxx` to specify a color when used by the `bgcolor` html attribute or the `color` or `background-color` css attributes. This PR allows support for `rgb(red, green, blue)` as well. * Update Change Log 2.0.0 --- docs/changes/2.x/2.0.0.md | 1 + src/PhpWord/Shared/Html.php | 17 ++++++-- .../Writer/Word2007/Style/FontTest.php | 42 +++++++++++++++++++ 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index a8c3cd596e..c679317049 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -18,5 +18,6 @@ - Bump phpmd/phpmd from 2.14.1 to 2.15.0 by [@dependabot](https://github.com/dependabot) in [#2538](https://github.com/PHPOffice/PHPWord/pull/2538) - Bump phpunit/phpunit from 9.6.14 to 9.6.15 by [@dependabot](https://github.com/dependabot) in [#2537](https://github.com/PHPOffice/PHPWord/pull/2537) - Bump symfony/process from 5.4.28 to 5.4.34 by [@dependabot](https://github.com/dependabot) in [#2536](https://github.com/PHPOffice/PHPWord/pull/2536) +- Allow rgb() when converting Html [@oleibman](https://github.com/oleibman) fixing [#2508](https://github.com/PHPOffice/PHPWord/issues/2508) in [#2512](https://github.com/PHPOffice/PHPWord/pull/2512) ### BC Breaks diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 0a9b23979c..2022f7da09 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -37,6 +37,8 @@ */ class Html { + private const RGB_REGEXP = '/^\s*rgb\s*[(]\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*[)]\s*$/'; + protected static $listIndex = 0; protected static $xpath; @@ -142,7 +144,7 @@ protected static function parseInlineStyle($node, $styles = []) break; case 'bgcolor': // tables, rows, cells e.g. - $styles['bgColor'] = trim($val, '# '); + $styles['bgColor'] = self::convertRgb($val); break; case 'valign': @@ -720,11 +722,11 @@ protected static function parseStyleDeclarations(array $selectors, array $styles break; case 'color': - $styles['color'] = trim($value, '#'); + $styles['color'] = self::convertRgb($value); break; case 'background-color': - $styles['bgColor'] = trim($value, '#'); + $styles['bgColor'] = self::convertRgb($value); break; case 'line-height': @@ -1170,4 +1172,13 @@ protected static function parseHorizRule($node, $element): void // - line - that is a shape, has different behaviour // - repeated text, e.g. underline "_", because of unpredictable line wrapping } + + private static function convertRgb(string $rgb): string + { + if (preg_match(self::RGB_REGEXP, $rgb, $matches) === 1) { + return sprintf('%02X%02X%02X', $matches[1], $matches[2], $matches[3]); + } + + return trim($rgb, '# '); + } } diff --git a/tests/PhpWordTests/Writer/Word2007/Style/FontTest.php b/tests/PhpWordTests/Writer/Word2007/Style/FontTest.php index 2c10b5ff2f..a8214ec35b 100644 --- a/tests/PhpWordTests/Writer/Word2007/Style/FontTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Style/FontTest.php @@ -17,6 +17,8 @@ namespace PhpOffice\PhpWordTests\Writer\Word2007\Style; +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Shared\Html; use PhpOffice\PhpWordTests\TestHelperDOCX; /** @@ -155,4 +157,44 @@ public function testPosition(): void self::assertTrue($doc->elementExists($path)); self::assertEquals(-20, $doc->getElementAttribute($path, 'w:val')); } + + public static function testRgb(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(['pageNumberingStart' => 1]); + $html = implode( + "\n", + [ + '', + '', + '', + '', + '', + '', + '', + '
This one is in color.This one too.
', + ] + ); + + Html::addHtml($section, $html, false, false); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $element = '/w:document/w:body/w:tbl/w:tr/w:tc/w:p/w:r'; + $txtelem = $element . '/w:t'; + $styelem = $element . '/w:rPr'; + self::assertTrue($doc->elementExists($txtelem)); + self::assertSame('This one is in color.', $doc->getElement($txtelem)->textContent); + self::assertTrue($doc->elementExists($styelem)); + self::assertTrue($doc->elementExists($styelem . '/w:color')); + self::assertSame('A7D9C1', $doc->getElementAttribute($styelem . '/w:color', 'w:val')); + + $element = '/w:document/w:body/w:tbl/w:tr/w:tc[2]/w:p/w:r'; + $txtelem = $element . '/w:t'; + $styelem = $element . '/w:rPr'; + self::assertTrue($doc->elementExists($txtelem)); + self::assertSame('This one too.', $doc->getElement($txtelem)->textContent); + self::assertTrue($doc->elementExists($styelem)); + self::assertTrue($doc->elementExists($styelem . '/w:color')); + self::assertSame('A7D9C1', $doc->getElementAttribute($styelem . '/w:color', 'w:val')); + } } From 98d038e05d2c9c0bf483a0c22118438a69853c49 Mon Sep 17 00:00:00 2001 From: Marin Nikolli <34999323+sibalonat@users.noreply.github.com> Date: Mon, 8 Jan 2024 07:34:35 +0100 Subject: [PATCH 181/246] Added extractVariables method to IOFactory (#2515) * Added extractVariables method to IOFactory * remove var_dumps * remove vardump * fix return and fix php stan errors and instances * fix order and whitespace * extra space * remove new lines * white space * new lines * whiteline * new line * white space * fix * new line * white space * remove some unneecessary if statement * Correct Font Size Calculated by MsDoc Reader Fix #2526. Most of that issue has already been fixed. The one remaining problem was a deprecation message handling font size. The code used `dechex($operand / 2)`, and issued the deprecation message whenever `$operand` was odd because `dechex` is designed only for integer conversion. `$operand` is actually 2 times the point size, so it will be odd only when the point size is some integer plus half a point (no other fractions are allowed). At any rate, it seems that `dechex` should not be used here in the first place; font size is a numeric value, not a hex string. There are many problems with MsDoc Reader at the moment. This PR is narrowly focused on the problem at hand. Its test is, at least, more detailed than the existing MsDoc Reader test, which does nothing more than confirm that read successfully creates a PhpWord object. The new test verifies that the font size is as expected, but does not validate any other aspect of the read. * Suggestions from @Progi1984 * Typo Tolerated By Windows but Not By Unix * Correct Title Line of Change Log * Bump dompdf/dompdf from 2.0.3 to 2.0.4 Bumps [dompdf/dompdf](https://github.com/dompdf/dompdf) from 2.0.3 to 2.0.4. - [Release notes](https://github.com/dompdf/dompdf/releases) - [Commits](https://github.com/dompdf/dompdf/compare/v2.0.3...v2.0.4) --- updated-dependencies: - dependency-name: dompdf/dompdf dependency-type: direct:development ... Signed-off-by: dependabot[bot] * Bump phpunit/phpunit from 9.6.13 to 9.6.14 Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.13 to 9.6.14. - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/9.6.14/ChangeLog-9.6.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.6.13...9.6.14) --- updated-dependencies: - dependency-name: phpunit/phpunit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump mpdf/mpdf from 8.2.0 to 8.2.2 Bumps [mpdf/mpdf](https://github.com/mpdf/mpdf) from 8.2.0 to 8.2.2. - [Release notes](https://github.com/mpdf/mpdf/releases) - [Changelog](https://github.com/mpdf/mpdf/blob/development/CHANGELOG.md) - [Commits](https://github.com/mpdf/mpdf/compare/v8.2.0...v8.2.2) --- updated-dependencies: - dependency-name: mpdf/mpdf dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump phpmd/phpmd from 2.14.1 to 2.15.0 Bumps [phpmd/phpmd](https://github.com/phpmd/phpmd) from 2.14.1 to 2.15.0. - [Release notes](https://github.com/phpmd/phpmd/releases) - [Changelog](https://github.com/phpmd/phpmd/blob/master/CHANGELOG) - [Commits](https://github.com/phpmd/phpmd/compare/2.14.1...2.15.0) --- updated-dependencies: - dependency-name: phpmd/phpmd dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Updated Changelog * Bump phpunit/phpunit from 9.6.14 to 9.6.15 Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.14 to 9.6.15. - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/9.6.15/ChangeLog-9.6.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.6.14...9.6.15) --- updated-dependencies: - dependency-name: phpunit/phpunit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Updated Changelog * Bump symfony/process from 5.4.28 to 5.4.34 Bumps [symfony/process](https://github.com/symfony/process) from 5.4.28 to 5.4.34. - [Release notes](https://github.com/symfony/process/releases) - [Changelog](https://github.com/symfony/process/blob/7.0/CHANGELOG.md) - [Commits](https://github.com/symfony/process/compare/v5.4.28...v5.4.34) --- updated-dependencies: - dependency-name: symfony/process dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Updated Changelog * Added extractVariables method to IOFactory * remove var_dumps * fix return and fix php stan errors and instances * fix order and whitespace * remove new lines * white space * new lines * whiteline * new line * white space * fix * white space * remove some unneecessary if statement * variable changes * 2.0.0 md * 2.0.0 * new line at end of the file * add entry to md * additional space, type fixes in enhancement md and iofactory * some fixes on spacing * based on fixer suggestions * new line at the end of the file --------- Signed-off-by: dependabot[bot] Co-authored-by: oleibman <10341515+oleibman@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Progi1984 --- docs/changes/2.x/2.0.0.md | 2 + ..._44_ExtractVariablesFromReaderWord2007.php | 14 +++++++ ...44_ExtractVariablesFromReaderWord2007.docx | Bin 0 -> 12981 bytes src/PhpWord/IOFactory.php | 39 ++++++++++++++++++ tests/PhpWordTests/IOFactoryTest.php | 13 ++++++ .../_files/templates/extract-variable.docx | Bin 0 -> 12575 bytes 6 files changed, 68 insertions(+) create mode 100644 samples/Sample_44_ExtractVariablesFromReaderWord2007.php create mode 100644 samples/resources/Sample_44_ExtractVariablesFromReaderWord2007.docx create mode 100644 tests/PhpWordTests/_files/templates/extract-variable.docx diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index c679317049..74f2184155 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -4,6 +4,8 @@ ## Enhancements +- IOFactory : Added extractVariables method to extract variables from a document [@sibalonat](https://github.com/sibalonat) in [#2515](https://github.com/PHPOffice/PHPWord/pull/2515) + ### Bug fixes - MsDoc Reader : Correct Font Size Calculation by [@oleibman](https://github.com/oleibman) fixing [#2526](https://github.com/PHPOffice/PHPWord/issues/2526) in [#2531](https://github.com/PHPOffice/PHPWord/pull/2531) diff --git a/samples/Sample_44_ExtractVariablesFromReaderWord2007.php b/samples/Sample_44_ExtractVariablesFromReaderWord2007.php new file mode 100644 index 0000000000..24574e5fb7 --- /dev/null +++ b/samples/Sample_44_ExtractVariablesFromReaderWord2007.php @@ -0,0 +1,14 @@ +9(1d|z* z_F-_mz}24O2U?%o(ZLl}!Q$X;NGaHER@v10116W!ZQxMr+$avQ1(N*|^enmP7UzF3 z_?qBSZX`0V3J-C9wqb8=!xyghWY72*oV>0xxmSxrcr{6VCsP||CdS|7|4i}!u>Jkzrtc3YctDT|C2Y4U&C*p7|ZcePKcLaJg_{Ob^~>I%rzY zyWu;yLYyZgnzi~H_V}5)!WXZB>A&s6TPpKu{?&4P&;S6`*O%gE?_|PcVsHG>_BC$( z7O;M%O520DQ3g&BF8OdofMI&|6bMxaT=g|P7|fiy20%n{X)$pnVoN@|$&+?b%{L&a zn(7)0XA9)G+fuME$RV=`!eg~q18oL3vy}D zGf3`Cv-H8Z-=_;sMII0^XBh?wC;B#Zl2w+%jmCVZgyckL8G3BY3$3b4=BGUZT6t}G z);2H^B?bMgerX#jr$_D^x0Pg_5OGMFY8`iQr9pz8hOhRpM8{87y{K;jvFLtM$u{$% z!8gFZk$%#wzj-vxJ9Obj4Jct~Zgglh+lC9Ew!v!ukPhLv5)D-V?#|GOk`N8mVH8Nw z(=Qv0hkTTZhiUFh8!U=%xDx&G=S&*J=kSl2+2Uuky0*p<>{4;15GyD{9&$)l%h3cD ziBv%8Kt7r|57B&J{tB0=tu-T#dF5~*uZ+_buQ{PoqG+8lce8wB>>dk546%SG%0}BJ z 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 } + /** + * Loads PhpWord ${variable} from file. + * + * @param string $filename The name of the file + * + * @return array The extracted variables + */ + public static function extractVariables(string $filename, string $readerName = 'Word2007'): array + { + /** @var \PhpOffice\PhpWord\Reader\ReaderInterface $reader */ + $reader = self::createReader($readerName); + $document = $reader->load($filename); + $extractedVariables = []; + foreach ($document->getSections() as $section) { + $concatenatedText = ''; + foreach ($section->getElements() as $element) { + if ($element instanceof TextRun) { + foreach ($element->getElements() as $textElement) { + if ($textElement instanceof Text) { + $text = $textElement->getText(); + $concatenatedText .= $text; + } + } + } + } + preg_match_all('/\$\{([^}]+)\}/', $concatenatedText, $matches); + if (!empty($matches[1])) { + foreach ($matches[1] as $match) { + $trimmedMatch = trim($match); + $extractedVariables[] = $trimmedMatch; + } + } + } + + return $extractedVariables; + } + /** * Check if it's a concrete class (not abstract nor interface). * diff --git a/tests/PhpWordTests/IOFactoryTest.php b/tests/PhpWordTests/IOFactoryTest.php index ee8d7fe180..79f0fd0c76 100644 --- a/tests/PhpWordTests/IOFactoryTest.php +++ b/tests/PhpWordTests/IOFactoryTest.php @@ -116,4 +116,17 @@ public function testLoad(): void IOFactory::load($file) ); } + + /** + * Test for extractVariables method. + */ + public function testExtractVariables(): void + { + $file = __DIR__ . '/_files/templates/extract-variable.docx'; + $extractedVariables = IOFactory::extractVariables($file, 'Word2007'); + + $expectedVariables = ['date', 'A1', 'B1']; + + self::assertEquals($expectedVariables, $extractedVariables, 'Extracted variables do not match expected variables.'); + } } diff --git a/tests/PhpWordTests/_files/templates/extract-variable.docx b/tests/PhpWordTests/_files/templates/extract-variable.docx new file mode 100644 index 0000000000000000000000000000000000000000..f95ec61862f7b5bc97a8eb65f5f3ce24407dd88d GIT binary patch literal 12575 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 Date: Mon, 8 Jan 2024 01:25:37 -0800 Subject: [PATCH 182/246] Template Processor Persist File After Destruct (#2545) * Template Processor Persist File After Destruct Replace PR #2542. Fix #2539. Inadvertent break in TemplateProcessor behavior after #2475. Deleted temp file on destruct. It will now persist after destructor. * Update Change Log --- docs/changes/1.x/1.2.0.md | 3 +- docs/changes/2.x/2.0.0.md | 2 +- src/PhpWord/TemplateProcessor.php | 17 ++--- tests/PhpWordTests/TemplateProcessorTest.php | 73 +++++++++++--------- 4 files changed, 49 insertions(+), 46 deletions(-) diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index 265d25b033..7a4b09ea2d 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -64,4 +64,5 @@ ### BC Breaks -- Removed dependency `laminas/laminas-escaper` \ No newline at end of file +- Removed dependency `laminas/laminas-escaper` +- *Unintended Break* TemplateProcessor Does Not Persist File After Destruct. [#2539](https://github.com/PHPOffice/PHPWord/issues/2539) To be fixed by [#2545](https://github.com/PHPOffice/PHPWord/pull/2545 diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 74f2184155..575510b222 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -9,7 +9,7 @@ ### Bug fixes - MsDoc Reader : Correct Font Size Calculation by [@oleibman](https://github.com/oleibman) fixing [#2526](https://github.com/PHPOffice/PHPWord/issues/2526) in [#2531](https://github.com/PHPOffice/PHPWord/pull/2531) - +- TemplateProcessor Persist File After Destruct [@oleibman](https://github.com/oleibman) fixing [#2539](https://github.com/PHPOffice/PHPWord/issues/2539) in [#2545](https://github.com/PHPOffice/PHPWord/pull/2545) - bug: TemplateProcessor fix multiline values [@gimler](https://github.com/gimler) fixing [#268](https://github.com/PHPOffice/PHPWord/issues/268), [#2323](https://github.com/PHPOffice/PHPWord/issues/2323) and [#2486](https://github.com/PHPOffice/PHPWord/issues/2486) in [#2522](https://github.com/PHPOffice/PHPWord/pull/2522) ### Miscellaneous diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 27577499e5..8aee40c546 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -146,18 +146,6 @@ public function __destruct() // Nothing to do here. } } - // Temporary file - if ($this->tempDocumentFilename && file_exists($this->tempDocumentFilename)) { - unlink($this->tempDocumentFilename); - } - } - - public function __wakeup(): void - { - $this->tempDocumentFilename = ''; - $this->zipClass = null; - - throw new Exception('unserialize not permitted for this class'); } /** @@ -1506,4 +1494,9 @@ public function setMacroChars(string $macroOpeningChars, string $macroClosingCha self::$macroOpeningChars = $macroOpeningChars; self::$macroClosingChars = $macroClosingChars; } + + public function getTempDocumentFilename(): string + { + return $this->tempDocumentFilename; + } } diff --git a/tests/PhpWordTests/TemplateProcessorTest.php b/tests/PhpWordTests/TemplateProcessorTest.php index 65d5cfe9d8..49e88d1b5b 100644 --- a/tests/PhpWordTests/TemplateProcessorTest.php +++ b/tests/PhpWordTests/TemplateProcessorTest.php @@ -21,7 +21,6 @@ use Exception; use PhpOffice\PhpWord\Element\Text; use PhpOffice\PhpWord\Element\TextRun; -use PhpOffice\PhpWord\Exception\Exception as WordException; use PhpOffice\PhpWord\IOFactory; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Settings; @@ -38,14 +37,36 @@ */ final class TemplateProcessorTest extends \PHPUnit\Framework\TestCase { + /** @var ?TemplateProcessor */ + private $templateProcessor; + + private function getTemplateProcessor(string $filename): TemplateProcessor + { + $this->templateProcessor = new TemplateProcessor($filename); + + return $this->templateProcessor; + } + + protected function tearDown(): void + { + if ($this->templateProcessor !== null) { + $filename = $this->templateProcessor->getTempDocumentFilename(); + $this->templateProcessor = null; + if (file_exists($filename)) { + @unlink($filename); + } + } + } + /** * Construct test. * * @covers ::__construct + * @covers ::__destruct */ public function testTheConstruct(): void { - $object = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); + $object = $this->getTemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); self::assertInstanceOf('PhpOffice\\PhpWord\\TemplateProcessor', $object); self::assertEquals([], $object->getVariables()); } @@ -106,7 +127,7 @@ public function xtestTemplateCanBeSavedInTemporaryLocation(string $templateFqfn, public function testXslStyleSheetCanBeApplied(): void { $templateFqfn = __DIR__ . '/_files/templates/with_table_macros.docx'; - $templateProcessor = new TemplateProcessor($templateFqfn); + $templateProcessor = $this->getTemplateProcessor($templateFqfn); $actualDocumentFqfn = $this->xtestTemplateCanBeSavedInTemporaryLocation($templateFqfn, $templateProcessor); $expectedDocumentFqfn = __DIR__ . '/_files/documents/without_table_macros.docx'; @@ -150,7 +171,7 @@ public function testXslStyleSheetCanNotBeAppliedOnFailureOfSettingParameterValue $this->expectExceptionMessage('Could not set values for the given XSL style sheet parameters.'); } - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); $xslDomDocument = new DOMDocument(); $xslDomDocument->load(__DIR__ . '/_files/xsl/passthrough.xsl'); @@ -171,7 +192,7 @@ public function testXslStyleSheetCanNotBeAppliedOnFailureOfLoadingXmlFromTemplat { $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); $this->expectExceptionMessage('Could not load the given XML document.'); - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/corrupted_main_document_part.docx'); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/corrupted_main_document_part.docx'); $xslDomDocument = new DOMDocument(); $xslDomDocument->load(__DIR__ . '/_files/xsl/passthrough.xsl'); @@ -190,7 +211,7 @@ public function testXslStyleSheetCanNotBeAppliedOnFailureOfLoadingXmlFromTemplat */ public function testDeleteRow(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/delete-row.docx'); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/delete-row.docx'); self::assertEquals( ['deleteMe', 'deleteMeToo'], @@ -216,7 +237,7 @@ public function testDeleteRow(): void */ public function testCloneRow(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx'); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx'); self::assertEquals( ['tableHeader', 'userId', 'userName', 'userLocation'], @@ -240,7 +261,7 @@ public function testCloneRow(): void */ public function testCloneRowWithCustomMacro(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx'); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx'); $templateProcessor->setMacroOpeningChars('{#'); $templateProcessor->setMacroClosingChars('#}'); @@ -397,7 +418,7 @@ public function testCloneRowAndSetValuesWithCustomMacro(): void */ public function testMacrosCanBeReplacedInHeaderAndFooter(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx'); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx'); self::assertEquals(['documentContent', 'headerValue:100:100', 'footerValue'], $templateProcessor->getVariables()); @@ -418,7 +439,7 @@ public function testMacrosCanBeReplacedInHeaderAndFooter(): void */ public function testCustomMacrosCanBeReplacedInHeaderAndFooter(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer-with-custom-macro.docx'); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/header-footer-with-custom-macro.docx'); $templateProcessor->setMacroOpeningChars('{{'); $templateProcessor->setMacroClosingChars('}}'); @@ -440,7 +461,7 @@ public function testCustomMacrosCanBeReplacedInHeaderAndFooter(): void */ public function testSetValue(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx'); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx'); Settings::setOutputEscapingEnabled(true); $helloworld = "hello\nworld"; $templateProcessor->setValue('userName', $helloworld); @@ -455,7 +476,7 @@ public function testSetValue(): void */ public function testSetValueWithCustomMacro(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx'); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx'); $templateProcessor->setMacroChars('{#', '#}'); Settings::setOutputEscapingEnabled(true); $helloworld = "hello\nworld"; @@ -786,7 +807,7 @@ public function testSetCheckboxWithCustomMacro(): void */ public function testSetImageValue(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx'); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx'); $imagePath = __DIR__ . '/_files/images/earth.jpg'; $variablesReplace = [ @@ -866,7 +887,7 @@ public function testSetImageValue(): void */ public function testCloneDeleteBlock(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-delete-block.docx'); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/clone-delete-block.docx'); self::assertEquals( ['DELETEME', '/DELETEME', 'CLONEME', 'blockVariable', '/CLONEME'], @@ -906,7 +927,7 @@ public function testGetVariableCountCountsHowManyTimesEachPlaceholderIsPresent() $templatePath = 'test.docx'; $objWriter->save($templatePath); - $templateProcessor = new TemplateProcessor($templatePath); + $templateProcessor = $this->getTemplateProcessor($templatePath); $variableCount = $templateProcessor->getVariableCount(); unlink($templatePath); @@ -943,7 +964,7 @@ public function testGetVariableCountCountsHowManyTimesEachPlaceholderIsPresentWi $templatePath = 'test.docx'; $objWriter->save($templatePath); - $templateProcessor = new TemplateProcessor($templatePath); + $templateProcessor = $this->getTemplateProcessor($templatePath); $templateProcessor->setMacroChars('{{', '}}'); $variableCount = $templateProcessor->getVariableCount(); unlink($templatePath); @@ -981,7 +1002,7 @@ public function testCloneBlockCanCloneABlockTwice(): void $objWriter->save($templatePath); // replace placeholders and save the file - $templateProcessor = new TemplateProcessor($templatePath); + $templateProcessor = $this->getTemplateProcessor($templatePath); $templateProcessor->setValue('title', 'Some title'); $templateProcessor->cloneBlock('subreport', 2); $templateProcessor->setValue('subreport.id', '123', 1); @@ -1034,7 +1055,7 @@ public function testCloneBlockCanCloneABlockTwiceWithCustomMacro(): void $objWriter->save($templatePath); // replace placeholders and save the file - $templateProcessor = new TemplateProcessor($templatePath); + $templateProcessor = $this->getTemplateProcessor($templatePath); $templateProcessor->setMacroChars('{{', '}}'); $templateProcessor->setValue('title', 'Some title'); $templateProcessor->cloneBlock('subreport', 2); @@ -1323,7 +1344,7 @@ public function testFixBrokenMacrosWithCustomMacro(): void */ public function testMainPartNameDetection(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/document22-xml.docx'); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/document22-xml.docx'); $variables = ['test']; @@ -1335,7 +1356,7 @@ public function testMainPartNameDetection(): void */ public function testMainPartNameDetectionWithCustomMacro(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/document22-with-custom-macro-xml.docx'); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/document22-with-custom-macro-xml.docx'); $templateProcessor->setMacroOpeningChars('{#'); $templateProcessor->setMacroClosingChars('#}'); $variables = ['test']; @@ -1595,18 +1616,6 @@ public function testShouldMakeFieldsUpdateOnOpen(): void self::assertStringContainsString('', $templateProcessor->getSettingsPart()); } - /** - * Should not allow unserialize to avoid malware. - */ - public function testUnserialize(): void - { - $this->expectException(WordException::class); - $this->expectExceptionMessage('unserialize not permitted'); - $object = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); - $serialized = serialize($object); - $object2 = unserialize($serialized); - } - public function testShouldMakeFieldsUpdateOnOpenWithCustomMacro(): void { $settingsPart = ' From 2f4da6e491643c88f3c5d2892f5a63febb66b313 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Mon, 15 Jan 2024 11:24:22 -0800 Subject: [PATCH 183/246] Invalid Annotation in Test Member (#2549) * Invalid Annotation in Test Member PhpUnit cannot parse the `@covers` lines in FormulaTest; they result in warnings in Coverage and Deploy tests. This PR fixes them; no change log entry should be needed. * Fluke Failure PhpWordTest ran in such a way that `new PhpWord()` and `new DocInfo()` happened in different seconds. Almost impossible, but easy enough to prevent. --- tests/PhpWordTests/Element/FormulaTest.php | 6 +++--- tests/PhpWordTests/PhpWordTest.php | 11 +++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/PhpWordTests/Element/FormulaTest.php b/tests/PhpWordTests/Element/FormulaTest.php index fef5c2221e..7e368e8995 100644 --- a/tests/PhpWordTests/Element/FormulaTest.php +++ b/tests/PhpWordTests/Element/FormulaTest.php @@ -30,7 +30,7 @@ class FormulaTest extends AbstractWebServerEmbeddedTest { /** - * @covers \Formula::__construct + * @covers \PhpOffice\PhpWord\Element\Formula::__construct */ public function testConstruct(): void { @@ -40,8 +40,8 @@ public function testConstruct(): void } /** - * @covers \Formula::getMath - * @covers \Formula::setMath + * @covers \PhpOffice\PhpWord\Element\Formula::getMath + * @covers \PhpOffice\PhpWord\Element\Formula::setMath */ public function testMath(): void { diff --git a/tests/PhpWordTests/PhpWordTest.php b/tests/PhpWordTests/PhpWordTest.php index 7b756e7082..33118a11e8 100644 --- a/tests/PhpWordTests/PhpWordTest.php +++ b/tests/PhpWordTests/PhpWordTest.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWordTests; use BadMethodCallException; +use DateTimeImmutable; use PhpOffice\PhpWord\Metadata\DocInfo; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Settings; @@ -35,8 +36,14 @@ class PhpWordTest extends \PHPUnit\Framework\TestCase */ public function testConstruct(): void { - $phpWord = new PhpWord(); - self::assertEquals(new DocInfo(), $phpWord->getDocInfo()); + do { + $dtStart = new DateTimeImmutable(); + $startSecond = $dtStart->format('s'); + $phpWord = new PhpWord(); + $docInfo = new DocInfo(); + $endSecond = (new DateTimeImmutable('now'))->format('s'); + } while ($startSecond !== $endSecond); + self::assertEquals($docInfo, $phpWord->getDocInfo()); self::assertEquals(Settings::DEFAULT_FONT_NAME, $phpWord->getDefaultFontName()); self::assertEquals(Settings::DEFAULT_FONT_SIZE, $phpWord->getDefaultFontSize()); } From 8b891bb6842dd383f679b47898fad0b7c181f325 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Tue, 23 Jan 2024 09:15:27 -0800 Subject: [PATCH 184/246] Fix 32-bit Problem in PasswordEncoder (#2551) * Fix 32-bit Problem in PasswordEncoder Fix #2550. * Update change log --- docs/changes/2.x/2.0.0.md | 2 ++ src/PhpWord/Shared/Microsoft/PasswordEncoder.php | 11 +++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 575510b222..8214ded041 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -12,6 +12,8 @@ - TemplateProcessor Persist File After Destruct [@oleibman](https://github.com/oleibman) fixing [#2539](https://github.com/PHPOffice/PHPWord/issues/2539) in [#2545](https://github.com/PHPOffice/PHPWord/pull/2545) - bug: TemplateProcessor fix multiline values [@gimler](https://github.com/gimler) fixing [#268](https://github.com/PHPOffice/PHPWord/issues/268), [#2323](https://github.com/PHPOffice/PHPWord/issues/2323) and [#2486](https://github.com/PHPOffice/PHPWord/issues/2486) in [#2522](https://github.com/PHPOffice/PHPWord/pull/2522) +- 32-bit Problem in PasswordEncoder [@oleibman](https://github.com/oleibman) fixing [#2550](https://github.com/PHPOffice/PHPWord/issues/2550) in [#2551](https://github.com/PHPOffice/PHPWord/pull/2551) + ### Miscellaneous - Bump dompdf/dompdf from 2.0.3 to 2.0.4 by [@dependabot](https://github.com/dependabot) in [#2530](https://github.com/PHPOffice/PHPWord/pull/2530) diff --git a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php b/src/PhpWord/Shared/Microsoft/PasswordEncoder.php index 5ff42e49b9..d6cf69fc6d 100644 --- a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php +++ b/src/PhpWord/Shared/Microsoft/PasswordEncoder.php @@ -34,6 +34,9 @@ class PasswordEncoder const ALGORITHM_MAC = 'MAC'; const ALGORITHM_HMAC = 'HMAC'; + private const ALL_ONE_BITS = (PHP_INT_SIZE > 4) ? 0xFFFFFFFF : -1; + private const HIGH_ORDER_BIT = (PHP_INT_SIZE > 4) ? 0x80000000 : PHP_INT_MIN; + /** * Mapping between algorithm name and algorithm ID. * @@ -128,7 +131,7 @@ public static function hashPassword($password, $algorithmName = self::ALGORITHM_ // build low-order word and hig-order word and combine them $combinedKey = self::buildCombinedKey($byteChars); // build reversed hexadecimal string - $hex = str_pad(strtoupper(dechex($combinedKey & 0xFFFFFFFF)), 8, '0', \STR_PAD_LEFT); + $hex = str_pad(strtoupper(dechex($combinedKey & self::ALL_ONE_BITS)), 8, '0', \STR_PAD_LEFT); $reversedHex = $hex[6] . $hex[7] . $hex[4] . $hex[5] . $hex[2] . $hex[3] . $hex[0] . $hex[1]; $generatedKey = mb_convert_encoding($reversedHex, 'UCS-2LE', 'UTF-8'); @@ -232,10 +235,10 @@ private static function buildCombinedKey($byteChars) */ private static function int32($value) { - $value = ($value & 0xFFFFFFFF); + $value = $value & self::ALL_ONE_BITS; - if ($value & 0x80000000) { - $value = -((~$value & 0xFFFFFFFF) + 1); + if ($value & self::HIGH_ORDER_BIT) { + $value = -((~$value & self::ALL_ONE_BITS) + 1); } return $value; From 2daa50c6f34c9cb6c532f72350e4bd8d466d6c71 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 15 May 2024 13:26:52 +0200 Subject: [PATCH 185/246] Improved Issue Template (#2609) --- .github/ISSUE_TEMPLATE/1_bug_report.yml | 65 ++++++++++++++++++++ .github/ISSUE_TEMPLATE/2_feature_request.yml | 35 +++++++++++ .github/ISSUE_TEMPLATE/bug_report.md | 38 ------------ .github/ISSUE_TEMPLATE/feature_request.md | 22 ------- .github/ISSUE_TEMPLATE/how-to-use.md | 14 ----- .github/PULL_REQUEST_TEMPLATE.md | 7 ++- docs/changes/2.x/2.0.0.md | 3 +- 7 files changed, 106 insertions(+), 78 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/1_bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/2_feature_request.yml delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md delete mode 100644 .github/ISSUE_TEMPLATE/how-to-use.md diff --git a/.github/ISSUE_TEMPLATE/1_bug_report.yml b/.github/ISSUE_TEMPLATE/1_bug_report.yml new file mode 100644 index 0000000000..ea335468a5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1_bug_report.yml @@ -0,0 +1,65 @@ +name: 🐛 Bug Report +description: Create a report to help improve PHPWord +labels: [ "Bug Report" ] +body: + - type: markdown + attributes: + value: | + ### ❗️ Read this before submitting your bug report: + - **Write in English/French.** Reports in all other languages will be closed. + - **Provide as much detail as possible** + - Attachments : Error logs, Screenshots, Document files (generated and expected). + - If the issue cannot be reproduced, it cannot be fixed. + - type: textarea + id: what-happened + attributes: + label: Describe the bug and add attachments + description: What went wrong? If possible, add screenshots, error logs, document files (generated and expected) or screen recordings to help explain your problem. + validations: + required: true + - type: textarea + id: expected-behavior + attributes: + label: Expected behavior + description: A clear and concise description of what you expected to happen. + validations: + required: true + - type: textarea + id: steps-reproduce + attributes: + label: Steps to reproduce + description: Please provide a code sample that reproduces the issue. + placeholder: | + ```php + addSection(); + $section->... + ``` + validations: + required: true + - type: input + id: phpword-version + attributes: + label: PHPWord version(s) where the bug happened + placeholder: "e.g., 1.2.0 or master" + validations: + required: true + - type: input + id: php-version + attributes: + label: PHP version(s) where the bug happened + placeholder: "e.g., 7.1 or 8.2" + validations: + required: true + - type: checkboxes + attributes: + label: Priority + description: Funded tickets have a higher priority. + options: + - label: I want to crowdfund the bug fix (with [@algora-io](https://docs.algora.io/bounties/overview)) and fund a community developer. + required: false + - label: I want to pay the bug fix and fund a maintainer for that. (Contact @Progi1984) + required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/2_feature_request.yml b/.github/ISSUE_TEMPLATE/2_feature_request.yml new file mode 100644 index 0000000000..bf3539c372 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2_feature_request.yml @@ -0,0 +1,35 @@ +name: 💡 Feature request +description: Suggest an idea for this project +labels: [ "Change Request" ] +body: + - type: markdown + attributes: + value: | + ### ❗️ Read this before submitting your bug report: + - **Write in English/French.** Reports in all other languages will be closed. + - **Provide as much detail as possible** + - Attachments : Error logs, Screenshots, Document files (generated and expected). + - If the issue cannot be reproduced, it cannot be fixed. + - type: textarea + id: problem + attributes: + label: Describe the problem + description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + validations: + required: true + - type: textarea + id: expected-behavior + attributes: + label: Describe the expected behavior + description: A clear and concise description of what you expected to happen. If possible, add screenshots, document files (expected). + validations: + required: true + - type: checkboxes + attributes: + label: Priority + description: Funded tickets have a higher priority. + options: + - label: I want to crowdfund the feature (with [@algora-io](https://docs.algora.io/bounties/overview)) and fund a community developer. + required: false + - label: I want to pay the feature and fund a maintainer for that. (Contact @Progi1984) + required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index fcb3a65db1..0000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -name: Bug report -about: Create a report to help improve PHPWord -labels: Bug Report - ---- - -### Describe the Bug - -A clear and concise description of what the bug is. - -### Steps to Reproduce - -Please provide a code sample that reproduces the issue. - -```php -addSection(); -$section->... -``` - -### Expected Behavior - -A clear and concise description of what you expected to happen. - -### Current Behavior - -What is the current behavior? - -### Context - -Please fill in your environment information: - -- PHP Version: -- PHPWord Version: diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 171e8378e1..0000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -labels: Change Request - ---- - -### Is your feature request related to a problem? Please describe. - -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -### Describe the solution you'd like - -A clear and concise description of what you want to happen. - -### Describe alternatives you've considered - -A clear and concise description of any alternative solutions or features you've considered. - -### Additional context - -Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/how-to-use.md b/.github/ISSUE_TEMPLATE/how-to-use.md deleted file mode 100644 index 85cc47072e..0000000000 --- a/.github/ISSUE_TEMPLATE/how-to-use.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: How to Use PHPWord -about: Find out how to use PHPWord -labels: WontFix - ---- - -***Please do not use the issue tracker to ask how to use PHPWord.*** - -Documentation is available on [Read the Docs](https://phpword.readthedocs.io/en/latest/). - -Sample code is in the [`/samples/` directory](https://github.com/PHPOffice/PHPWord/tree/master/samples). - -Usage questions belong on [Stack Overflow](https://stackoverflow.com/questions/tagged/phpword). diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 5430a996ec..ce201f8bb6 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -6,6 +6,7 @@ Fixes # (issue) ### Checklist: -- [ ] I have run `composer run-script check --timeout=0` and no errors were reported -- [ ] The new code is covered by unit tests (check build/coverage for coverage report) -- [ ] I have updated the documentation to describe the changes +- [ ] My CI is :green_circle: +- [ ] I have covered by unit tests my new code (check build/coverage for coverage report) +- [ ] I have updated the [documentation](https://github.com/PHPOffice/PHPWord/tree/master/docs) to describe the changes +- [ ] I have updated the [changelog](https://github.com/PHPOffice/PHPWord/blob/master/docs/changes/2.x/2.0.0.md) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 8214ded041..c5fbaf4b52 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -22,6 +22,7 @@ - Bump phpmd/phpmd from 2.14.1 to 2.15.0 by [@dependabot](https://github.com/dependabot) in [#2538](https://github.com/PHPOffice/PHPWord/pull/2538) - Bump phpunit/phpunit from 9.6.14 to 9.6.15 by [@dependabot](https://github.com/dependabot) in [#2537](https://github.com/PHPOffice/PHPWord/pull/2537) - Bump symfony/process from 5.4.28 to 5.4.34 by [@dependabot](https://github.com/dependabot) in [#2536](https://github.com/PHPOffice/PHPWord/pull/2536) -- Allow rgb() when converting Html [@oleibman](https://github.com/oleibman) fixing [#2508](https://github.com/PHPOffice/PHPWord/issues/2508) in [#2512](https://github.com/PHPOffice/PHPWord/pull/2512) +- Allow rgb() when converting Html by [@oleibman](https://github.com/oleibman) fixing [#2508](https://github.com/PHPOffice/PHPWord/issues/2508) in [#2512](https://github.com/PHPOffice/PHPWord/pull/2512) +- Improved Issue Template by [@Progi1984](https://github.com/Progi1984) in [#2609](https://github.com/PHPOffice/PHPWord/pull/2609) ### BC Breaks From f9ce80473fb6116e84fd8ae9b2460a0469b7e5f2 Mon Sep 17 00:00:00 2001 From: Matthew Setter Date: Wed, 7 Aug 2024 17:08:23 +1000 Subject: [PATCH 186/246] Extend the Options section of the PDF Writer documentation (#2642) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Extend the Options section of the PDF Writer documentation When I used PHPWord to write a PDF document, recently, I followed the docs only to find that I also had to specify a PDF renderer — otherwise the operation failed. After a bit of research to figure out what to do to specify one, I thought it only right to document what I learned in the official documentation. * Update the docs changelog detailing the PDF Writer additions This change updates the changelog to include the enhancement made to the PDF Writer docs that show how to specify a PDF renderer when working with the PDF writer. * Fixed docs --------- Co-authored-by: Progi1984 --- docs/changes/2.x/2.0.0.md | 1 + docs/usage/writers.md | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index c5fbaf4b52..18f9267f39 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -5,6 +5,7 @@ ## Enhancements - IOFactory : Added extractVariables method to extract variables from a document [@sibalonat](https://github.com/sibalonat) in [#2515](https://github.com/PHPOffice/PHPWord/pull/2515) +- PDF Writer : Documented how to specify a PDF renderer, when working with the PDF writer, as well as the three available choices by [@settermjd](https://github.com/settermjd) in [#2642](https://github.com/PHPOffice/PHPWord/pull/2642) ### Bug fixes diff --git a/docs/usage/writers.md b/docs/usage/writers.md index 81fb2b99b4..f561345a95 100644 --- a/docs/usage/writers.md +++ b/docs/usage/writers.md @@ -87,6 +87,29 @@ $writer = IOFactory::createWriter($oPhpWord, 'PDF'); $writer->save(__DIR__ . '/sample.pdf'); ``` +#### Specify the PDF Renderer + +Before PHPWord can write a PDF, you **must** specify the renderer to use and the path to it. +Currently, three renderers are supported: + +- [DomPDF](https://github.com/dompdf/dompdf) +- [MPDF](https://mpdf.github.io/) +- [TCPDF](https://tcpdf.org/) + +To specify the renderer you use two static `Settings` functions: + +- `setPdfRendererName`: This sets the name of the renderer library to use. + Provide one of [`Settings`' three `PDF_` constants](https://github.com/PHPOffice/PHPWord/blob/master/src/PhpWord/Settings.php#L39-L41) to the function call. +- `setPdfRendererPath`: This sets the path to the renderer library. + This directory is the renderer's package directory within Composer's _vendor_ directory. + +In the code below, you can see an example of setting MPDF as the desired PDF renderer. + +```php +Settings::setPdfRendererName(Settings::PDF_RENDERER_MPDF); +Settings::setPdfRendererPath(__DIR__ . '/../vendor/mpdf/mpdf'); +``` + ## RTF The name of the writer is `RTF`. From 8e441e8ae00b76b32dd39aa427c0a89b26381cf7 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Wed, 7 Aug 2024 04:21:28 -0700 Subject: [PATCH 187/246] Php7 Problem with TemplateProcessor Destructor (#2554) Fix #2548. A particularly perplexing problem accidentally introduced by PR #2475. Problem does not arise for Php8, and does not arise for Php7 unit tests. But, running *not* under Phpunit auspices with Php7 can cause a warning message at destructor time if the `save` function has been used. A very artificial test is introduced to test this situation. --- docs/changes/2.x/2.0.0.md | 1 + src/PhpWord/Shared/ZipArchive.php | 10 +++++++--- tests/PhpWordTests/TemplateProcessorTest.php | 10 ++++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 18f9267f39..cdd6b7b49d 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -11,6 +11,7 @@ - MsDoc Reader : Correct Font Size Calculation by [@oleibman](https://github.com/oleibman) fixing [#2526](https://github.com/PHPOffice/PHPWord/issues/2526) in [#2531](https://github.com/PHPOffice/PHPWord/pull/2531) - TemplateProcessor Persist File After Destruct [@oleibman](https://github.com/oleibman) fixing [#2539](https://github.com/PHPOffice/PHPWord/issues/2539) in [#2545](https://github.com/PHPOffice/PHPWord/pull/2545) +- TemplateProcessor Destructor Problem with Php7 [@oleibman](https://github.com/oleibman) fixing [#2548](https://github.com/PHPOffice/PHPWord/issues/2548) in [#2554](https://github.com/PHPOffice/PHPWord/pull/2554) - bug: TemplateProcessor fix multiline values [@gimler](https://github.com/gimler) fixing [#268](https://github.com/PHPOffice/PHPWord/issues/268), [#2323](https://github.com/PHPOffice/PHPWord/issues/2323) and [#2486](https://github.com/PHPOffice/PHPWord/issues/2486) in [#2522](https://github.com/PHPOffice/PHPWord/pull/2522) - 32-bit Problem in PasswordEncoder [@oleibman](https://github.com/oleibman) fixing [#2550](https://github.com/PHPOffice/PHPWord/issues/2550) in [#2551](https://github.com/PHPOffice/PHPWord/pull/2551) diff --git a/src/PhpWord/Shared/ZipArchive.php b/src/PhpWord/Shared/ZipArchive.php index ce4d22533e..f120756d8b 100644 --- a/src/PhpWord/Shared/ZipArchive.php +++ b/src/PhpWord/Shared/ZipArchive.php @@ -20,6 +20,7 @@ use PclZip; use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\Settings; +use Throwable; /** * ZipArchive wrapper. @@ -162,13 +163,16 @@ public function open($filename, $flags = null) * Close the active archive. * * @return bool - * - * @codeCoverageIgnore Can't find any test case. Uncomment when found. */ public function close() { if (!$this->usePclzip) { - if ($this->zip->close() === false) { + try { + $result = @$this->zip->close(); + } catch (Throwable $e) { + $result = false; + } + if ($result === false) { throw new Exception("Could not close zip file {$this->filename}: "); } } diff --git a/tests/PhpWordTests/TemplateProcessorTest.php b/tests/PhpWordTests/TemplateProcessorTest.php index 49e88d1b5b..b8ad970ced 100644 --- a/tests/PhpWordTests/TemplateProcessorTest.php +++ b/tests/PhpWordTests/TemplateProcessorTest.php @@ -25,6 +25,7 @@ use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\TemplateProcessor; +use Throwable; use TypeError; use ZipArchive; @@ -63,12 +64,21 @@ protected function tearDown(): void * * @covers ::__construct * @covers ::__destruct + * @covers \PhpOffice\PhpWord\Shared\ZipArchive::close */ public function testTheConstruct(): void { $object = $this->getTemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); self::assertInstanceOf('PhpOffice\\PhpWord\\TemplateProcessor', $object); self::assertEquals([], $object->getVariables()); + $object->save(); + + try { + $object->zip()->close(); + self::fail('Expected exception for double close'); + } catch (Throwable $e) { + // nothing to do here + } } /** From 7084019cd47e38d4a9fcde4edc70f6979556f03c Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Wed, 7 Aug 2024 04:26:02 -0700 Subject: [PATCH 188/246] Generate Table Cell if Row Doesn't Have Any (#2516) * Generate Table Cell if Row Doesn't Have Any Fix #2505. Word treats file as corrupt if a table row does not contain a cell (documentation for why this is so is included in the issue). Person reporting the issue suggests that dropping such a row from the output file is preferred. However, I think generating an empty cell instead is closer to the user's expectation. For example, as demonstrated in the unit tests added with this PR, if a table has row 1 and 3 which contain cells, but row 2 does not, the table as written to the file will have 3 rows, with the second containing an empty cell. * Remove Commented-Out Code in Tests --- docs/changes/2.x/2.0.0.md | 3 +- src/PhpWord/Writer/Word2007/Element/Table.php | 10 +- .../Writer/Word2007/Element/TableTest.php | 147 ++++++++++++++++++ 3 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 tests/PhpWordTests/Writer/Word2007/Element/TableTest.php diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index cdd6b7b49d..c0423d8caf 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -10,10 +10,11 @@ ### Bug fixes - MsDoc Reader : Correct Font Size Calculation by [@oleibman](https://github.com/oleibman) fixing [#2526](https://github.com/PHPOffice/PHPWord/issues/2526) in [#2531](https://github.com/PHPOffice/PHPWord/pull/2531) +- Html Reader : Process Titles as Headings not Paragraphs [@0b10011](https://github.com/0b10011) and [@oleibman](https://github.com/oleibman) Issue [#1692](https://github.com/PHPOffice/PHPWord/issues/1692) PR [#2533](https://github.com/PHPOffice/PHPWord/pull/2533) +- Generate Table Cell if Row Doesn't Have Any [@oleibman](https://github.com/oleibman) fixing [#2505](https://github.com/PHPOffice/PHPWord/issues/2505) in [#2516](https://github.com/PHPOffice/PHPWord/pull/2516) - TemplateProcessor Persist File After Destruct [@oleibman](https://github.com/oleibman) fixing [#2539](https://github.com/PHPOffice/PHPWord/issues/2539) in [#2545](https://github.com/PHPOffice/PHPWord/pull/2545) - TemplateProcessor Destructor Problem with Php7 [@oleibman](https://github.com/oleibman) fixing [#2548](https://github.com/PHPOffice/PHPWord/issues/2548) in [#2554](https://github.com/PHPOffice/PHPWord/pull/2554) - bug: TemplateProcessor fix multiline values [@gimler](https://github.com/gimler) fixing [#268](https://github.com/PHPOffice/PHPWord/issues/268), [#2323](https://github.com/PHPOffice/PHPWord/issues/2323) and [#2486](https://github.com/PHPOffice/PHPWord/issues/2486) in [#2522](https://github.com/PHPOffice/PHPWord/pull/2522) - - 32-bit Problem in PasswordEncoder [@oleibman](https://github.com/oleibman) fixing [#2550](https://github.com/PHPOffice/PHPWord/issues/2550) in [#2551](https://github.com/PHPOffice/PHPWord/pull/2551) ### Miscellaneous diff --git a/src/PhpWord/Writer/Word2007/Element/Table.php b/src/PhpWord/Writer/Word2007/Element/Table.php index 9364fe45c1..a32cc19639 100644 --- a/src/PhpWord/Writer/Word2007/Element/Table.php +++ b/src/PhpWord/Writer/Word2007/Element/Table.php @@ -103,8 +103,14 @@ private function writeRow(XMLWriter $xmlWriter, RowElement $row): void } // Write cells - foreach ($row->getCells() as $cell) { - $this->writeCell($xmlWriter, $cell); + $cells = $row->getCells(); + if (count($cells) === 0) { + // issue 2505 - Word treats doc as corrupt if row without cell + $this->writeCell($xmlWriter, new CellElement()); + } else { + foreach ($cells as $cell) { + $this->writeCell($xmlWriter, $cell); + } } $xmlWriter->endElement(); // w:tr diff --git a/tests/PhpWordTests/Writer/Word2007/Element/TableTest.php b/tests/PhpWordTests/Writer/Word2007/Element/TableTest.php new file mode 100644 index 0000000000..57010893ae --- /dev/null +++ b/tests/PhpWordTests/Writer/Word2007/Element/TableTest.php @@ -0,0 +1,147 @@ +addSection(); + $section->addText('Before table (normal).'); + $table = $section->addTable(['width' => 5000, 'unit' => TblWidth::PERCENT]); + $row = $table->addRow(); + $tc = $table->addCell(); + $tc->addText('R1C1'); + $tc = $table->addCell(); + $tc->addText('R1C2'); + $row = $table->addRow(); + $tc = $table->addCell(); + $tc->addText('R2C1'); + $tc = $table->addCell(); + $tc->addText('R2C2'); + $row = $table->addRow(); + $tc = $table->addCell(); + $tc->addText('R3C1'); + $tc = $table->addCell(); + $tc->addText('R3C2'); + $section->addText('After table.'); + + $doc = TestHelperDOCX::getDocument($phpWord); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl[2]'), 'should be only 1 table'); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc[2]')); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc[3]')); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]/w:tc')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]/w:tc[2]')); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]/w:tc[3]')); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]/w:tc')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]/w:tc[2]')); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]/w:tc[3]')); + } + + public static function testSomeRowWithNoCells(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $section->addText('Before table (row 2 has no cells).'); + $table = $section->addTable(['width' => 5000, 'unit' => TblWidth::PERCENT]); + $row = $table->addRow(); + $tc = $table->addCell(); + $tc->addText('R1C1'); + $tc = $table->addCell(); + $tc->addText('R1C2'); + $row = $table->addRow(); + $row = $table->addRow(); + $tc = $table->addCell(); + $tc->addText('R3C1'); + $tc = $table->addCell(); + $tc->addText('R3C2'); + $section->addText('After table.'); + + $doc = TestHelperDOCX::getDocument($phpWord); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl[2]'), 'should be only 1 table'); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc[2]')); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc[3]')); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]/w:tc')); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]/w:tc[2]')); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]/w:tc')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]/w:tc[2]')); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]/w:tc[3]')); + } + + public static function testOnly1RowWithNoCells(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $section->addText('Before table (only 1 row and it has no cells).'); + $table = $section->addTable(['width' => 5000, 'unit' => TblWidth::PERCENT]); + $row = $table->addRow(); + $section->addText('After table.'); + + $doc = TestHelperDOCX::getDocument($phpWord); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl[2]'), 'only 1 table should be written'); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc')); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc[2]')); + + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]')); + } + + public static function testNoRows(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $section->addText('Before table (no rows therefore omitted).'); + $table = $section->addTable(['width' => 5000, 'unit' => TblWidth::PERCENT]); + $section->addText('After table.'); + + $doc = TestHelperDOCX::getDocument($phpWord); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl[1]'), 'no table should be written'); + } +} From b99230a3c058b89f22d0247e260bc8e4ec9b1d86 Mon Sep 17 00:00:00 2001 From: Guillaume Lafarge <670645+glafarge@users.noreply.github.com> Date: Wed, 7 Aug 2024 18:45:59 +0200 Subject: [PATCH 189/246] [TYPO] Fix hardcoded macro chars in TemplateProcessor method (#2618) * Fix hardcoded macro chars * Update changelog --------- Co-authored-by: glafarge --- docs/changes/2.x/2.0.0.md | 1 + src/PhpWord/TemplateProcessor.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index c0423d8caf..2d4b3b9cca 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -16,6 +16,7 @@ - TemplateProcessor Destructor Problem with Php7 [@oleibman](https://github.com/oleibman) fixing [#2548](https://github.com/PHPOffice/PHPWord/issues/2548) in [#2554](https://github.com/PHPOffice/PHPWord/pull/2554) - bug: TemplateProcessor fix multiline values [@gimler](https://github.com/gimler) fixing [#268](https://github.com/PHPOffice/PHPWord/issues/268), [#2323](https://github.com/PHPOffice/PHPWord/issues/2323) and [#2486](https://github.com/PHPOffice/PHPWord/issues/2486) in [#2522](https://github.com/PHPOffice/PHPWord/pull/2522) - 32-bit Problem in PasswordEncoder [@oleibman](https://github.com/oleibman) fixing [#2550](https://github.com/PHPOffice/PHPWord/issues/2550) in [#2551](https://github.com/PHPOffice/PHPWord/pull/2551) +- Typo : Fix hardcoded macro chars in TemplateProcessor method [@glafarge](https://github.com/glafarge) in [#2618](https://github.com/PHPOffice/PHPWord/pull/2618) ### Miscellaneous diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 8aee40c546..900169bd68 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -805,8 +805,8 @@ public function cloneRow($search, $numberOfClones): void */ public function deleteRow(string $search): void { - if ('${' !== substr($search, 0, 2) && '}' !== substr($search, -1)) { - $search = '${' . $search . '}'; + if (self::$macroOpeningChars !== substr($search, 0, 2) && self::$macroClosingChars !== substr($search, -1)) { + $search = self::$macroOpeningChars . $search . self::$macroClosingChars; } $tagPos = strpos($this->tempDocumentMainPart, $search); From 761280bb71a3171a31a875e5bf2cb0ae97021139 Mon Sep 17 00:00:00 2001 From: Mark McEver Date: Thu, 8 Aug 2024 09:53:04 -0500 Subject: [PATCH 190/246] Prevented fatal errors when opening corrupt files or "doc" files (#2626) * Prevented fatal errors when opening corrupt files or "doc" files * Ran php-cs-fixer * Fixed phpstan errors * Updated the change log --- docs/changes/2.x/2.0.0.md | 1 + src/PhpWord/Shared/XMLReader.php | 10 +++++++- tests/PhpWordTests/Shared/XMLReaderTest.php | 27 +++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 2d4b3b9cca..bb4eadec99 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -17,6 +17,7 @@ - bug: TemplateProcessor fix multiline values [@gimler](https://github.com/gimler) fixing [#268](https://github.com/PHPOffice/PHPWord/issues/268), [#2323](https://github.com/PHPOffice/PHPWord/issues/2323) and [#2486](https://github.com/PHPOffice/PHPWord/issues/2486) in [#2522](https://github.com/PHPOffice/PHPWord/pull/2522) - 32-bit Problem in PasswordEncoder [@oleibman](https://github.com/oleibman) fixing [#2550](https://github.com/PHPOffice/PHPWord/issues/2550) in [#2551](https://github.com/PHPOffice/PHPWord/pull/2551) - Typo : Fix hardcoded macro chars in TemplateProcessor method [@glafarge](https://github.com/glafarge) in [#2618](https://github.com/PHPOffice/PHPWord/pull/2618) +- XML Reader : Prevent fatal errors when opening corrupt files or "doc" files [@mmcev106](https://github.com/mmcev106) in [#2626](https://github.com/PHPOffice/PHPWord/pull/2626) ### Miscellaneous diff --git a/src/PhpWord/Shared/XMLReader.php b/src/PhpWord/Shared/XMLReader.php index 1c95a64426..e836607d29 100644 --- a/src/PhpWord/Shared/XMLReader.php +++ b/src/PhpWord/Shared/XMLReader.php @@ -61,7 +61,15 @@ public function getDomFromZip($zipFile, $xmlFile) } $zip = new ZipArchive(); - $zip->open($zipFile); + $openStatus = $zip->open($zipFile); + if ($openStatus !== true) { + /** + * Throw an exception since making further calls on the ZipArchive would cause a fatal error. + * This prevents fatal errors on corrupt archives and attempts to open old "doc" files. + */ + throw new Exception("The archive failed to load with the following error code: $openStatus"); + } + $content = $zip->getFromName(ltrim($xmlFile, '/')); $zip->close(); diff --git a/tests/PhpWordTests/Shared/XMLReaderTest.php b/tests/PhpWordTests/Shared/XMLReaderTest.php index 4cbe92a5e2..cc15c85f01 100644 --- a/tests/PhpWordTests/Shared/XMLReaderTest.php +++ b/tests/PhpWordTests/Shared/XMLReaderTest.php @@ -85,6 +85,33 @@ public function testThrowsExceptionOnNonExistingArchive(): void $reader->getDomFromZip($archiveFile, 'test.xml'); } + /** + * Test that read from invalid archive throws exception. + */ + public function testThrowsExceptionOnZipArchiveOpenErrors(): void + { + /** + * @var string + */ + $tempPath = tempnam(sys_get_temp_dir(), 'PhpWord'); + + // Simulate a corrupt archive + file_put_contents($tempPath, mt_rand()); + + $exceptionMessage = null; + + try { + $reader = new XMLReader(); + $reader->getDomFromZip($tempPath, 'test.xml'); + } catch (Exception $e) { + $exceptionMessage = $e->getMessage(); + } + + self::assertNotNull($exceptionMessage); + + unlink($tempPath); + } + /** * Test elements count. */ From 9c9382a75cdb2b71eb0dcec55f5dde9505492baa Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Mon, 12 Aug 2024 10:03:49 +0200 Subject: [PATCH 191/246] Bump phpoffice/math from 0.1.0 to 0.2.0 (#2645) --- composer.json | 2 +- composer.lock | 17 ++++++++--------- docs/changes/2.x/2.0.0.md | 1 + 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/composer.json b/composer.json index 7e0deaa092..bce0f4b8f4 100644 --- a/composer.json +++ b/composer.json @@ -68,7 +68,7 @@ "ext-dom": "*", "ext-json": "*", "ext-xml": "*", - "phpoffice/math": "^0.1" + "phpoffice/math": "^0.2" }, "require-dev": { "ext-zip": "*", diff --git a/composer.lock b/composer.lock index 6eb3324ccb..587491c588 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8d0272c1442e11290de55a7947fc849c", + "content-hash": "15c1d733e1ddd2f424af0383ceb28dfd", "packages": [ { "name": "phpoffice/math", - "version": "0.1.0", + "version": "0.2.0", "source": { "type": "git", "url": "https://github.com/PHPOffice/Math.git", - "reference": "f0f8cad98624459c540cdd61d2a174d834471773" + "reference": "fc2eb6d1a61b058d5dac77197059db30ee3c8329" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/Math/zipball/f0f8cad98624459c540cdd61d2a174d834471773", - "reference": "f0f8cad98624459c540cdd61d2a174d834471773", + "url": "https://api.github.com/repos/PHPOffice/Math/zipball/fc2eb6d1a61b058d5dac77197059db30ee3c8329", + "reference": "fc2eb6d1a61b058d5dac77197059db30ee3c8329", "shasum": "" }, "require": { @@ -32,8 +32,7 @@ "type": "library", "autoload": { "psr-4": { - "PhpOffice\\Math\\": "src/Math/", - "Tests\\PhpOffice\\Math\\": "tests/Math/" + "PhpOffice\\Math\\": "src/Math/" } }, "notification-url": "https://packagist.org/downloads/", @@ -55,9 +54,9 @@ ], "support": { "issues": "https://github.com/PHPOffice/Math/issues", - "source": "https://github.com/PHPOffice/Math/tree/0.1.0" + "source": "https://github.com/PHPOffice/Math/tree/0.2.0" }, - "time": "2023-09-25T12:08:20+00:00" + "time": "2024-08-12T07:30:45+00:00" } ], "packages-dev": [ diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index bb4eadec99..8a3ef6c82d 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -29,5 +29,6 @@ - Bump symfony/process from 5.4.28 to 5.4.34 by [@dependabot](https://github.com/dependabot) in [#2536](https://github.com/PHPOffice/PHPWord/pull/2536) - Allow rgb() when converting Html by [@oleibman](https://github.com/oleibman) fixing [#2508](https://github.com/PHPOffice/PHPWord/issues/2508) in [#2512](https://github.com/PHPOffice/PHPWord/pull/2512) - Improved Issue Template by [@Progi1984](https://github.com/Progi1984) in [#2609](https://github.com/PHPOffice/PHPWord/pull/2609) +- Bump phpoffice/math from 0.1.0 to 0.2.0 by [@Progi1984](https://github.com/Progi1984) fixing [#2559](https://github.com/PHPOffice/PHPWord/issues/2559) in [#2645](https://github.com/PHPOffice/PHPWord/pull/2645) ### BC Breaks From 997a82996d02c6480939a72d1e4970deb4477b8c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 10:47:44 +0200 Subject: [PATCH 192/246] Bump tecnickcom/tcpdf from 6.6.5 to 6.7.5 (#2646) * Bump tecnickcom/tcpdf from 6.6.5 to 6.7.5 Bumps [tecnickcom/tcpdf](https://github.com/tecnickcom/TCPDF) from 6.6.5 to 6.7.5. - [Changelog](https://github.com/tecnickcom/TCPDF/blob/main/CHANGELOG.TXT) - [Commits](https://github.com/tecnickcom/TCPDF/commits/6.7.5) --- updated-dependencies: - dependency-name: tecnickcom/tcpdf dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Updated changelog --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Progi1984 --- composer.lock | 14 +++++++------- docs/changes/2.x/2.0.0.md | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index 587491c588..6a1df276c9 100644 --- a/composer.lock +++ b/composer.lock @@ -4935,20 +4935,20 @@ }, { "name": "tecnickcom/tcpdf", - "version": "6.6.5", + "version": "6.7.5", "source": { "type": "git", "url": "https://github.com/tecnickcom/TCPDF.git", - "reference": "5fce932fcee4371865314ab7f6c0d85423c5c7ce" + "reference": "951eabf0338ec2522bd0d5d9c79b08a3a3d36b36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/5fce932fcee4371865314ab7f6c0d85423c5c7ce", - "reference": "5fce932fcee4371865314ab7f6c0d85423c5c7ce", + "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/951eabf0338ec2522bd0d5d9c79b08a3a3d36b36", + "reference": "951eabf0338ec2522bd0d5d9c79b08a3a3d36b36", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.5.0" }, "type": "library", "autoload": { @@ -4995,7 +4995,7 @@ ], "support": { "issues": "https://github.com/tecnickcom/TCPDF/issues", - "source": "https://github.com/tecnickcom/TCPDF/tree/6.6.5" + "source": "https://github.com/tecnickcom/TCPDF/tree/6.7.5" }, "funding": [ { @@ -5003,7 +5003,7 @@ "type": "custom" } ], - "time": "2023-09-06T15:09:26+00:00" + "time": "2024-04-20T17:25:10+00:00" }, { "name": "theseer/tokenizer", diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 8a3ef6c82d..09a4feb5d8 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -30,5 +30,6 @@ - Allow rgb() when converting Html by [@oleibman](https://github.com/oleibman) fixing [#2508](https://github.com/PHPOffice/PHPWord/issues/2508) in [#2512](https://github.com/PHPOffice/PHPWord/pull/2512) - Improved Issue Template by [@Progi1984](https://github.com/Progi1984) in [#2609](https://github.com/PHPOffice/PHPWord/pull/2609) - Bump phpoffice/math from 0.1.0 to 0.2.0 by [@Progi1984](https://github.com/Progi1984) fixing [#2559](https://github.com/PHPOffice/PHPWord/issues/2559) in [#2645](https://github.com/PHPOffice/PHPWord/pull/2645) +- Bump tecnickcom/tcpdf from 6.6.5 to 6.7.5 by [@dependabot](https://github.com/dependabot) in [#2646](https://github.com/PHPOffice/PHPWord/pull/2646) ### BC Breaks From fbe52dcd842ccbfc6f3974535ba2ed9bc4ad8128 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Mon, 12 Aug 2024 11:04:34 +0200 Subject: [PATCH 193/246] Documentation : Updated Comment element (#2650) Fix error on comments code snippet. Co-authored-by: laminga <39699385+laminga@users.noreply.github.com> --- docs/changes/2.x/2.0.0.md | 1 + docs/usage/elements/comment.md | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 09a4feb5d8..3e3e55807d 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -18,6 +18,7 @@ - 32-bit Problem in PasswordEncoder [@oleibman](https://github.com/oleibman) fixing [#2550](https://github.com/PHPOffice/PHPWord/issues/2550) in [#2551](https://github.com/PHPOffice/PHPWord/pull/2551) - Typo : Fix hardcoded macro chars in TemplateProcessor method [@glafarge](https://github.com/glafarge) in [#2618](https://github.com/PHPOffice/PHPWord/pull/2618) - XML Reader : Prevent fatal errors when opening corrupt files or "doc" files [@mmcev106](https://github.com/mmcev106) in [#2626](https://github.com/PHPOffice/PHPWord/pull/2626) +- Documentation : Updated Comment element by [@laminga](https://github.com/laminga) in [#2650](https://github.com/PHPOffice/PHPWord/pull/2650) ### Miscellaneous diff --git a/docs/usage/elements/comment.md b/docs/usage/elements/comment.md index 06a3866a3e..50813fa2a1 100644 --- a/docs/usage/elements/comment.md +++ b/docs/usage/elements/comment.md @@ -1,7 +1,7 @@ # Comment Comments can be added to a document by using ``addComment``. -The comment can contain formatted text. Once the comment has been added, it can be linked to any element with ``setCommentStart``. +The comment can contain formatted text. Once the comment has been added, it can be linked to any element with ``setCommentRangeStart``. ``` php addTextRun(); $textrun->addText('This '); $text = $textrun->addText('is'); // link the comment to the text you just created -$text->setCommentStart($comment); +$text->setCommentRangeStart($comment); +$textrun->addText(' a test'); ``` -If no end is set for a comment using the ``setCommentEnd``, the comment will be ended automatically at the end of the element it is started on. \ No newline at end of file +If no end is set for a comment using the ``setCommentRangeEnd``, the comment will be ended automatically at the end of the element it is started on. \ No newline at end of file From 8730d1bad7a73a7a98200bbbe7fbefc079aec841 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 11:22:21 +0200 Subject: [PATCH 194/246] Bump mpdf/mpdf from 8.2.2 to 8.2.4 (#2647) * Bump mpdf/mpdf from 8.2.2 to 8.2.4 Bumps [mpdf/mpdf](https://github.com/mpdf/mpdf) from 8.2.2 to 8.2.4. - [Release notes](https://github.com/mpdf/mpdf/releases) - [Changelog](https://github.com/mpdf/mpdf/blob/development/CHANGELOG.md) - [Commits](https://github.com/mpdf/mpdf/compare/v8.2.2...v8.2.4) --- updated-dependencies: - dependency-name: mpdf/mpdf dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Updated changelog --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Progi1984 --- composer.lock | 25 +++++++++++++------------ docs/changes/2.x/2.0.0.md | 1 + 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/composer.lock b/composer.lock index 6a1df276c9..cff0751756 100644 --- a/composer.lock +++ b/composer.lock @@ -765,16 +765,16 @@ }, { "name": "mpdf/mpdf", - "version": "v8.2.2", + "version": "v8.2.4", "source": { "type": "git", "url": "https://github.com/mpdf/mpdf.git", - "reference": "596a87b876d7793be7be060a8ac13424de120dd5" + "reference": "9e3ff91606fed11cd58a130eabaaf60e56fdda88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mpdf/mpdf/zipball/596a87b876d7793be7be060a8ac13424de120dd5", - "reference": "596a87b876d7793be7be060a8ac13424de120dd5", + "url": "https://api.github.com/repos/mpdf/mpdf/zipball/9e3ff91606fed11cd58a130eabaaf60e56fdda88", + "reference": "9e3ff91606fed11cd58a130eabaaf60e56fdda88", "shasum": "" }, "require": { @@ -842,7 +842,7 @@ "type": "custom" } ], - "time": "2023-11-07T13:52:14+00:00" + "time": "2024-06-14T16:06:41+00:00" }, { "name": "mpdf/psr-http-message-shim", @@ -938,16 +938,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.11.1", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", "shasum": "" }, "require": { @@ -955,11 +955,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", @@ -985,7 +986,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" }, "funding": [ { @@ -993,7 +994,7 @@ "type": "tidelift" } ], - "time": "2023-03-08T13:26:56+00:00" + "time": "2024-06-12T14:39:25+00:00" }, { "name": "nikic/php-parser", diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 3e3e55807d..cdb104c413 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -32,5 +32,6 @@ - Improved Issue Template by [@Progi1984](https://github.com/Progi1984) in [#2609](https://github.com/PHPOffice/PHPWord/pull/2609) - Bump phpoffice/math from 0.1.0 to 0.2.0 by [@Progi1984](https://github.com/Progi1984) fixing [#2559](https://github.com/PHPOffice/PHPWord/issues/2559) in [#2645](https://github.com/PHPOffice/PHPWord/pull/2645) - Bump tecnickcom/tcpdf from 6.6.5 to 6.7.5 by [@dependabot](https://github.com/dependabot) in [#2646](https://github.com/PHPOffice/PHPWord/pull/2646) +- Bump mpdf/mpdf from 8.2.2 to 8.2.4 by [@dependabot](https://github.com/dependabot) in [#2647](https://github.com/PHPOffice/PHPWord/pull/2647) ### BC Breaks From 6e27dbf2b67db84afee4794c744206754c52d81e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 12:09:15 +0200 Subject: [PATCH 195/246] Bump phenx/php-svg-lib from 0.5.1 to 0.5.4 (#2649) * Bump phenx/php-svg-lib from 0.5.1 to 0.5.4 Bumps [phenx/php-svg-lib](https://github.com/dompdf/php-svg-lib) from 0.5.1 to 0.5.4. - [Release notes](https://github.com/dompdf/php-svg-lib/releases) - [Commits](https://github.com/dompdf/php-svg-lib/compare/0.5.1...0.5.4) --- updated-dependencies: - dependency-name: phenx/php-svg-lib dependency-type: indirect ... Signed-off-by: dependabot[bot] * Updated changelog --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Progi1984 --- composer.lock | 46 ++++++++++++++++++++++++--------------- docs/changes/2.x/2.0.0.md | 1 + 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/composer.lock b/composer.lock index cff0751756..d309d421c3 100644 --- a/composer.lock +++ b/composer.lock @@ -1322,16 +1322,16 @@ }, { "name": "phenx/php-svg-lib", - "version": "0.5.1", + "version": "0.5.4", "source": { "type": "git", "url": "https://github.com/dompdf/php-svg-lib.git", - "reference": "8a8a1ebcf6aea861ef30197999f096f7bd4b4456" + "reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/8a8a1ebcf6aea861ef30197999f096f7bd4b4456", - "reference": "8a8a1ebcf6aea861ef30197999f096f7bd4b4456", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/46b25da81613a9cf43c83b2a8c2c1bdab27df691", + "reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691", "shasum": "" }, "require": { @@ -1350,7 +1350,7 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0" + "LGPL-3.0-or-later" ], "authors": [ { @@ -1362,9 +1362,9 @@ "homepage": "https://github.com/PhenX/php-svg-lib", "support": { "issues": "https://github.com/dompdf/php-svg-lib/issues", - "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.1" + "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.4" }, - "time": "2023-12-11T20:56:08+00:00" + "time": "2024-04-08T12:52:34+00:00" }, { "name": "php-cs-fixer/diff", @@ -2290,16 +2290,16 @@ }, { "name": "sabberworm/php-css-parser", - "version": "8.4.0", + "version": "v8.6.0", "source": { "type": "git", - "url": "https://github.com/sabberworm/PHP-CSS-Parser.git", - "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30" + "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", + "reference": "d2fb94a9641be84d79c7548c6d39bbebba6e9a70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabberworm/PHP-CSS-Parser/zipball/e41d2140031d533348b2192a83f02d8dd8a71d30", - "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/d2fb94a9641be84d79c7548c6d39bbebba6e9a70", + "reference": "d2fb94a9641be84d79c7548c6d39bbebba6e9a70", "shasum": "" }, "require": { @@ -2307,13 +2307,17 @@ "php": ">=5.6.20" }, "require-dev": { - "codacy/coverage": "^1.4", - "phpunit/phpunit": "^4.8.36" + "phpunit/phpunit": "^5.7.27" }, "suggest": { "ext-mbstring": "for parsing UTF-8 CSS" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.0.x-dev" + } + }, "autoload": { "psr-4": { "Sabberworm\\CSS\\": "src/" @@ -2326,6 +2330,14 @@ "authors": [ { "name": "Raphael Schweikert" + }, + { + "name": "Oliver Klee", + "email": "github@oliverklee.de" + }, + { + "name": "Jake Hotson", + "email": "jake.github@qzdesign.co.uk" } ], "description": "Parser for CSS Files written in PHP", @@ -2336,10 +2348,10 @@ "stylesheet" ], "support": { - "issues": "https://github.com/sabberworm/PHP-CSS-Parser/issues", - "source": "https://github.com/sabberworm/PHP-CSS-Parser/tree/8.4.0" + "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.6.0" }, - "time": "2021-12-11T13:40:54+00:00" + "time": "2024-07-01T07:33:21+00:00" }, { "name": "sebastian/cli-parser", diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index cdb104c413..70f9322750 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -33,5 +33,6 @@ - Bump phpoffice/math from 0.1.0 to 0.2.0 by [@Progi1984](https://github.com/Progi1984) fixing [#2559](https://github.com/PHPOffice/PHPWord/issues/2559) in [#2645](https://github.com/PHPOffice/PHPWord/pull/2645) - Bump tecnickcom/tcpdf from 6.6.5 to 6.7.5 by [@dependabot](https://github.com/dependabot) in [#2646](https://github.com/PHPOffice/PHPWord/pull/2646) - Bump mpdf/mpdf from 8.2.2 to 8.2.4 by [@dependabot](https://github.com/dependabot) in [#2647](https://github.com/PHPOffice/PHPWord/pull/2647) +- Bump phenx/php-svg-lib from 0.5.1 to 0.5.4 by [@dependabot](https://github.com/dependabot) in [#2649](https://github.com/PHPOffice/PHPWord/pull/2649) ### BC Breaks From 72c29a6ff7dbd949e136a1e0f9fda06e7acc5637 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Mon, 12 Aug 2024 12:17:06 +0200 Subject: [PATCH 196/246] Word2007 Reader: Support for Paragraph Border Style (#2651) Co-authored-by: damienfa --- docs/changes/2.x/2.0.0.md | 1 + src/PhpWord/Element/TextRun.php | 10 ++--- src/PhpWord/Reader/Word2007/AbstractPart.php | 12 ++++++ tests/PhpWordTests/Reader/Word2007Test.php | 36 ++++++++++++++++++ .../_files/documents/reader-styles.docx | Bin 0 -> 63587 bytes 5 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 tests/PhpWordTests/_files/documents/reader-styles.docx diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 70f9322750..3b08c2f0ca 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -6,6 +6,7 @@ - IOFactory : Added extractVariables method to extract variables from a document [@sibalonat](https://github.com/sibalonat) in [#2515](https://github.com/PHPOffice/PHPWord/pull/2515) - PDF Writer : Documented how to specify a PDF renderer, when working with the PDF writer, as well as the three available choices by [@settermjd](https://github.com/settermjd) in [#2642](https://github.com/PHPOffice/PHPWord/pull/2642) +- Word2007 Reader: Support for Paragraph Border Style by [@damienfa](https://github.com/damienfa) in [#2651](https://github.com/PHPOffice/PHPWord/pull/2651) ### Bug fixes diff --git a/src/PhpWord/Element/TextRun.php b/src/PhpWord/Element/TextRun.php index 33c55f6584..8ddc9cd7ba 100644 --- a/src/PhpWord/Element/TextRun.php +++ b/src/PhpWord/Element/TextRun.php @@ -32,14 +32,14 @@ class TextRun extends AbstractContainer /** * Paragraph style. * - * @var \PhpOffice\PhpWord\Style\Paragraph|string + * @var Paragraph|string */ protected $paragraphStyle; /** * Create new instance. * - * @param array|\PhpOffice\PhpWord\Style\Paragraph|string $paragraphStyle + * @param array|Paragraph|string $paragraphStyle */ public function __construct($paragraphStyle = null) { @@ -49,7 +49,7 @@ public function __construct($paragraphStyle = null) /** * Get Paragraph style. * - * @return \PhpOffice\PhpWord\Style\Paragraph|string + * @return Paragraph|string */ public function getParagraphStyle() { @@ -59,9 +59,9 @@ public function getParagraphStyle() /** * Set Paragraph style. * - * @param array|\PhpOffice\PhpWord\Style\Paragraph|string $style + * @param array|Paragraph|string $style * - * @return \PhpOffice\PhpWord\Style\Paragraph|string + * @return Paragraph|string */ public function setParagraphStyle($style = null) { diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 95799387ed..2741841ef3 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -529,6 +529,18 @@ protected function readParagraphStyle(XMLReader $xmlReader, DOMElement $domNode) 'contextualSpacing' => [self::READ_TRUE, 'w:contextualSpacing'], 'bidi' => [self::READ_TRUE, 'w:bidi'], 'suppressAutoHyphens' => [self::READ_TRUE, 'w:suppressAutoHyphens'], + 'borderTopStyle' => [self::READ_VALUE, 'w:pBdr/w:top'], + 'borderTopColor' => [self::READ_VALUE, 'w:pBdr/w:top', 'w:color'], + 'borderTopSize' => [self::READ_VALUE, 'w:pBdr/w:top', 'w:sz'], + 'borderRightStyle' => [self::READ_VALUE, 'w:pBdr/w:right'], + 'borderRightColor' => [self::READ_VALUE, 'w:pBdr/w:right', 'w:color'], + 'borderRightSize' => [self::READ_VALUE, 'w:pBdr/w:right', 'w:sz'], + 'borderBottomStyle' => [self::READ_VALUE, 'w:pBdr/w:bottom'], + 'borderBottomColor' => [self::READ_VALUE, 'w:pBdr/w:bottom', 'w:color'], + 'borderBottomSize' => [self::READ_VALUE, 'w:pBdr/w:bottom', 'w:sz'], + 'borderLeftStyle' => [self::READ_VALUE, 'w:pBdr/w:left'], + 'borderLeftColor' => [self::READ_VALUE, 'w:pBdr/w:left', 'w:color'], + 'borderLeftSize' => [self::READ_VALUE, 'w:pBdr/w:left', 'w:sz'], ]; return $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); diff --git a/tests/PhpWordTests/Reader/Word2007Test.php b/tests/PhpWordTests/Reader/Word2007Test.php index fac5b6b59a..ebfd8ad7a2 100644 --- a/tests/PhpWordTests/Reader/Word2007Test.php +++ b/tests/PhpWordTests/Reader/Word2007Test.php @@ -29,6 +29,7 @@ use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Reader\Word2007; use PhpOffice\PhpWord\Style\Font; +use PhpOffice\PhpWord\Style\Paragraph; use PhpOffice\PhpWordTests\TestHelperDOCX; /** @@ -82,6 +83,41 @@ public function testLoad(): void self::assertEquals('0', $doc->getElementAttribute('/w:document/w:body/w:p/w:r[w:t/node()="italics"]/w:rPr/w:b', 'w:val')); } + public function testLoadStyles(): void + { + $phpWord = IOFactory::load(dirname(__DIR__, 1) . '/_files/documents/reader-styles.docx', 'Word2007'); + + self::assertInstanceOf(PhpWord::class, $phpWord); + + $section2 = $phpWord->getSection(2); + self::assertInstanceOf(Section::class, $section2); + + $element2_31 = $section2->getElement(31); + self::assertInstanceOf(TextRun::class, $element2_31); + self::assertEquals('This is a paragraph with border differents', $element2_31->getText()); + + /** @var Paragraph $element2_31_pStyle */ + $element2_31_pStyle = $element2_31->getParagraphStyle(); + self::assertInstanceOf(Paragraph::class, $element2_31_pStyle); + + // Top + self::assertEquals('FFFF00', $element2_31_pStyle->getBorderTopColor()); + self::assertEquals('10', $element2_31_pStyle->getBorderTopSize()); + self::assertEquals('dotted', $element2_31_pStyle->getBorderTopStyle()); + // Right + self::assertEquals('00A933', $element2_31_pStyle->getBorderRightColor()); + self::assertEquals('4', $element2_31_pStyle->getBorderRightSize()); + self::assertEquals('dashed', $element2_31_pStyle->getBorderRightStyle()); + // Bottom + self::assertEquals('F10D0C', $element2_31_pStyle->getBorderBottomColor()); + self::assertEquals('8', $element2_31_pStyle->getBorderBottomSize()); + self::assertEquals('dashSmallGap', $element2_31_pStyle->getBorderBottomStyle()); + // Left + self::assertEquals('3465A4', $element2_31_pStyle->getBorderLeftColor()); + self::assertEquals('8', $element2_31_pStyle->getBorderLeftSize()); + self::assertEquals('dashed', $element2_31_pStyle->getBorderLeftStyle()); + } + /** * Load a Word 2011 file. */ diff --git a/tests/PhpWordTests/_files/documents/reader-styles.docx b/tests/PhpWordTests/_files/documents/reader-styles.docx new file mode 100644 index 0000000000000000000000000000000000000000..b02cf73c5ff84b4dc1c309052f035ac791659b3b GIT binary patch literal 63587 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 Date: Mon, 12 Aug 2024 12:47:47 +0200 Subject: [PATCH 197/246] Bump phpstan/phpstan-phpunit from 1.3.15 to 1.4.0 (#2648) * Bump phpstan/phpstan-phpunit from 1.3.15 to 1.4.0 Bumps [phpstan/phpstan-phpunit](https://github.com/phpstan/phpstan-phpunit) from 1.3.15 to 1.4.0. - [Release notes](https://github.com/phpstan/phpstan-phpunit/releases) - [Commits](https://github.com/phpstan/phpstan-phpunit/compare/1.3.15...1.4.0) --- updated-dependencies: - dependency-name: phpstan/phpstan-phpunit dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Updated changelog * Fixed PHPStan errors --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Progi1984 --- composer.lock | 32 ++++++++++++---------------- docs/changes/2.x/2.0.0.md | 1 + phpstan-baseline.neon | 40 ----------------------------------- phpstan.neon | 4 +++- src/PhpWord/Element/Image.php | 5 +++-- src/PhpWord/Shared/Html.php | 20 ++++++++++-------- 6 files changed, 31 insertions(+), 71 deletions(-) diff --git a/composer.lock b/composer.lock index d309d421c3..a803691ad2 100644 --- a/composer.lock +++ b/composer.lock @@ -1504,16 +1504,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.40", + "version": "1.11.10", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d" + "reference": "640410b32995914bde3eed26fa89552f9c2c082f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/93c84b5bf7669920d823631e39904d69b9c7dc5d", - "reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/640410b32995914bde3eed26fa89552f9c2c082f", + "reference": "640410b32995914bde3eed26fa89552f9c2c082f", "shasum": "" }, "require": { @@ -1556,31 +1556,27 @@ { "url": "https://github.com/phpstan", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" } ], - "time": "2023-10-30T14:48:31+00:00" + "time": "2024-08-08T09:02:50+00:00" }, { "name": "phpstan/phpstan-phpunit", - "version": "1.3.15", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "70ecacc64fe8090d8d2a33db5a51fe8e88acd93a" + "reference": "f3ea021866f4263f07ca3636bf22c64be9610c11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/70ecacc64fe8090d8d2a33db5a51fe8e88acd93a", - "reference": "70ecacc64fe8090d8d2a33db5a51fe8e88acd93a", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/f3ea021866f4263f07ca3636bf22c64be9610c11", + "reference": "f3ea021866f4263f07ca3636bf22c64be9610c11", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.10" + "phpstan/phpstan": "^1.11" }, "conflict": { "phpunit/phpunit": "<7.0" @@ -1612,9 +1608,9 @@ "description": "PHPUnit extensions and rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.15" + "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.4.0" }, - "time": "2023-10-09T18:58:39+00:00" + "time": "2024-04-20T06:39:00+00:00" }, { "name": "phpunit/php-code-coverage", @@ -5071,9 +5067,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "phpstan/phpstan-phpunit": 0 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 3b08c2f0ca..a299d15b41 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -35,5 +35,6 @@ - Bump tecnickcom/tcpdf from 6.6.5 to 6.7.5 by [@dependabot](https://github.com/dependabot) in [#2646](https://github.com/PHPOffice/PHPWord/pull/2646) - Bump mpdf/mpdf from 8.2.2 to 8.2.4 by [@dependabot](https://github.com/dependabot) in [#2647](https://github.com/PHPOffice/PHPWord/pull/2647) - Bump phenx/php-svg-lib from 0.5.1 to 0.5.4 by [@dependabot](https://github.com/dependabot) in [#2649](https://github.com/PHPOffice/PHPWord/pull/2649) +- Bump phpstan/phpstan-phpunit from 1.3.15 to 1.4.0 by [@dependabot](https://github.com/dependabot) in [#2648](https://github.com/PHPOffice/PHPWord/pull/2648) ### BC Breaks diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 2e44745b3d..8e47429ad9 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -60,11 +60,6 @@ parameters: count: 1 path: src/PhpWord/Element/Image.php - - - message: "#^Parameter \\#2 \\$length of function fread expects int\\<0, max\\>, int\\<0, max\\>\\|false given\\.$#" - count: 1 - path: src/PhpWord/Element/Image.php - - message: "#^Property PhpOffice\\\\PhpWord\\\\Element\\\\Image\\:\\:\\$source \\(string\\) does not accept string\\|false\\.$#" count: 1 @@ -385,11 +380,6 @@ parameters: count: 1 path: src/PhpWord/Shared/Drawing.php - - - message: "#^Access to an undefined property DOMNode\\:\\:\\$value\\.$#" - count: 6 - path: src/PhpWord/Shared/Html.php - - message: "#^Binary operation \"\\*\" between string and 50 results in an error\\.$#" count: 1 @@ -520,16 +510,6 @@ parameters: count: 1 path: src/PhpWord/Shared/XMLWriter.php - - - message: "#^Parameter \\#1 \\$uri of method XMLWriter\\:\\:openUri\\(\\) expects string, string\\|false given\\.$#" - count: 1 - path: src/PhpWord/Shared/XMLWriter.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Shared\\\\XMLWriter\\:\\:\\$tempFileName \\(string\\) does not accept string\\|false\\.$#" - count: 1 - path: src/PhpWord/Shared/XMLWriter.php - - message: "#^Call to method add\\(\\) on an unknown class PclZip\\.$#" count: 2 @@ -1110,11 +1090,6 @@ parameters: count: 1 path: src/PhpWord/TemplateProcessor.php - - - message: "#^Parameter \\#1 \\$str of function preg_quote expects string, int\\|string given\\.$#" - count: 1 - path: src/PhpWord/TemplateProcessor.php - - message: "#^Parameter \\#2 \\$array of function implode expects array\\|null, array\\\\|string given\\.$#" count: 1 @@ -1135,11 +1110,6 @@ parameters: count: 1 path: src/PhpWord/TemplateProcessor.php - - - message: "#^Property PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:\\$tempDocumentFilename \\(string\\) does not accept string\\|false\\.$#" - count: 1 - path: src/PhpWord/TemplateProcessor.php - - message: "#^Property PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:\\$tempDocumentFooters \\(array\\\\) does not accept string\\.$#" count: 1 @@ -1230,11 +1200,6 @@ parameters: count: 1 path: src/PhpWord/Writer/PDF.php - - - message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, string\\|false given\\.$#" - count: 1 - path: src/PhpWord/Writer/PDF.php - - message: "#^Property PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:\\$renderer \\(PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\\\AbstractRenderer\\) does not accept object\\.$#" count: 1 @@ -1815,11 +1780,6 @@ parameters: count: 1 path: tests/PhpWordTests/TestHelperDOCX.php - - - message: "#^Static property PhpOffice\\\\PhpWordTests\\\\TestHelperDOCX\\:\\:\\$file \\(string\\) does not accept string\\|false\\.$#" - count: 1 - path: tests/PhpWordTests/TestHelperDOCX.php - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\TestableTemplateProcesor\\:\\:__construct\\(\\) has parameter \\$mainPart with no type specified\\.$#" count: 1 diff --git a/phpstan.neon b/phpstan.neon index e490e1b179..aac94077bd 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -14,4 +14,6 @@ parameters: - src/PhpWord/Writer/PDF/MPDF.php bootstrapFiles: - tests/bootstrap.php - checkMissingIterableValueType: false + ignoreErrors: + - + identifier: missingType.iterableValue diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php index 1f1a62500a..12d637d7d2 100644 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -386,8 +386,9 @@ public function getImageString(): ?string $imageBinary = $this->source; } else { $fileHandle = fopen($actualSource, 'rb', false); - if ($fileHandle !== false) { - $imageBinary = fread($fileHandle, filesize($actualSource)); + $fileSize = filesize($actualSource); + if ($fileHandle !== false && $fileSize > 0) { + $imageBinary = fread($fileHandle, $fileSize); fclose($fileHandle); } } diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 2022f7da09..e38f8be910 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -102,7 +102,7 @@ public static function addHtml($element, $html, $fullHTML = false, $preserveWhit * parse Inline style of a node. * * @param DOMNode $node Node to check on attributes and to compile a style array - * @param array $styles is supplied, the inline style attributes are added to the already existing style + * @param array $styles is supplied, the inline style attributes are added to the already existing style * * @return array */ @@ -111,7 +111,9 @@ protected static function parseInlineStyle($node, $styles = []) if (XML_ELEMENT_NODE == $node->nodeType) { $attributes = $node->attributes; // get all the attributes(eg: id, class) - $bidi = ($attributes['dir'] ?? '') === 'rtl'; + $attributeDir = $attributes->getNamedItem('dir'); + $attributeDirValue = $attributeDir ? $attributeDir->nodeValue : ''; + $bidi = $attributeDirValue === 'rtl'; foreach ($attributes as $attribute) { $val = $attribute->value; switch (strtolower($attribute->name)) { @@ -159,15 +161,15 @@ protected static function parseInlineStyle($node, $styles = []) $attributeIdentifier = $attributes->getNamedItem('id'); if ($attributeIdentifier && self::$css) { - $styles = self::parseStyleDeclarations(self::$css->getStyle('#' . $attributeIdentifier->value), $styles); + $styles = self::parseStyleDeclarations(self::$css->getStyle('#' . $attributeIdentifier->nodeValue), $styles); } $attributeClass = $attributes->getNamedItem('class'); if ($attributeClass) { if (self::$css) { - $styles = self::parseStyleDeclarations(self::$css->getStyle('.' . $attributeClass->value), $styles); + $styles = self::parseStyleDeclarations(self::$css->getStyle('.' . $attributeClass->nodeValue), $styles); } - $styles['className'] = $attributeClass->value; + $styles['className'] = $attributeClass->nodeValue; } $attributeStyle = $attributes->getNamedItem('style'); @@ -325,10 +327,10 @@ protected static function parseInput($node, $element, &$styles): void return; } - $inputType = $attributes->getNamedItem('type')->value; + $inputType = $attributes->getNamedItem('type')->nodeValue; switch ($inputType) { case 'checkbox': - $checked = ($checked = $attributes->getNamedItem('checked')) && $checked->value === 'true' ? true : false; + $checked = ($checked = $attributes->getNamedItem('checked')) && $checked->nodeValue === 'true' ? true : false; $textrun = $element->addTextRun($styles['paragraph']); $textrun->addFormField('checkbox')->setValue($checked); @@ -423,8 +425,8 @@ protected static function parseTable($node, $element, &$styles) } $attributes = $node->attributes; - if ($attributes->getNamedItem('border') !== null) { - $border = (int) $attributes->getNamedItem('border')->value; + if ($attributes->getNamedItem('border')) { + $border = (int) $attributes->getNamedItem('border')->nodeValue; $newElement->getStyle()->setBorderSize(Converter::pixelToTwip($border)); } From 00febf54321d77ac4ec99a308ab73d634f6ab422 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Mon, 12 Aug 2024 14:11:49 +0200 Subject: [PATCH 198/246] Word2007 Writer : Added support for field `REF` (#2652) * added support for REF field * Spelling correction * UnitTest and fixes * updated documentation * Update doc docs/elements.rst. Aded ref support * Rebase & Fixed CI --------- Co-authored-by: Adekunle Co-authored-by: Adekunle Adekoya --- docs/changes/2.x/2.0.0.md | 1 + docs/usage/elements/field.md | 15 ++- src/PhpWord/Element/Field.php | 4 + src/PhpWord/Writer/Word2007/Element/Field.php | 113 +++++++++++++++++- .../Writer/Word2007/Element/FieldTest.php | 73 +++++++++++ 5 files changed, 198 insertions(+), 8 deletions(-) create mode 100644 tests/PhpWordTests/Writer/Word2007/Element/FieldTest.php diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index a299d15b41..06a7ba3675 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -7,6 +7,7 @@ - IOFactory : Added extractVariables method to extract variables from a document [@sibalonat](https://github.com/sibalonat) in [#2515](https://github.com/PHPOffice/PHPWord/pull/2515) - PDF Writer : Documented how to specify a PDF renderer, when working with the PDF writer, as well as the three available choices by [@settermjd](https://github.com/settermjd) in [#2642](https://github.com/PHPOffice/PHPWord/pull/2642) - Word2007 Reader: Support for Paragraph Border Style by [@damienfa](https://github.com/damienfa) in [#2651](https://github.com/PHPOffice/PHPWord/pull/2651) +- Word2007 Writer: Support for field REF by [@crystoline](https://github.com/crystoline) in [#2652](https://github.com/PHPOffice/PHPWord/pull/2652) ### Bug fixes diff --git a/docs/usage/elements/field.md b/docs/usage/elements/field.md index fe8e9756fc..1cafd18ef8 100644 --- a/docs/usage/elements/field.md +++ b/docs/usage/elements/field.md @@ -8,6 +8,7 @@ Currently the following fields are supported: - XE - INDEX - FILENAME +- REF ``` php addText('My '); $fieldText->addText('bold index', ['bold' => true]); $fieldText->addText(' entry'); $section->addField('XE', array(), array(), $fieldText); -//this actually adds the index +// this actually adds the index $section->addField('INDEX', array(), array('\\e " " \\h "A" \\c "3"'), 'right click to update index'); + +// Adding reference to a bookmark +$fieldText->addField('REF', [ + 'name' => 'bookmark' +], [ + 'InsertParagraphNumberRelativeContext', + 'CreateHyperLink', +]); ``` diff --git a/src/PhpWord/Element/Field.php b/src/PhpWord/Element/Field.php index b371bb80d7..a828aaa02e 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -91,6 +91,10 @@ class Field extends AbstractElement ], 'options' => ['Path', 'PreserveFormat'], ], + 'REF' => [ + 'properties' => ['name' => ''], + 'options' => ['f', 'h', 'n', 'p', 'r', 't', 'w'], + ], ]; /** diff --git a/src/PhpWord/Writer/Word2007/Element/Field.php b/src/PhpWord/Writer/Word2007/Element/Field.php index 4d7c2a0b46..2977c01626 100644 --- a/src/PhpWord/Writer/Word2007/Element/Field.php +++ b/src/PhpWord/Writer/Word2007/Element/Field.php @@ -17,6 +17,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; +use PhpOffice\PhpWord\Element\Field as ElementField; +use PhpOffice\PhpWord\Element\TextRun; + /** * Field element writer. * @@ -30,7 +33,7 @@ class Field extends Text public function write(): void { $element = $this->getElement(); - if (!$element instanceof \PhpOffice\PhpWord\Element\Field) { + if (!$element instanceof ElementField) { return; } @@ -42,7 +45,7 @@ public function write(): void } } - private function writeDefault(\PhpOffice\PhpWord\Element\Field $element): void + private function writeDefault(ElementField $element): void { $xmlWriter = $this->getXmlWriter(); $this->startElementP(); @@ -73,7 +76,7 @@ private function writeDefault(\PhpOffice\PhpWord\Element\Field $element): void $xmlWriter->endElement(); // w:r if ($element->getText() != null) { - if ($element->getText() instanceof \PhpOffice\PhpWord\Element\TextRun) { + if ($element->getText() instanceof TextRun) { $containerWriter = new Container($xmlWriter, $element->getText(), true); $containerWriter->write(); @@ -120,7 +123,7 @@ private function writeDefault(\PhpOffice\PhpWord\Element\Field $element): void * * //TODO A lot of code duplication with general method, should maybe be refactored */ - protected function writeMacrobutton(\PhpOffice\PhpWord\Element\Field $element): void + protected function writeMacrobutton(ElementField $element): void { $xmlWriter = $this->getXmlWriter(); $this->startElementP(); @@ -159,7 +162,7 @@ protected function writeMacrobutton(\PhpOffice\PhpWord\Element\Field $element): $this->endElementP(); // w:p } - private function buildPropertiesAndOptions(\PhpOffice\PhpWord\Element\Field $element) + private function buildPropertiesAndOptions(ElementField $element) { $propertiesAndOptions = ''; $properties = $element->getProperties(); @@ -226,4 +229,104 @@ private function buildPropertiesAndOptions(\PhpOffice\PhpWord\Element\Field $ele return $propertiesAndOptions; } + + /** + * Writes a REF field. + */ + protected function writeRef(ElementField $element): void + { + $xmlWriter = $this->getXmlWriter(); + $this->startElementP(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'begin'); + $xmlWriter->endElement(); // w:fldChar + $xmlWriter->endElement(); // w:r + + $instruction = ' ' . $element->getType() . ' '; + + foreach ($element->getProperties() as $property) { + $instruction .= $property . ' '; + } + foreach ($element->getOptions() as $optionKey => $optionValue) { + $instruction .= $this->convertRefOption($optionKey, $optionValue) . ' '; + } + + $xmlWriter->startElement('w:r'); + $this->writeFontStyle(); + $xmlWriter->startElement('w:instrText'); + $xmlWriter->writeAttribute('xml:space', 'preserve'); + $xmlWriter->text($instruction); + $xmlWriter->endElement(); // w:instrText + $xmlWriter->endElement(); // w:r + + if ($element->getText() != null) { + if ($element->getText() instanceof \PhpOffice\PhpWord\Element\TextRun) { + $containerWriter = new Container($xmlWriter, $element->getText(), true); + $containerWriter->write(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:instrText'); + $xmlWriter->text('"' . $this->buildPropertiesAndOptions($element)); + $xmlWriter->endElement(); // w:instrText + $xmlWriter->endElement(); // w:r + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:instrText'); + $xmlWriter->writeAttribute('xml:space', 'preserve'); + $xmlWriter->text(' '); + $xmlWriter->endElement(); // w:instrText + $xmlWriter->endElement(); // w:r + } + } + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'separate'); + $xmlWriter->endElement(); // w:fldChar + $xmlWriter->endElement(); // w:r + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:rPr'); + $xmlWriter->startElement('w:noProof'); + $xmlWriter->endElement(); // w:noProof + $xmlWriter->endElement(); // w:rPr + $xmlWriter->writeElement('w:t', $element->getText() != null && is_string($element->getText()) ? $element->getText() : '1'); + $xmlWriter->endElement(); // w:r + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'end'); + $xmlWriter->endElement(); // w:fldChar + $xmlWriter->endElement(); // w:r + + $this->endElementP(); // w:p + } + + private function convertRefOption(string $optionKey, string $optionValue): string + { + if ($optionKey === 'NumberSeperatorSequence') { + return '\\d ' . $optionValue; + } + + switch ($optionValue) { + case 'IncrementAndInsertText': + return '\\f'; + case 'CreateHyperLink': + return '\\h'; + case 'NoTrailingPeriod': + return '\\n'; + case 'IncludeAboveOrBelow': + return '\\p'; + case 'InsertParagraphNumberRelativeContext': + return '\\r'; + case 'SuppressNonDelimiterNonNumericalText': + return '\\t'; + case 'InsertParagraphNumberFullContext': + return '\\w'; + default: + return ''; + } + } } diff --git a/tests/PhpWordTests/Writer/Word2007/Element/FieldTest.php b/tests/PhpWordTests/Writer/Word2007/Element/FieldTest.php new file mode 100644 index 0000000000..30f875c08c --- /dev/null +++ b/tests/PhpWordTests/Writer/Word2007/Element/FieldTest.php @@ -0,0 +1,73 @@ +addSection(); + $section->addField( + 'REF', + [ + 'name' => 'my-bookmark', + ], + [ + 'InsertParagraphNumberRelativeContext', + 'CreateHyperLink', + ] + ); + + $section->addListItem('line one item'); + $section->addListItem('line two item'); + $section->addBookmark('my-bookmark'); + $section->addListItem('line three item'); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $refFieldPath = '/w:document/w:body/w:p[1]/w:r[2]/w:instrText'; + self::assertTrue($doc->elementExists($refFieldPath)); + + $bookMarkElement = $doc->getElement($refFieldPath); + self::assertNotNull($bookMarkElement); + self::assertEquals(' REF my-bookmark \r \h ', $bookMarkElement->textContent); + + $bookmarkPath = '/w:document/w:body/w:bookmarkStart'; + self::assertTrue($doc->elementExists($bookmarkPath)); + self::assertEquals('my-bookmark', $doc->getElementAttribute("$bookmarkPath", 'w:name')); + } +} From 3631936b9e60fe817501bb7922cb220fb9bba74d Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Mon, 12 Aug 2024 14:44:08 +0200 Subject: [PATCH 199/246] Word2007 Reader : Support for FormFields (#2653) * Added code to read FormFields (text input, dropdown and checkbox) from a Word file * Fixed code style issues and added a testcase for reading a FormField of type checkbox * Fixed minor issue found by Scrutinizer * Fixed CI --------- Co-authored-by: Vincent Kool --- docs/changes/2.x/2.0.0.md | 1 + phpstan-baseline.neon | 5 - src/PhpWord/Reader/Word2007/AbstractPart.php | 146 +++++++++++++- .../Reader/Word2007/ElementTest.php | 188 ++++++++++++++++++ 4 files changed, 332 insertions(+), 8 deletions(-) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 06a7ba3675..e658f1a787 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -8,6 +8,7 @@ - PDF Writer : Documented how to specify a PDF renderer, when working with the PDF writer, as well as the three available choices by [@settermjd](https://github.com/settermjd) in [#2642](https://github.com/PHPOffice/PHPWord/pull/2642) - Word2007 Reader: Support for Paragraph Border Style by [@damienfa](https://github.com/damienfa) in [#2651](https://github.com/PHPOffice/PHPWord/pull/2651) - Word2007 Writer: Support for field REF by [@crystoline](https://github.com/crystoline) in [#2652](https://github.com/PHPOffice/PHPWord/pull/2652) +- Word2007 Reader : Support for FormFields by [@vincentKool](https://github.com/vincentKool) in [#2653](https://github.com/PHPOffice/PHPWord/pull/2653) ### Bug fixes diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 8e47429ad9..026fd8b59a 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -235,11 +235,6 @@ parameters: count: 1 path: src/PhpWord/Reader/Word2007/AbstractPart.php - - - message: "#^Parameter \\#1 \\$count of method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractContainer\\:\\:addTextBreak\\(\\) expects int, null given\\.$#" - count: 1 - path: src/PhpWord/Reader/Word2007/AbstractPart.php - - message: "#^Parameter \\#1 \\$depth of method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractContainer\\:\\:addListItemRun\\(\\) expects int, string\\|null given\\.$#" count: 1 diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 2741841ef3..0f3d8bf711 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -24,6 +24,7 @@ use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType; use PhpOffice\PhpWord\Element\AbstractContainer; use PhpOffice\PhpWord\Element\AbstractElement; +use PhpOffice\PhpWord\Element\FormField; use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\PhpWord; @@ -192,8 +193,44 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par // Paragraph style $paragraphStyle = $xmlReader->elementExists('w:pPr', $domNode) ? $this->readParagraphStyle($xmlReader, $domNode) : null; - // PreserveText - if ($xmlReader->elementExists('w:r/w:instrText', $domNode)) { + if ($xmlReader->elementExists('w:r/w:fldChar/w:ffData', $domNode)) { + // FormField + $partOfFormField = false; + $formNodes = []; + $formType = null; + $textRunContainers = $xmlReader->countElements('w:r|w:ins|w:del|w:hyperlink|w:smartTag', $domNode); + if ($textRunContainers > 0) { + $nodes = $xmlReader->getElements('*', $domNode); + $paragraph = $parent->addTextRun($paragraphStyle); + foreach ($nodes as $node) { + if ($xmlReader->elementExists('w:fldChar/w:ffData', $node)) { + $partOfFormField = true; + $formNodes[] = $node; + if ($xmlReader->elementExists('w:fldChar/w:ffData/w:ddList', $node)) { + $formType = 'dropdown'; + } elseif ($xmlReader->elementExists('w:fldChar/w:ffData/w:textInput', $node)) { + $formType = 'textinput'; + } elseif ($xmlReader->elementExists('w:fldChar/w:ffData/w:checkBox', $node)) { + $formType = 'checkbox'; + } + } elseif ($partOfFormField && + $xmlReader->elementExists('w:fldChar', $node) && + 'end' == $xmlReader->getAttribute('w:fldCharType', $node, 'w:fldChar') + ) { + $formNodes[] = $node; + $partOfFormField = false; + // Process the form fields + $this->readFormField($xmlReader, $formNodes, $paragraph, $paragraphStyle, $formType); + } elseif ($partOfFormField) { + $formNodes[] = $node; + } else { + // normal runs + $this->readRun($xmlReader, $node, $paragraph, $docPart, $paragraphStyle); + } + } + } + } elseif ($xmlReader->elementExists('w:r/w:instrText', $domNode)) { + // PreserveText $ignoreText = false; $textContent = ''; $fontStyle = $this->readFontStyle($xmlReader, $domNode); @@ -272,7 +309,7 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par // Text and TextRun $textRunContainers = $xmlReader->countElements('w:r|w:ins|w:del|w:hyperlink|w:smartTag|w:commentReference|w:commentRangeStart|w:commentRangeEnd', $domNode); if (0 === $textRunContainers) { - $parent->addTextBreak(null, $paragraphStyle); + $parent->addTextBreak(1, $paragraphStyle); } else { $nodes = $xmlReader->getElements('*', $domNode); $paragraph = $parent->addTextRun($paragraphStyle); @@ -282,6 +319,109 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par } } + /** + * @param DOMElement[] $domNodes + * @param AbstractContainer $parent + * @param mixed $paragraphStyle + * @param string $formType + */ + private function readFormField(XMLReader $xmlReader, array $domNodes, $parent, $paragraphStyle, $formType): void + { + if (!in_array($formType, ['textinput', 'checkbox', 'dropdown'])) { + return; + } + + $formField = $parent->addFormField($formType, null, $paragraphStyle); + $ffData = $xmlReader->getElement('w:fldChar/w:ffData', $domNodes[0]); + + foreach ($xmlReader->getElements('*', $ffData) as $node) { + /** @var DOMElement $node */ + switch ($node->localName) { + case 'name': + $formField->setName($node->getAttribute('w:val')); + + break; + case 'ddList': + $listEntries = []; + foreach ($xmlReader->getElements('*', $node) as $ddListNode) { + switch ($ddListNode->localName) { + case 'result': + $formField->setValue($xmlReader->getAttribute('w:val', $ddListNode)); + + break; + case 'default': + $formField->setDefault($xmlReader->getAttribute('w:val', $ddListNode)); + + break; + case 'listEntry': + $listEntries[] = $xmlReader->getAttribute('w:val', $ddListNode); + + break; + } + } + $formField->setEntries($listEntries); + if (null !== $formField->getValue()) { + $formField->setText($listEntries[$formField->getValue()]); + } + + break; + case 'textInput': + foreach ($xmlReader->getElements('*', $node) as $ddListNode) { + switch ($ddListNode->localName) { + case 'default': + $formField->setDefault($xmlReader->getAttribute('w:val', $ddListNode)); + + break; + case 'format': + case 'maxLength': + break; + } + } + + break; + case 'checkBox': + foreach ($xmlReader->getElements('*', $node) as $ddListNode) { + switch ($ddListNode->localName) { + case 'default': + $formField->setDefault($xmlReader->getAttribute('w:val', $ddListNode)); + + break; + case 'checked': + $formField->setValue($xmlReader->getAttribute('w:val', $ddListNode)); + + break; + case 'size': + case 'sizeAuto': + break; + } + } + + break; + } + } + + if ('textinput' == $formType) { + $ignoreText = true; + $textContent = ''; + foreach ($domNodes as $node) { + if ($xmlReader->elementExists('w:fldChar', $node)) { + $fldCharType = $xmlReader->getAttribute('w:fldCharType', $node, 'w:fldChar'); + if ('separate' == $fldCharType) { + $ignoreText = false; + } elseif ('end' == $fldCharType) { + $ignoreText = true; + } + } + + if (false === $ignoreText) { + $textContent .= $xmlReader->getValue('w:t', $node); + } + } + $formField->setValue(htmlspecialchars($textContent, ENT_QUOTES, 'UTF-8')); + $formField->setText(htmlspecialchars($textContent, ENT_QUOTES, 'UTF-8')); + } + } + /** * Returns the depth of the Heading, returns 0 for a Title. * diff --git a/tests/PhpWordTests/Reader/Word2007/ElementTest.php b/tests/PhpWordTests/Reader/Word2007/ElementTest.php index f96d8ac1a2..3685cbea03 100644 --- a/tests/PhpWordTests/Reader/Word2007/ElementTest.php +++ b/tests/PhpWordTests/Reader/Word2007/ElementTest.php @@ -355,4 +355,192 @@ public function testReadDrawing(): void $elements = $phpWord->getSection(0)->getElements(); self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); } + + /** + * Test reading FormField - DROPDOWN. + */ + public function testReadFormFieldDropdown(): void + { + $documentXml = ' + + Reference + + + + + + + + + + + + + + + + + + + + FORMDROPDOWN + + + + + + + + + + + + + + + + + + + '; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $elements = $phpWord->getSection(0)->getElements(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); + + $subElements = $elements[0]->getElements(); + + self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $subElements[0]); + self::assertEquals('Reference', $subElements[0]->getText()); + + self::assertInstanceOf('PhpOffice\PhpWord\Element\FormField', $subElements[1]); + self::assertEquals('dropdown', $subElements[1]->getType()); + self::assertEquals('DropDownList1', $subElements[1]->getName()); + self::assertEquals('2', $subElements[1]->getValue()); + self::assertEquals('Option Two', $subElements[1]->getText()); + self::assertEquals(['TBD', 'Option One', 'Option Two', 'Option Three', 'Other'], $subElements[1]->getEntries()); + } + + /** + * Test reading FormField - textinput. + */ + public function testReadFormFieldTextinput(): void + { + $documentXml = ' + + Fieldname + + + + + + + + + + + + + + + + FORMTEXT + + + + + + + + + + + + + + + + + + This is some sample text + + + + + + + + '; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $elements = $phpWord->getSection(0)->getElements(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); + + $subElements = $elements[0]->getElements(); + + self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $subElements[0]); + self::assertEquals('Fieldname', $subElements[0]->getText()); + + self::assertInstanceOf('PhpOffice\PhpWord\Element\FormField', $subElements[1]); + self::assertEquals('textinput', $subElements[1]->getType()); + self::assertEquals('TextInput2', $subElements[1]->getName()); + self::assertEquals('This is some sample text', $subElements[1]->getValue()); + self::assertEquals('This is some sample text', $subElements[1]->getText()); + } + + /** + * Test reading FormField - checkbox. + */ + public function testReadFormFieldCheckbox(): void + { + $documentXml = ' + + + + + + + + + + + + + + + + + + FORMCHECKBOX + + + + + + + + + + + + + + '; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $elements = $phpWord->getSection(0)->getElements(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); + + $subElements = $elements[0]->getElements(); + +// $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $subElements[0]); +// $this->assertEquals('Fieldname', $subElements[0]->getText()); + + self::assertInstanceOf('PhpOffice\PhpWord\Element\FormField', $subElements[0]); + self::assertEquals('checkbox', $subElements[0]->getType()); + self::assertEquals('SomeCheckbox', $subElements[0]->getName()); + } } From fdf1343701f76d3eda7a3e312a01859362acfe69 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Mon, 12 Aug 2024 16:07:06 +0200 Subject: [PATCH 200/246] HTML Reader : Read width & height attributes in points (#2654) --- composer.lock | 4 +- docs/changes/2.x/2.0.0.md | 1 + src/PhpWord/Shared/Html.php | 22 ++++++++++ tests/PhpWordTests/Shared/HtmlTest.php | 60 ++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 1 deletion(-) diff --git a/composer.lock b/composer.lock index a803691ad2..d6b3ee35d8 100644 --- a/composer.lock +++ b/composer.lock @@ -5067,7 +5067,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "phpstan/phpstan-phpunit": 0 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index e658f1a787..19fc9f35e2 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -22,6 +22,7 @@ - Typo : Fix hardcoded macro chars in TemplateProcessor method [@glafarge](https://github.com/glafarge) in [#2618](https://github.com/PHPOffice/PHPWord/pull/2618) - XML Reader : Prevent fatal errors when opening corrupt files or "doc" files [@mmcev106](https://github.com/mmcev106) in [#2626](https://github.com/PHPOffice/PHPWord/pull/2626) - Documentation : Updated Comment element by [@laminga](https://github.com/laminga) in [#2650](https://github.com/PHPOffice/PHPWord/pull/2650) +- HTML Reader : Read width & height attributes in points fixing [#2589](https://github.com/PHPOffice/PHPWord/issues/2589) by [@Progi1984](https://github.com/Progi1984) in [#2654](https://github.com/PHPOffice/PHPWord/pull/2654) ### Miscellaneous diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index e38f8be910..602b74ccbb 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -902,12 +902,34 @@ protected static function parseImage($node, $element) break; case 'width': $width = $attribute->value; + + // pt + if (false !== strpos($width, 'pt')) { + $width = Converter::pointToPixel((float) str_replace('pt', '', $width)); + } + + // px + if (false !== strpos($width, 'px')) { + $width = str_replace('px', '', $width); + } + $style['width'] = $width; $style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX; break; case 'height': $height = $attribute->value; + + // pt + if (false !== strpos($height, 'pt')) { + $height = Converter::pointToPixel((float) str_replace('pt', '', $height)); + } + + // px + if (false !== strpos($height, 'px')) { + $height = str_replace('px', '', $height); + } + $style['height'] = $height; $style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX; diff --git a/tests/PhpWordTests/Shared/HtmlTest.php b/tests/PhpWordTests/Shared/HtmlTest.php index c8640509de..8144eb6f72 100644 --- a/tests/PhpWordTests/Shared/HtmlTest.php +++ b/tests/PhpWordTests/Shared/HtmlTest.php @@ -806,6 +806,66 @@ public function testParseImage(): void self::assertStringMatchesFormat('%Smso-position-horizontal:left%S', $doc->getElementAttribute($baseXpath . '[2]/w:pict/v:shape', 'style')); } + /** + * Test parsing of img. + */ + public function testParseImageSizeInPixels(): void + { + $src = __DIR__ . '/../_files/images/firefox.png'; + + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $html = '

'; + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $baseXpath = '/w:document/w:body/w:p/w:r'; + self::assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); + self::assertStringMatchesFormat('%Swidth:150px%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + self::assertStringMatchesFormat('%Sheight:200px%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + } + + /** + * Test parsing of img. + */ + public function testParseImageSizeInPoints(): void + { + $src = __DIR__ . '/../_files/images/firefox.png'; + + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $html = '

'; + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $baseXpath = '/w:document/w:body/w:p/w:r'; + self::assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); + self::assertStringMatchesFormat('%Swidth:200px%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + self::assertStringMatchesFormat('%Sheight:266.66666666667%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + } + + /** + * Test parsing of img. + */ + public function testParseImageSizeWithoutUnits(): void + { + $src = __DIR__ . '/../_files/images/firefox.png'; + + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $html = '

'; + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $baseXpath = '/w:document/w:body/w:p/w:r'; + self::assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); + self::assertStringMatchesFormat('%Swidth:150px%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + self::assertStringMatchesFormat('%Sheight:200px%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + } + /** * Test parsing of remote img. */ From c917d039b510df5173337add96ed03926d9672b8 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Tue, 13 Aug 2024 10:21:36 +0200 Subject: [PATCH 201/246] Template Processor : Fixed bad naming of variables (#2655) --- docs/changes/2.x/2.0.0.md | 1 + src/PhpWord/TemplateProcessor.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 19fc9f35e2..6638178d91 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -23,6 +23,7 @@ - XML Reader : Prevent fatal errors when opening corrupt files or "doc" files [@mmcev106](https://github.com/mmcev106) in [#2626](https://github.com/PHPOffice/PHPWord/pull/2626) - Documentation : Updated Comment element by [@laminga](https://github.com/laminga) in [#2650](https://github.com/PHPOffice/PHPWord/pull/2650) - HTML Reader : Read width & height attributes in points fixing [#2589](https://github.com/PHPOffice/PHPWord/issues/2589) by [@Progi1984](https://github.com/Progi1984) in [#2654](https://github.com/PHPOffice/PHPWord/pull/2654) +- Template Processor : Fixed bad naming of variables fixing [#2586](https://github.com/PHPOffice/PHPWord/issues/2586) by [@Progi1984](https://github.com/Progi1984) in [#2655](https://github.com/PHPOffice/PHPWord/pull/2655) ### Miscellaneous diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 900169bd68..8bef424fd1 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -662,8 +662,8 @@ public function setImageValue($search, $replace, $limit = self::MAXIMUM_REPLACEM foreach (array_keys($this->tempDocumentHeaders) as $headerIndex) { $searchParts[$this->getHeaderName($headerIndex)] = &$this->tempDocumentHeaders[$headerIndex]; } - foreach (array_keys($this->tempDocumentFooters) as $headerIndex) { - $searchParts[$this->getFooterName($headerIndex)] = &$this->tempDocumentFooters[$headerIndex]; + foreach (array_keys($this->tempDocumentFooters) as $footerIndex) { + $searchParts[$this->getFooterName($footerIndex)] = &$this->tempDocumentFooters[$footerIndex]; } // define templates From 169130124e07254103356d0ccdd7082191a7acfa Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Tue, 13 Aug 2024 15:14:29 +0200 Subject: [PATCH 202/246] RTF Writer : Support for Table Border Style (#2656) --- docs/changes/2.x/2.0.0.md | 1 + src/PhpWord/Style/Border.php | 28 +-- src/PhpWord/Writer/HTML/Element/Table.php | 4 +- .../Writer/RTF/Element/AbstractElement.php | 6 +- src/PhpWord/Writer/RTF/Element/Table.php | 114 ++++++++++++ src/PhpWord/Writer/RTF/Part/Header.php | 9 + .../Writer/Word2007/Style/MarginBorder.php | 2 +- .../Writer/RTF/Element/TableTest.php | 169 ++++++++++++++++++ .../PhpWordTests/Writer/RTF/Element2Test.php | 46 +---- 9 files changed, 313 insertions(+), 66 deletions(-) create mode 100644 tests/PhpWordTests/Writer/RTF/Element/TableTest.php diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 6638178d91..219db0c939 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -9,6 +9,7 @@ - Word2007 Reader: Support for Paragraph Border Style by [@damienfa](https://github.com/damienfa) in [#2651](https://github.com/PHPOffice/PHPWord/pull/2651) - Word2007 Writer: Support for field REF by [@crystoline](https://github.com/crystoline) in [#2652](https://github.com/PHPOffice/PHPWord/pull/2652) - Word2007 Reader : Support for FormFields by [@vincentKool](https://github.com/vincentKool) in [#2653](https://github.com/PHPOffice/PHPWord/pull/2653) +- RTF Writer : Support for Table Border Style fixing [#345](https://github.com/PHPOffice/PHPWord/issues/345) by [@Progi1984](https://github.com/Progi1984) in [#2656](https://github.com/PHPOffice/PHPWord/pull/2656) ### Bug fixes diff --git a/src/PhpWord/Style/Border.php b/src/PhpWord/Style/Border.php index 28e340c040..e2a56c5d21 100644 --- a/src/PhpWord/Style/Border.php +++ b/src/PhpWord/Style/Border.php @@ -34,7 +34,7 @@ class Border extends AbstractStyle /** * Border Top Color. * - * @var string + * @var null|string */ protected $borderTopColor; @@ -55,7 +55,7 @@ class Border extends AbstractStyle /** * Border Left Color. * - * @var string + * @var null|string */ protected $borderLeftColor; @@ -76,7 +76,7 @@ class Border extends AbstractStyle /** * Border Right Color. * - * @var string + * @var null|string */ protected $borderRightColor; @@ -97,7 +97,7 @@ class Border extends AbstractStyle /** * Border Bottom Color. * - * @var string + * @var null|string */ protected $borderBottomColor; @@ -171,7 +171,7 @@ public function setBorderSize($value = null) /** * Get border color. * - * @return string[] + * @return array */ public function getBorderColor() { @@ -186,7 +186,7 @@ public function getBorderColor() /** * Set border color. * - * @param string $value + * @param null|string $value * * @return self */ @@ -259,7 +259,7 @@ public function setBorderTopSize($value = null) /** * Get border top color. * - * @return string + * @return null|string */ public function getBorderTopColor() { @@ -269,7 +269,7 @@ public function getBorderTopColor() /** * Set border top color. * - * @param string $value + * @param null|string $value * * @return self */ @@ -331,7 +331,7 @@ public function setBorderLeftSize($value = null) /** * Get border left color. * - * @return string + * @return null|string */ public function getBorderLeftColor() { @@ -341,7 +341,7 @@ public function getBorderLeftColor() /** * Set border left color. * - * @param string $value + * @param null|string $value * * @return self */ @@ -403,7 +403,7 @@ public function setBorderRightSize($value = null) /** * Get border right color. * - * @return string + * @return null|string */ public function getBorderRightColor() { @@ -413,7 +413,7 @@ public function getBorderRightColor() /** * Set border right color. * - * @param string $value + * @param null|string $value * * @return self */ @@ -475,7 +475,7 @@ public function setBorderBottomSize($value = null) /** * Get border bottom color. * - * @return string + * @return null|string */ public function getBorderBottomColor() { @@ -485,7 +485,7 @@ public function getBorderBottomColor() /** * Set border bottom color. * - * @param string $value + * @param null|string $value * * @return self */ diff --git a/src/PhpWord/Writer/HTML/Element/Table.php b/src/PhpWord/Writer/HTML/Element/Table.php index c7a23d2fe1..f4acc8cdf4 100644 --- a/src/PhpWord/Writer/HTML/Element/Table.php +++ b/src/PhpWord/Writer/HTML/Element/Table.php @@ -120,9 +120,7 @@ private function getTableStyle($tableStyle = null): string return ''; } if (is_string($tableStyle)) { - $style = ' class="' . $tableStyle; - - return $style . '"'; + return ' class="' . $tableStyle . '"'; } $styleWriter = new TableStyleWriter($tableStyle); diff --git a/src/PhpWord/Writer/RTF/Element/AbstractElement.php b/src/PhpWord/Writer/RTF/Element/AbstractElement.php index dedbc8bfa1..5c33868a8b 100644 --- a/src/PhpWord/Writer/RTF/Element/AbstractElement.php +++ b/src/PhpWord/Writer/RTF/Element/AbstractElement.php @@ -24,7 +24,7 @@ use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Style\Font as FontStyle; use PhpOffice\PhpWord\Style\Paragraph as ParagraphStyle; -use PhpOffice\PhpWord\Writer\AbstractWriter; +use PhpOffice\PhpWord\Writer\RTF as WriterRTF; use PhpOffice\PhpWord\Writer\RTF\Style\Font as FontStyleWriter; use PhpOffice\PhpWord\Writer\RTF\Style\Paragraph as ParagraphStyleWriter; @@ -38,7 +38,7 @@ abstract class AbstractElement /** * Parent writer. * - * @var \PhpOffice\PhpWord\Writer\AbstractWriter + * @var WriterRTF */ protected $parentWriter; @@ -82,7 +82,7 @@ abstract public function write(); */ protected $escaper; - public function __construct(AbstractWriter $parentWriter, Element $element, bool $withoutP = false) + public function __construct(WriterRTF $parentWriter, Element $element, bool $withoutP = false) { $this->parentWriter = $parentWriter; $this->element = $element; diff --git a/src/PhpWord/Writer/RTF/Element/Table.php b/src/PhpWord/Writer/RTF/Element/Table.php index b7b370bd5a..f2d5f9fb5a 100644 --- a/src/PhpWord/Writer/RTF/Element/Table.php +++ b/src/PhpWord/Writer/RTF/Element/Table.php @@ -21,7 +21,10 @@ use PhpOffice\PhpWord\Element\Row as RowElement; use PhpOffice\PhpWord\Element\Table as TableElement; use PhpOffice\PhpWord\Settings; +use PhpOffice\PhpWord\SimpleType\Border; use PhpOffice\PhpWord\Style; +use PhpOffice\PhpWord\Style\Cell as CellStyle; +use PhpOffice\PhpWord\Style\Table as TableStyle; /** * Table element RTF writer. @@ -30,6 +33,11 @@ */ class Table extends AbstractElement { + /** + * @var TableElement + */ + protected $element; + /** * Write element. * @@ -77,9 +85,18 @@ public function write() private function writeRowDef(RowElement $row) { $content = ''; + $tableStyle = $this->element->getStyle(); + if (is_string($tableStyle)) { + $tableStyle = Style::getStyle($tableStyle); + if (!($tableStyle instanceof TableStyle)) { + $tableStyle = null; + } + } $rightMargin = 0; foreach ($row->getCells() as $cell) { + $content .= $this->writeCellStyle($cell->getStyle(), $tableStyle); + $width = $cell->getWidth(); $vMerge = $this->getVMerge($cell->getStyle()->getVMerge()); if ($width === null) { @@ -127,6 +144,103 @@ private function writeCell(CellElement $cell) return $content; } + private function writeCellStyle(CellStyle $cell, ?TableStyle $table): string + { + $content = $this->writeCellBorder( + 't', + $cell->getBorderTopStyle() ?: ($table ? $table->getBorderTopStyle() : null), + (int) round($cell->getBorderTopSize() ?: ($table ? ($table->getBorderTopSize() ?: 0) : 0)), + $cell->getBorderTopColor() ?? ($table ? $table->getBorderTopColor() : null) + ); + $content .= $this->writeCellBorder( + 'l', + $cell->getBorderLeftStyle() ?: ($table ? $table->getBorderLeftStyle() : null), + (int) round($cell->getBorderLeftSize() ?: ($table ? ($table->getBorderLeftSize() ?: 0) : 0)), + $cell->getBorderLeftColor() ?? ($table ? $table->getBorderLeftColor() : null) + ); + $content .= $this->writeCellBorder( + 'b', + $cell->getBorderBottomStyle() ?: ($table ? $table->getBorderBottomStyle() : null), + (int) round($cell->getBorderBottomSize() ?: ($table ? ($table->getBorderBottomSize() ?: 0) : 0)), + $cell->getBorderBottomColor() ?? ($table ? $table->getBorderBottomColor() : null) + ); + $content .= $this->writeCellBorder( + 'r', + $cell->getBorderRightStyle() ?: ($table ? $table->getBorderRightStyle() : null), + (int) round($cell->getBorderRightSize() ?: ($table ? ($table->getBorderRightSize() ?: 0) : 0)), + $cell->getBorderRightColor() ?? ($table ? $table->getBorderRightColor() : null) + ); + + return $content; + } + + private function writeCellBorder(string $prefix, ?string $borderStyle, int $borderSize, ?string $borderColor): string + { + if ($borderSize == 0) { + return ''; + } + + $content = '\clbrdr' . $prefix; + /** + * \brdrs Single-thickness border. + * \brdrth Double-thickness border. + * \brdrsh Shadowed border. + * \brdrdb Double border. + * \brdrdot Dotted border. + * \brdrdash Dashed border. + * \brdrhair Hairline border. + * \brdrinset Inset border. + * \brdrdashsm Dash border (small). + * \brdrdashd Dot dash border. + * \brdrdashdd Dot dot dash border. + * \brdroutset Outset border. + * \brdrtriple Triple border. + * \brdrtnthsg Thick thin border (small). + * \brdrthtnsg Thin thick border (small). + * \brdrtnthtnsg Thin thick thin border (small). + * \brdrtnthmg Thick thin border (medium). + * \brdrthtnmg Thin thick border (medium). + * \brdrtnthtnmg Thin thick thin border (medium). + * \brdrtnthlg Thick thin border (large). + * \brdrthtnlg Thin thick border (large). + * \brdrtnthtnlg Thin thick thin border (large). + * \brdrwavy Wavy border. + * \brdrwavydb Double wavy border. + * \brdrdashdotstr Striped border. + * \brdremboss Emboss border. + * \brdrengrave Engrave border. + */ + switch ($borderStyle) { + case Border::DOTTED: + $content .= '\brdrdot'; + + break; + case Border::SINGLE: + default: + $content .= '\brdrs'; + + break; + } + + // \brdrwN N is the width in twips (1/20 pt) of the pen used to draw the paragraph border line. + // N cannot be greater than 75. + // To obtain a larger border width, the \brdth control word can be used to obtain a width double that of N. + // $borderSize is in eights of a point, i.e. 4 / 8 = .5pt + // 1/20 pt => 1/8 / 2.5 + $content .= '\brdrw' . (int) ($borderSize / 2.5); + + // \brdrcfN N is the color of the paragraph border, specified as an index into the color table in the RTF header. + $colorIndex = 0; + $index = array_search($borderColor, $this->parentWriter->getColorTable()); + if ($index !== false) { + $colorIndex = (int) $index + 1; + } + $content .= '\brdrcf' . $colorIndex; + $content .= PHP_EOL; + + return $content; + } + /** * Get vertical merge style. * diff --git a/src/PhpWord/Writer/RTF/Part/Header.php b/src/PhpWord/Writer/RTF/Part/Header.php index e4ad4bee0b..7f8cc84b97 100644 --- a/src/PhpWord/Writer/RTF/Part/Header.php +++ b/src/PhpWord/Writer/RTF/Part/Header.php @@ -21,6 +21,7 @@ use PhpOffice\PhpWord\Shared\Converter; use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Style\Font; +use PhpOffice\PhpWord\Style\Table; /** * RTF header part writer. @@ -236,6 +237,14 @@ private function registerFontItems($style): void $this->registerTableItem($this->fontTable, $style->getName(), $defaultFont); $this->registerTableItem($this->colorTable, $style->getColor(), $defaultColor); $this->registerTableItem($this->colorTable, $style->getFgColor(), $defaultColor); + + return; + } + if ($style instanceof Table) { + $this->registerTableItem($this->colorTable, $style->getBorderTopColor(), $defaultColor); + $this->registerTableItem($this->colorTable, $style->getBorderRightColor(), $defaultColor); + $this->registerTableItem($this->colorTable, $style->getBorderLeftColor(), $defaultColor); + $this->registerTableItem($this->colorTable, $style->getBorderBottomColor(), $defaultColor); } } diff --git a/src/PhpWord/Writer/Word2007/Style/MarginBorder.php b/src/PhpWord/Writer/Word2007/Style/MarginBorder.php index 8d08eec3cc..ce250e54d4 100644 --- a/src/PhpWord/Writer/Word2007/Style/MarginBorder.php +++ b/src/PhpWord/Writer/Word2007/Style/MarginBorder.php @@ -120,7 +120,7 @@ public function setSizes($value): void /** * Set colors. * - * @param string[] $value + * @param array $value */ public function setColors($value): void { diff --git a/tests/PhpWordTests/Writer/RTF/Element/TableTest.php b/tests/PhpWordTests/Writer/RTF/Element/TableTest.php new file mode 100644 index 0000000000..35cdfbec28 --- /dev/null +++ b/tests/PhpWordTests/Writer/RTF/Element/TableTest.php @@ -0,0 +1,169 @@ +write()); + } + + public function testTable(): void + { + Settings::setDefaultRtl(false); + $parentWriter = new RTF(); + $element = new \PhpOffice\PhpWord\Element\Table(); + $width = 100; + $width2 = 2 * $width; + $element->addRow(); + $tce = $element->addCell($width); + $tce->addText('1'); + $tce = $element->addCell($width); + $tce->addText('2'); + $element->addRow(); + $tce = $element->addCell($width); + $tce->addText('3'); + $tce = $element->addCell($width); + $tce->addText('4'); + $table = new WriterTable($parentWriter, $element); + $expect = implode("\n", [ + '\\pard', + "\\trowd \\cellx$width \\cellx$width2 ", + '\\intbl', + '\\ql{\\cf0\\f0 1}\\par', + '\\cell', + '\\intbl', + '{\\cf0\\f0 2}\\par', + '\\cell', + '\\row', + "\\trowd \\cellx$width \\cellx$width2 ", + '\\intbl', + '\\ql{\\cf0\\f0 3}\\par', + '\\cell', + '\\intbl', + '{\\cf0\\f0 4}\par', + '\\cell', + '\\row', + '\\pard', + '', + ]); + + self::assertEquals($expect, $this->removeCr($table)); + } + + public function testTableStyle(): void + { + $width = 100; + + Settings::setDefaultRtl(false); + $parentWriter = new RTF(); + + Style::addTableStyle('TableStyle', ['borderSize' => 6, 'borderColor' => '006699']); + + $element = new Table('TableStyle'); + $element->addRow(); + $elementCell = $element->addCell($width); + $elementCell->addText('1'); + + $expect = implode("\n", [ + '\\pard', + '\\trowd \\clbrdrt\\brdrs\\brdrw2\\brdrcf0', + '\\clbrdrl\\brdrs\\brdrw2\\brdrcf0', + '\\clbrdrb\\brdrs\\brdrw2\\brdrcf0', + '\\clbrdrr\\brdrs\\brdrw2\\brdrcf0', + "\\cellx$width ", + '\\intbl', + '\\ql{\\cf0\\f0 1}\\par', + '\\cell', + '\\row', + '\\pard', + '', + ]); + + self::assertEquals($expect, $this->removeCr(new WriterTable($parentWriter, $element))); + } + + public function testTableStyleNotExisting(): void + { + $width = 100; + + Settings::setDefaultRtl(false); + $parentWriter = new RTF(); + + $element = new Table('TableStyleNotExisting'); + $element->addRow(); + $elementCell = $element->addCell($width); + $elementCell->addText('1'); + + $expect = implode("\n", [ + '\\pard', + "\\trowd \\cellx$width ", + '\\intbl', + '\\ql{\\cf0\\f0 1}\\par', + '\\cell', + '\\row', + '\\pard', + '', + ]); + + self::assertEquals($expect, $this->removeCr(new WriterTable($parentWriter, $element))); + } + + public function testTableCellStyle(): void + { + $width = 100; + + Settings::setDefaultRtl(false); + $parentWriter = new RTF(); + + $element = new Table(); + $element->addRow(); + $elementCell = $element->addCell($width, ['borderSize' => 6, 'borderColor' => '006699', 'borderStyle' => Border::DOTTED]); + $elementCell->addText('1'); + + $expect = implode("\n", [ + '\\pard', + '\\trowd \\clbrdrt\\brdrdot\\brdrw2\\brdrcf0', + '\\clbrdrl\\brdrdot\\brdrw2\\brdrcf0', + '\\clbrdrb\\brdrdot\\brdrw2\\brdrcf0', + '\\clbrdrr\\brdrdot\\brdrw2\\brdrcf0', + "\\cellx$width ", + '\\intbl', + '\\ql{\\cf0\\f0 1}\\par', + '\\cell', + '\\row', + '\\pard', + '', + ]); + + self::assertEquals($expect, $this->removeCr(new WriterTable($parentWriter, $element))); + } +} diff --git a/tests/PhpWordTests/Writer/RTF/Element2Test.php b/tests/PhpWordTests/Writer/RTF/Element2Test.php index d82a3095d7..7d36fac869 100644 --- a/tests/PhpWordTests/Writer/RTF/Element2Test.php +++ b/tests/PhpWordTests/Writer/RTF/Element2Test.php @@ -19,7 +19,6 @@ use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Writer\RTF; -use PhpOffice\PhpWord\Writer\RTF\Element\Table as WriterTable; use PhpOffice\PhpWord\Writer\RTF\Element\TextRun as WriterTextRun; use PhpOffice\PhpWord\Writer\RTF\Element\Title as WriterTitle; @@ -33,55 +32,12 @@ protected function tearDown(): void Settings::setDefaultRtl(null); } - /** @param WriterTable|WriterTextRun|WriterTitle $field */ + /** @param WriterTextRun|WriterTitle $field */ public function removeCr($field): string { return str_replace("\r\n", "\n", $field->write()); } - public function testTable(): void - { - Settings::setDefaultRtl(false); - $parentWriter = new RTF(); - $element = new \PhpOffice\PhpWord\Element\Table(); - $width = 100; - $width2 = 2 * $width; - $element->addRow(); - $tce = $element->addCell($width); - $tce->addText('1'); - $tce = $element->addCell($width); - $tce->addText('2'); - $element->addRow(); - $tce = $element->addCell($width); - $tce->addText('3'); - $tce = $element->addCell($width); - $tce->addText('4'); - $table = new WriterTable($parentWriter, $element); - $expect = implode("\n", [ - '\\pard', - "\\trowd \\cellx$width \\cellx$width2 ", - '\\intbl', - '\\ql{\\cf0\\f0 1}\\par', - '\\cell', - '\\intbl', - '{\\cf0\\f0 2}\\par', - '\\cell', - '\\row', - "\\trowd \\cellx$width \\cellx$width2 ", - '\\intbl', - '\\ql{\\cf0\\f0 3}\\par', - '\\cell', - '\\intbl', - '{\\cf0\\f0 4}\par', - '\\cell', - '\\row', - '\\pard', - '', - ]); - - self::assertEquals($expect, $this->removeCr($table)); - } - public function testTextRun(): void { Settings::setDefaultRtl(false); From dbf0a3e427bceb5744b760c23aeb7ddf558803d3 Mon Sep 17 00:00:00 2001 From: Jack Sleight Date: Wed, 14 Aug 2024 03:50:25 +0100 Subject: [PATCH 203/246] Word2007 Writer : Fixed first footnote appearing as separator (#2635) * Fix first footnote appearing as separator * Add test * Update changelog * Fixed changelog --------- Co-authored-by: Progi1984 --- docs/changes/2.x/2.0.0.md | 1 + src/PhpWord/Writer/Word2007/Element/Footnote.php | 2 +- src/PhpWord/Writer/Word2007/Part/Footnotes.php | 2 +- tests/PhpWordTests/Writer/Word2007/Part/FootnotesTest.php | 3 +++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 219db0c939..121ce9bb4c 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -25,6 +25,7 @@ - Documentation : Updated Comment element by [@laminga](https://github.com/laminga) in [#2650](https://github.com/PHPOffice/PHPWord/pull/2650) - HTML Reader : Read width & height attributes in points fixing [#2589](https://github.com/PHPOffice/PHPWord/issues/2589) by [@Progi1984](https://github.com/Progi1984) in [#2654](https://github.com/PHPOffice/PHPWord/pull/2654) - Template Processor : Fixed bad naming of variables fixing [#2586](https://github.com/PHPOffice/PHPWord/issues/2586) by [@Progi1984](https://github.com/Progi1984) in [#2655](https://github.com/PHPOffice/PHPWord/pull/2655) +- Word2007 Writer : Fix first footnote appearing as separator [#2634](https://github.com/PHPOffice/PHPWord/issues/2634) by [@jacksleight](https://github.com/jacksleight) in [#2635](https://github.com/PHPOffice/PHPWord/pull/2635) ### Miscellaneous diff --git a/src/PhpWord/Writer/Word2007/Element/Footnote.php b/src/PhpWord/Writer/Word2007/Element/Footnote.php index b59fc5e1cc..77073a239d 100644 --- a/src/PhpWord/Writer/Word2007/Element/Footnote.php +++ b/src/PhpWord/Writer/Word2007/Element/Footnote.php @@ -51,7 +51,7 @@ public function write(): void $xmlWriter->endElement(); // w:rStyle $xmlWriter->endElement(); // w:rPr $xmlWriter->startElement("w:{$this->referenceType}"); - $xmlWriter->writeAttribute('w:id', $element->getRelationId()); + $xmlWriter->writeAttribute('w:id', $element->getRelationId() + 1); $xmlWriter->endElement(); // w:$referenceType $xmlWriter->endElement(); // w:r diff --git a/src/PhpWord/Writer/Word2007/Part/Footnotes.php b/src/PhpWord/Writer/Word2007/Part/Footnotes.php index 9624ab7459..e284c674b5 100644 --- a/src/PhpWord/Writer/Word2007/Part/Footnotes.php +++ b/src/PhpWord/Writer/Word2007/Part/Footnotes.php @@ -141,7 +141,7 @@ public function setElements($elements) protected function writeNote(XMLWriter $xmlWriter, $element): void { $xmlWriter->startElement($this->elementNode); - $xmlWriter->writeAttribute('w:id', $element->getRelationId()); + $xmlWriter->writeAttribute('w:id', $element->getRelationId() + 1); $xmlWriter->startElement('w:p'); // Paragraph style diff --git a/tests/PhpWordTests/Writer/Word2007/Part/FootnotesTest.php b/tests/PhpWordTests/Writer/Word2007/Part/FootnotesTest.php index 14872970a1..526d3591e8 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/FootnotesTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/FootnotesTest.php @@ -49,5 +49,8 @@ public function testWriteFootnotes(): void self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:footnoteReference')); self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:endnoteReference')); + + self::assertFalse($doc->elementExists('/w:document/w:body/w:p/w:r/w:footnoteReference[@w:id="0"]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:footnoteReference[@w:id="1"]')); } } From a7b90305a3379f0d469dd2ad063f6feaf7adeb44 Mon Sep 17 00:00:00 2001 From: Elwyn Van der Borght <38124619+ElwynVdb@users.noreply.github.com> Date: Thu, 15 Aug 2024 16:26:15 +0200 Subject: [PATCH 204/246] Fix transparent background images to be displayed correctly (#2638) * fix(TemplateProcessor): Images with transparent backgrounds are now correctly displayed with transparency. * docs: Updated changelog * docs: Name --- docs/changes/2.x/2.0.0.md | 1 + src/PhpWord/TemplateProcessor.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index 121ce9bb4c..f1e5583e7c 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -26,6 +26,7 @@ - HTML Reader : Read width & height attributes in points fixing [#2589](https://github.com/PHPOffice/PHPWord/issues/2589) by [@Progi1984](https://github.com/Progi1984) in [#2654](https://github.com/PHPOffice/PHPWord/pull/2654) - Template Processor : Fixed bad naming of variables fixing [#2586](https://github.com/PHPOffice/PHPWord/issues/2586) by [@Progi1984](https://github.com/Progi1984) in [#2655](https://github.com/PHPOffice/PHPWord/pull/2655) - Word2007 Writer : Fix first footnote appearing as separator [#2634](https://github.com/PHPOffice/PHPWord/issues/2634) by [@jacksleight](https://github.com/jacksleight) in [#2635](https://github.com/PHPOffice/PHPWord/pull/2635) +- Template Processor : Fixed images with transparent backgrounds displaying a white background by [@ElwynVdb](https://github.com/ElwynVdb) in [#2638](https://github.com/PHPOffice/PHPWord/pull/2638) ### Miscellaneous diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 8bef424fd1..f6fe1d8887 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -668,7 +668,7 @@ public function setImageValue($search, $replace, $limit = self::MAXIMUM_REPLACEM // define templates // result can be verified via "Open XML SDK 2.5 Productivity Tool" (http://www.microsoft.com/en-us/download/details.aspx?id=30425) - $imgTpl = ''; + $imgTpl = ''; $i = 0; foreach ($searchParts as $partFileName => &$partContent) { From 39e806b7235c7a3ff2d1eaa776f7fd696b0a68af Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Mon, 26 Aug 2024 17:33:45 +0200 Subject: [PATCH 205/246] HTML Writer : Fixed rowspan for tables (#2659) Co-authored-by: Evgeniya Gryaznova --- docs/changes/{2.x/2.0.0.md => 1.x/1.3.0.md} | 5 +- mkdocs.yml | 3 +- phpstan-baseline.neon | 9 +-- samples/Sample_09_Tables.php | 41 ++++++------ src/PhpWord/Writer/HTML/Element/Table.php | 65 ++++++++++++++++--- .../PhpWordTests/Writer/HTML/ElementTest.php | 46 ++++++++++--- 6 files changed, 118 insertions(+), 51 deletions(-) rename docs/changes/{2.x/2.0.0.md => 1.x/1.3.0.md} (96%) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/1.x/1.3.0.md similarity index 96% rename from docs/changes/2.x/2.0.0.md rename to docs/changes/1.x/1.3.0.md index f1e5583e7c..7b07ed2406 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/1.x/1.3.0.md @@ -1,6 +1,6 @@ -# [2.0.0](https://github.com/PHPOffice/PHPWord/tree/2.0.0) (WIP) +# [1.3.0](https://github.com/PHPOffice/PHPWord/tree/1.3.0) (WIP) -[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.2.0...2.0.0) +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.2.0...1.3.0) ## Enhancements @@ -27,6 +27,7 @@ - Template Processor : Fixed bad naming of variables fixing [#2586](https://github.com/PHPOffice/PHPWord/issues/2586) by [@Progi1984](https://github.com/Progi1984) in [#2655](https://github.com/PHPOffice/PHPWord/pull/2655) - Word2007 Writer : Fix first footnote appearing as separator [#2634](https://github.com/PHPOffice/PHPWord/issues/2634) by [@jacksleight](https://github.com/jacksleight) in [#2635](https://github.com/PHPOffice/PHPWord/pull/2635) - Template Processor : Fixed images with transparent backgrounds displaying a white background by [@ElwynVdb](https://github.com/ElwynVdb) in [#2638](https://github.com/PHPOffice/PHPWord/pull/2638) +- HTML Writer : Fixed rowspan for tables by [@andomiell](https://github.com/andomiell) in [#2659](https://github.com/PHPOffice/PHPWord/pull/2659) ### Miscellaneous diff --git a/mkdocs.yml b/mkdocs.yml index 6eb4d42911..dfabbb195a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -86,9 +86,8 @@ nav: - How to: 'howto.md' - Credits: 'credits.md' - Releases: - - '2.x': - - '2.0.0 (WIP)': 'changes/2.x/2.0.0.md' - '1.x': + - '1.3.0 (WIP)': 'changes/1.x/1.3.0.md' - '1.2.0': 'changes/1.x/1.2.0.md' - '1.1.0': 'changes/1.x/1.1.0.md' - '1.0.0': 'changes/1.x/1.0.0.md' diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 026fd8b59a..909718b83b 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1787,17 +1787,12 @@ parameters: - message: "#^Cannot access property \\$length on DOMNodeList\\\\|false\\.$#" - count: 6 + count: 9 path: tests/PhpWordTests/Writer/HTML/ElementTest.php - message: "#^Cannot call method item\\(\\) on DOMNodeList\\\\|false\\.$#" - count: 8 - path: tests/PhpWordTests/Writer/HTML/ElementTest.php - - - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\Writer\\\\HTML\\\\ElementTest\\:\\:getAsHTML\\(\\) has no return type specified\\.$#" - count: 1 + count: 11 path: tests/PhpWordTests/Writer/HTML/ElementTest.php - diff --git a/samples/Sample_09_Tables.php b/samples/Sample_09_Tables.php index f1b67c9ecc..877072d898 100644 --- a/samples/Sample_09_Tables.php +++ b/samples/Sample_09_Tables.php @@ -56,11 +56,13 @@ /* * 3. colspan (gridSpan) and rowspan (vMerge) - * --------------------- - * | | B | | - * | A |--------| E | - * | | C | D | | - * --------------------- + * ------------------------- + * | A | B | C | + * |-----|-----------| | + * | D | | + * ------|-----------| | + * | E | F | G | | + * ------------------------- */ $section->addPageBreak(); @@ -77,25 +79,20 @@ $phpWord->addTableStyle($spanTableStyleName, $fancyTableStyle); $table = $section->addTable($spanTableStyleName); -$table->addRow(); - -$cell1 = $table->addCell(2000, $cellRowSpan); -$textrun1 = $cell1->addTextRun($cellHCentered); -$textrun1->addText('A'); -$textrun1->addFootnote()->addText('Row span'); - -$cell2 = $table->addCell(4000, $cellColSpan); -$textrun2 = $cell2->addTextRun($cellHCentered); -$textrun2->addText('B'); -$textrun2->addFootnote()->addText('Column span'); +$row1 = $table->addRow(); +$row1->addCell(500)->addText('A'); +$row1->addCell(1000, ['gridSpan' => 2])->addText('B'); +$row1->addCell(500, ['vMerge' => 'restart'])->addText('C'); -$table->addCell(2000, $cellRowSpan)->addText('E', null, $cellHCentered); +$row2 = $table->addRow(); +$row2->addCell(1500, ['gridSpan' => 3])->addText('D'); +$row2->addCell(null, ['vMerge' => 'continue']); -$table->addRow(); -$table->addCell(null, $cellRowContinue); -$table->addCell(2000, $cellVCentered)->addText('C', null, $cellHCentered); -$table->addCell(2000, $cellVCentered)->addText('D', null, $cellHCentered); -$table->addCell(null, $cellRowContinue); +$row3 = $table->addRow(); +$row3->addCell(500)->addText('E'); +$row3->addCell(500)->addText('F'); +$row3->addCell(500)->addText('G'); +$row3->addCell(null, ['vMerge' => 'continue']); /* * 4. colspan (gridSpan) and rowspan (vMerge) diff --git a/src/PhpWord/Writer/HTML/Element/Table.php b/src/PhpWord/Writer/HTML/Element/Table.php index f4acc8cdf4..7f8d0bcc3c 100644 --- a/src/PhpWord/Writer/HTML/Element/Table.php +++ b/src/PhpWord/Writer/HTML/Element/Table.php @@ -65,16 +65,9 @@ public function write() $cellColSpan = $cellStyle->getGridSpan(); $cellRowSpan = 1; $cellVMerge = $cellStyle->getVMerge(); - // If this is the first cell of the vertical merge, find out how man rows it spans + // If this is the first cell of the vertical merge, find out how many rows it spans if ($cellVMerge === 'restart') { - for ($k = $i + 1; $k < $rowCount; ++$k) { - $kRowCells = $rows[$k]->getCells(); - if (isset($kRowCells[$j]) && $kRowCells[$j]->getStyle()->getVMerge() === 'continue') { - ++$cellRowSpan; - } else { - break; - } - } + $cellRowSpan = $this->calculateCellRowSpan($rows, $i, $j); } // Ignore cells that are merged vertically with previous rows if ($cellVMerge !== 'continue') { @@ -131,4 +124,58 @@ private function getTableStyle($tableStyle = null): string return ' style="' . $style . '"'; } + + /** + * Calculates cell rowspan. + * + * @param \PhpOffice\PhpWord\Element\Row[] $rows + */ + private function calculateCellRowSpan(array $rows, int $rowIndex, int $colIndex): int + { + $currentRow = $rows[$rowIndex]; + $currentRowCells = $currentRow->getCells(); + $shiftedColIndex = 0; + + foreach ($currentRowCells as $cell) { + if ($cell === $currentRowCells[$colIndex]) { + break; + } + + $colSpan = 1; + + if ($cell->getStyle()->getGridSpan() !== null) { + $colSpan = $cell->getStyle()->getGridSpan(); + } + + $shiftedColIndex += $colSpan; + } + + $rowCount = count($rows); + $rowSpan = 1; + + for ($i = $rowIndex + 1; $i < $rowCount; ++$i) { + $rowCells = $rows[$i]->getCells(); + $colIndex = 0; + + foreach ($rowCells as $cell) { + if ($colIndex === $shiftedColIndex) { + if ($cell->getStyle()->getVMerge() === 'continue') { + ++$rowSpan; + } + + break; + } + + $colSpan = 1; + + if ($cell->getStyle()->getGridSpan() !== null) { + $colSpan = $cell->getStyle()->getGridSpan(); + } + + $colIndex += $colSpan; + } + } + + return $rowSpan; + } } diff --git a/tests/PhpWordTests/Writer/HTML/ElementTest.php b/tests/PhpWordTests/Writer/HTML/ElementTest.php index 64fa5a31ff..3fee31a69b 100644 --- a/tests/PhpWordTests/Writer/HTML/ElementTest.php +++ b/tests/PhpWordTests/Writer/HTML/ElementTest.php @@ -73,7 +73,7 @@ public function testWriteTrackChanges(): void $text2 = $section->addText('my other text'); $text2->setTrackChange(new TrackChange(TrackChange::DELETED, 'another author', new DateTime())); - $dom = $this->getAsHTML($phpWord); + $dom = Helper::getAsHTML($phpWord); $xpath = new DOMXPath($dom); self::assertEquals(1, $xpath->query('/html/body/div/p[1]/ins')->length); @@ -97,7 +97,7 @@ public function testWriteColSpan(): void $cell22 = $row2->addCell(500); $cell22->addText('second cell'); - $dom = $this->getAsHTML($phpWord); + $dom = Helper::getAsHTML($phpWord); $xpath = new DOMXPath($dom); self::assertEquals(1, $xpath->query('/html/body/div/table/tr[1]/td')->length); @@ -131,7 +131,7 @@ public function testWriteRowSpan(): void $row3->addCell(null, ['vMerge' => 'continue']); $row3->addCell(500)->addText('third cell being spanned'); - $dom = $this->getAsHTML($phpWord); + $dom = Helper::getAsHTML($phpWord); $xpath = new DOMXPath($dom); self::assertEquals(2, $xpath->query('/html/body/div/table/tr[1]/td')->length); @@ -139,13 +139,41 @@ public function testWriteRowSpan(): void self::assertEquals(1, $xpath->query('/html/body/div/table/tr[2]/td')->length); } - private function getAsHTML(PhpWord $phpWord) + /** + * Tests writing table with rowspan and colspan. + */ + public function testWriteRowSpanAndColSpan(): void { - $htmlWriter = new HTML($phpWord); - $dom = new DOMDocument(); - $dom->loadHTML($htmlWriter->getContent()); + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $table = $section->addTable(); + + $row1 = $table->addRow(); + $row1->addCell(500)->addText('A'); + $row1->addCell(1000, ['gridSpan' => 2])->addText('B'); + $row1->addCell(500, ['vMerge' => 'restart'])->addText('C'); + + $row2 = $table->addRow(); + $row2->addCell(1500, ['gridSpan' => 3])->addText('D'); + $row2->addCell(null, ['vMerge' => 'continue']); + + $row3 = $table->addRow(); + $row3->addCell(500)->addText('E'); + $row3->addCell(500)->addText('F'); + $row3->addCell(500)->addText('G'); + $row3->addCell(null, ['vMerge' => 'continue']); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + self::assertEquals(3, $xpath->query('/html/body/div/table/tr[1]/td')->length); + self::assertEquals('2', $xpath->query('/html/body/div/table/tr[1]/td[2]')->item(0)->attributes->getNamedItem('colspan')->textContent); + self::assertEquals('3', $xpath->query('/html/body/div/table/tr[1]/td[3]')->item(0)->attributes->getNamedItem('rowspan')->textContent); + + self::assertEquals(1, $xpath->query('/html/body/div/table/tr[2]/td')->length); + self::assertEquals('3', $xpath->query('/html/body/div/table/tr[2]/td[1]')->item(0)->attributes->getNamedItem('colspan')->textContent); - return $dom; + self::assertEquals(3, $xpath->query('/html/body/div/table/tr[3]/td')->length); } public function testWriteTitleTextRun(): void @@ -208,7 +236,7 @@ public function testWriteTableLayout(): void $row2 = $table2->addRow(); $row2->addCell()->addText('auto layout table'); - $dom = $this->getAsHTML($phpWord); + $dom = Helper::getAsHTML($phpWord); $xpath = new DOMXPath($dom); self::assertEquals('table-layout: fixed;', $xpath->query('/html/body/div/table[1]')->item(0)->attributes->getNamedItem('style')->textContent); From 89a202e6e3803b78b69bdb484fcbe4b1e562aec4 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Tue, 27 Aug 2024 12:26:13 +0200 Subject: [PATCH 206/246] Word2007 Writer : Fixed StrikeThrough property (#2661) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Noé --- docs/changes/1.x/1.3.0.md | 1 + src/PhpWord/Style/Font.php | 16 +++------ src/PhpWord/Writer/Word2007/Style/Font.php | 4 +-- .../Writer/Word2007/Part/DocumentTest.php | 35 +++++++++++++++++++ 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/docs/changes/1.x/1.3.0.md b/docs/changes/1.x/1.3.0.md index 7b07ed2406..4e38e38f91 100644 --- a/docs/changes/1.x/1.3.0.md +++ b/docs/changes/1.x/1.3.0.md @@ -28,6 +28,7 @@ - Word2007 Writer : Fix first footnote appearing as separator [#2634](https://github.com/PHPOffice/PHPWord/issues/2634) by [@jacksleight](https://github.com/jacksleight) in [#2635](https://github.com/PHPOffice/PHPWord/pull/2635) - Template Processor : Fixed images with transparent backgrounds displaying a white background by [@ElwynVdb](https://github.com/ElwynVdb) in [#2638](https://github.com/PHPOffice/PHPWord/pull/2638) - HTML Writer : Fixed rowspan for tables by [@andomiell](https://github.com/andomiell) in [#2659](https://github.com/PHPOffice/PHPWord/pull/2659) +- Word2007 Writer : Fixed StrikeThrough property by [@noec764](https://github.com/noec764) fixing [#1722](https://github.com/PHPOffice/PHPWord/issues/1722) & [#1693](https://github.com/PHPOffice/PHPWord/issues/1693) in [#2661](https://github.com/PHPOffice/PHPWord/pull/2661) ### Miscellaneous diff --git a/src/PhpWord/Style/Font.php b/src/PhpWord/Style/Font.php index fda95a9432..a4580bc87b 100644 --- a/src/PhpWord/Style/Font.php +++ b/src/PhpWord/Style/Font.php @@ -565,10 +565,8 @@ public function setSubScript($value = true) /** * Get strikethrough. - * - * @return bool */ - public function isStrikethrough() + public function isStrikethrough(): ?bool { return $this->strikethrough; } @@ -577,20 +575,16 @@ public function isStrikethrough() * Set strikethrough. * * @param bool $value - * - * @return self */ - public function setStrikethrough($value = true) + public function setStrikethrough($value = true): self { return $this->setPairedVal($this->strikethrough, $this->doubleStrikethrough, $value); } /** * Get double strikethrough. - * - * @return bool */ - public function isDoubleStrikethrough() + public function isDoubleStrikethrough(): ?bool { return $this->doubleStrikethrough; } @@ -599,10 +593,8 @@ public function isDoubleStrikethrough() * Set double strikethrough. * * @param bool $value - * - * @return self */ - public function setDoubleStrikethrough($value = true) + public function setDoubleStrikethrough($value = true): self { return $this->setPairedVal($this->doubleStrikethrough, $this->strikethrough, $value); } diff --git a/src/PhpWord/Writer/Word2007/Style/Font.php b/src/PhpWord/Writer/Word2007/Style/Font.php index 8d9697715c..1f6db009e4 100644 --- a/src/PhpWord/Writer/Word2007/Style/Font.php +++ b/src/PhpWord/Writer/Word2007/Style/Font.php @@ -117,8 +117,8 @@ private function writeStyle(): void $xmlWriter->writeElementIf($style->isItalic() !== null, 'w:iCs', 'w:val', $this->writeOnOf($style->isItalic())); // Strikethrough, double strikethrough - $xmlWriter->writeElementIf($style->isStrikethrough() !== null, 'w:strike', 'w:val', $this->writeOnOf($style->isStrikethrough())); - $xmlWriter->writeElementIf($style->isDoubleStrikethrough() !== null, 'w:dstrike', 'w:val', $this->writeOnOf($style->isDoubleStrikethrough())); + $xmlWriter->writeElementIf($style->isStrikethrough(), 'w:strike', 'w:val', $this->writeOnOf($style->isStrikethrough())); + $xmlWriter->writeElementIf($style->isDoubleStrikethrough(), 'w:dstrike', 'w:val', $this->writeOnOf($style->isDoubleStrikethrough())); // Small caps, all caps $xmlWriter->writeElementIf($style->isSmallCaps() !== null, 'w:smallCaps', 'w:val', $this->writeOnOf($style->isSmallCaps())); diff --git a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php index 58aaf6df6d..76c05786c0 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php @@ -533,12 +533,47 @@ public function testWriteFontStyle(): void self::assertTrue($doc->elementExists("{$parent}/w:i")); self::assertEquals($styles['underline'], $doc->getElementAttribute("{$parent}/w:u", 'w:val')); self::assertTrue($doc->elementExists("{$parent}/w:strike")); + self::assertFalse($doc->elementExists("{$parent}/w:dstrike")); self::assertEquals('superscript', $doc->getElementAttribute("{$parent}/w:vertAlign", 'w:val')); self::assertEquals($styles['color'], $doc->getElementAttribute("{$parent}/w:color", 'w:val')); self::assertEquals($styles['fgColor'], $doc->getElementAttribute("{$parent}/w:highlight", 'w:val')); self::assertTrue($doc->elementExists("{$parent}/w:smallCaps")); } + /** + * covers ::_writeTextStyle. + * + * @dataProvider providerFontStyleStrikethrough + */ + public function testWriteFontStyleStrikethrough( + bool $isStrikethrough, + bool $isDoubleStrikethrough, + bool $expectedStrikethrough, + bool $expectedDoubleStrikethrough + ): void { + $phpWord = new PhpWord(); + $styles['strikethrough'] = $isStrikethrough; + $styles['doublestrikethrough'] = $isDoubleStrikethrough; + + $section = $phpWord->addSection(); + $section->addText('Test', $styles); + $doc = TestHelperDOCX::getDocument($phpWord); + + $parent = '/w:document/w:body/w:p/w:r/w:rPr'; + self::assertSame($expectedStrikethrough, $doc->elementExists("{$parent}/w:strike")); + self::assertSame($expectedDoubleStrikethrough, $doc->elementExists("{$parent}/w:dstrike")); + } + + public static function providerFontStyleStrikethrough(): iterable + { + return [ + [true, true, false, true], + [true, false, true, false], + [false, true, false, true], + [false, false, false, false], + ]; + } + /** * Tests that if no color is set on a cell a border gets writen with the default color. */ From 249412be6f4eaf481e9f7d7184cecdbf17b14032 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 28 Aug 2024 13:28:20 +0200 Subject: [PATCH 207/246] Word2007 Reader: Support the page break () (#2662) Co-authored-by: stanolacko --- docs/changes/1.x/1.3.0.md | 1 + src/PhpWord/Reader/Word2007/AbstractPart.php | 19 +++++++++++-------- src/PhpWord/Reader/Word2007/Document.php | 2 -- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/docs/changes/1.x/1.3.0.md b/docs/changes/1.x/1.3.0.md index 4e38e38f91..f55fc6d262 100644 --- a/docs/changes/1.x/1.3.0.md +++ b/docs/changes/1.x/1.3.0.md @@ -10,6 +10,7 @@ - Word2007 Writer: Support for field REF by [@crystoline](https://github.com/crystoline) in [#2652](https://github.com/PHPOffice/PHPWord/pull/2652) - Word2007 Reader : Support for FormFields by [@vincentKool](https://github.com/vincentKool) in [#2653](https://github.com/PHPOffice/PHPWord/pull/2653) - RTF Writer : Support for Table Border Style fixing [#345](https://github.com/PHPOffice/PHPWord/issues/345) by [@Progi1984](https://github.com/Progi1984) in [#2656](https://github.com/PHPOffice/PHPWord/pull/2656) +- Word2007 Reader: Support the page break () by [@stanolacko](https://github.com/stanolacko) in [#2662](https://github.com/PHPOffice/PHPWord/pull/2662) ### Bug fixes diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 0f3d8bf711..98a74772cd 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -236,18 +236,21 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par $fontStyle = $this->readFontStyle($xmlReader, $domNode); $nodes = $xmlReader->getElements('w:r', $domNode); foreach ($nodes as $node) { - $instrText = $xmlReader->getValue('w:instrText', $node); - if ($xmlReader->elementExists('w:fldChar', $node)) { - $fldCharType = $xmlReader->getAttribute('w:fldCharType', $node, 'w:fldChar'); - if ('begin' == $fldCharType) { - $ignoreText = true; - } elseif ('end' == $fldCharType) { - $ignoreText = false; - } + if ($xmlReader->elementExists('w:lastRenderedPageBreak', $node)) { + $parent->addPageBreak(); } + $instrText = $xmlReader->getValue('w:instrText', $node); if (null !== $instrText) { $textContent .= '{' . $instrText . '}'; } else { + if ($xmlReader->elementExists('w:fldChar', $node)) { + $fldCharType = $xmlReader->getAttribute('w:fldCharType', $node, 'w:fldChar'); + if ('begin' == $fldCharType) { + $ignoreText = true; + } elseif ('end' == $fldCharType) { + $ignoreText = false; + } + } if (false === $ignoreText) { $textContent .= $xmlReader->getValue('w:t', $node); } diff --git a/src/PhpWord/Reader/Word2007/Document.php b/src/PhpWord/Reader/Word2007/Document.php index da42bddc9e..87a24f4198 100644 --- a/src/PhpWord/Reader/Word2007/Document.php +++ b/src/PhpWord/Reader/Word2007/Document.php @@ -138,8 +138,6 @@ private function readSectionStyle(XMLReader $xmlReader, DOMElement $domNode) /** * Read w:p node. - * - * @todo */ private function readWPNode(XMLReader $xmlReader, DOMElement $node, Section &$section): void { From 9f755a4fe874ae58b85a142b6d2697bbd0a496fe Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Fri, 30 Aug 2024 09:20:46 +0200 Subject: [PATCH 208/246] HTML Reader : Fixed link without href (#2663) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Åsmund Stavdahl --- docs/changes/1.x/1.3.0.md | 1 + src/PhpWord/Shared/Html.php | 6 +++++- tests/PhpWordTests/Shared/HtmlTest.php | 21 +++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/changes/1.x/1.3.0.md b/docs/changes/1.x/1.3.0.md index f55fc6d262..6157befb03 100644 --- a/docs/changes/1.x/1.3.0.md +++ b/docs/changes/1.x/1.3.0.md @@ -30,6 +30,7 @@ - Template Processor : Fixed images with transparent backgrounds displaying a white background by [@ElwynVdb](https://github.com/ElwynVdb) in [#2638](https://github.com/PHPOffice/PHPWord/pull/2638) - HTML Writer : Fixed rowspan for tables by [@andomiell](https://github.com/andomiell) in [#2659](https://github.com/PHPOffice/PHPWord/pull/2659) - Word2007 Writer : Fixed StrikeThrough property by [@noec764](https://github.com/noec764) fixing [#1722](https://github.com/PHPOffice/PHPWord/issues/1722) & [#1693](https://github.com/PHPOffice/PHPWord/issues/1693) in [#2661](https://github.com/PHPOffice/PHPWord/pull/2661) +- HTML Reader : Fixed link without href by [@asmundstavdahl](https://github.com/asmundstavdahl) fixing [#1562](https://github.com/PHPOffice/PHPWord/issues/1562) in [#2663](https://github.com/PHPOffice/PHPWord/pull/2663) ### Miscellaneous diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 602b74ccbb..f65c67435b 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -1156,7 +1156,11 @@ protected static function parseLink($node, $element, &$styles) } $styles['font'] = self::parseInlineStyle($node, $styles['font']); - if (strpos($target, '#') === 0) { + if (empty($target)) { + $target = '#'; + } + + if (strpos($target, '#') === 0 && strlen($target) > 1) { return $element->addLink(substr($target, 1), $node->textContent, $styles['font'], $styles['paragraph'], true); } diff --git a/tests/PhpWordTests/Shared/HtmlTest.php b/tests/PhpWordTests/Shared/HtmlTest.php index 8144eb6f72..2d39701cd1 100644 --- a/tests/PhpWordTests/Shared/HtmlTest.php +++ b/tests/PhpWordTests/Shared/HtmlTest.php @@ -984,6 +984,27 @@ public function testParseLink2(): void self::assertEquals('bookmark', $doc->getElement('/w:document/w:body/w:p/w:hyperlink')->getAttribute('w:anchor')); } + public function testParseLinkAllowsAbsenceOfHref(): void + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $html = '

text of href-less link

'; + Html::addHtml($section, $html); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:hyperlink')); + self::assertEquals('text of href-less link', $doc->getElement('/w:document/w:body/w:p/w:hyperlink/w:r/w:t')->nodeValue); + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $html = '

text of empty-href link

'; + Html::addHtml($section, $html); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:hyperlink')); + self::assertEquals('text of empty-href link', $doc->getElement('/w:document/w:body/w:p/w:hyperlink/w:r/w:t')->nodeValue); + } + public function testParseMalformedStyleIsIgnored(): void { $phpWord = new PhpWord(); From b0ed3dbde7e83cde271fa6b0f765fde823b0df52 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Fri, 30 Aug 2024 13:50:43 +0200 Subject: [PATCH 209/246] MsDoc Reader: Support for UTF-8 characters (#2664) --- docs/changes/1.x/1.3.0.md | 1 + src/PhpWord/Reader/MsDoc.php | 10 +-- tests/PhpWordTests/Reader/MsDocTest.php | 66 ++++++++++++++++-- .../_files/documents/docChinese.doc | Bin 0 -> 2479104 bytes .../_files/documents/docCzech.doc | Bin 0 -> 10752 bytes .../_files/documents/docSlovak.doc | Bin 0 -> 32768 bytes 6 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 tests/PhpWordTests/_files/documents/docChinese.doc create mode 100644 tests/PhpWordTests/_files/documents/docCzech.doc create mode 100644 tests/PhpWordTests/_files/documents/docSlovak.doc diff --git a/docs/changes/1.x/1.3.0.md b/docs/changes/1.x/1.3.0.md index 6157befb03..a843c80bb1 100644 --- a/docs/changes/1.x/1.3.0.md +++ b/docs/changes/1.x/1.3.0.md @@ -11,6 +11,7 @@ - Word2007 Reader : Support for FormFields by [@vincentKool](https://github.com/vincentKool) in [#2653](https://github.com/PHPOffice/PHPWord/pull/2653) - RTF Writer : Support for Table Border Style fixing [#345](https://github.com/PHPOffice/PHPWord/issues/345) by [@Progi1984](https://github.com/Progi1984) in [#2656](https://github.com/PHPOffice/PHPWord/pull/2656) - Word2007 Reader: Support the page break () by [@stanolacko](https://github.com/stanolacko) in [#2662](https://github.com/PHPOffice/PHPWord/pull/2662) +- MsDoc Reader: Support for UTF-8 characters by [@Progi1984] fixing [#881](https://github.com/PHPOffice/PHPWord/issues/881), [#1454](https://github.com/PHPOffice/PHPWord/issues/1454), [#1817](https://github.com/PHPOffice/PHPWord/issues/1817), [#1927](https://github.com/PHPOffice/PHPWord/issues/1927), [#2383](https://github.com/PHPOffice/PHPWord/issues/2383), [#2565](https://github.com/PHPOffice/PHPWord/issues/2565) in [#2664](https://github.com/PHPOffice/PHPWord/pull/2664) ### Bug fixes diff --git a/src/PhpWord/Reader/MsDoc.php b/src/PhpWord/Reader/MsDoc.php index 2599e42350..72b9af6c59 100644 --- a/src/PhpWord/Reader/MsDoc.php +++ b/src/PhpWord/Reader/MsDoc.php @@ -1279,10 +1279,12 @@ private function readRecordPlcfBtePapx(): void break; } $strLen = $arrayRGFC[$key + 1] - $arrayRGFC[$key] - 1; - for ($inc = 0; $inc < $strLen; ++$inc) { - $byte = self::getInt1d($this->dataWorkDocument, $arrayRGFC[$key] + $inc); + for ($inc = 0; $inc < ($strLen * 2); ++$inc) { + $byte = self::getInt2d($this->dataWorkDocument, $arrayRGFC[$key] + ($inc * 2)); if ($byte > 0) { - $string .= chr($byte); + $string .= mb_chr($byte, 'UTF-8'); + } else { + break; } } } @@ -2331,7 +2333,7 @@ private function generatePhpWord(): void foreach ($this->arrayParagraphs as $itmParagraph) { $textPara = $itmParagraph; foreach ($this->arrayCharacters as $oCharacters) { - $subText = substr($textPara, $oCharacters->pos_start, $oCharacters->pos_len); + $subText = mb_substr($textPara, $oCharacters->pos_start, $oCharacters->pos_len); $subText = str_replace(chr(13), PHP_EOL, $subText); $arrayText = explode(PHP_EOL, $subText); if (end($arrayText) == '') { diff --git a/tests/PhpWordTests/Reader/MsDocTest.php b/tests/PhpWordTests/Reader/MsDocTest.php index b62d545de0..b243fccfee 100644 --- a/tests/PhpWordTests/Reader/MsDocTest.php +++ b/tests/PhpWordTests/Reader/MsDocTest.php @@ -18,7 +18,9 @@ namespace PhpOffice\PhpWordTests\Reader; use Exception; +use PhpOffice\PhpWord\Element\Text; use PhpOffice\PhpWord\IOFactory; +use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Reader\MsDoc; /** @@ -50,14 +52,20 @@ public function testCanReadFailed(): void self::assertFalse($object->canRead($filename)); } - /** - * Load. - */ - public function testLoad(): void + public function testLoadBasic(): void { $filename = __DIR__ . '/../_files/documents/reader.doc'; $phpWord = IOFactory::load($filename, 'MsDoc'); - self::assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); + self::assertInstanceOf(PhpWord::class, $phpWord); + + $sections = $phpWord->getSections(); + self::assertCount(1, $sections); + $elements = $sections[0]->getElements(); + self::assertArrayHasKey(0, $elements); + /** @var Text $element0 */ + $element0 = $elements[0]; + self::assertInstanceOf(Text::class, $element0); + self::assertEquals('Welcome to PhpWord', $element0->getText()); } public function testLoadHalfPointFont(): void @@ -76,6 +84,54 @@ public function testLoadHalfPointFont(): void } } + public function testLoadChinese(): void + { + $filename = __DIR__ . '/../_files/documents/docChinese.doc'; + $phpWord = IOFactory::load($filename, 'MsDoc'); + self::assertInstanceOf(PhpWord::class, $phpWord); + + $sections = $phpWord->getSections(); + self::assertCount(1, $sections); + $elements = $sections[0]->getElements(); + self::assertArrayHasKey(0, $elements); + /** @var Text $element0 */ + $element0 = $elements[0]; + self::assertInstanceOf(Text::class, $element0); + self::assertEquals('OKKI AI 客户案例', $element0->getText()); + } + + public function testLoadCzech(): void + { + $filename = __DIR__ . '/../_files/documents/docCzech.doc'; + $phpWord = IOFactory::load($filename, 'MsDoc'); + self::assertInstanceOf(PhpWord::class, $phpWord); + + $sections = $phpWord->getSections(); + self::assertCount(1, $sections); + $elements = $sections[0]->getElements(); + self::assertArrayHasKey(0, $elements); + /** @var Text $element0 */ + $element0 = $elements[0]; + self::assertInstanceOf(Text::class, $element0); + self::assertEquals('Příliš žluťoučký kůň pěl ďábelské ódy', $element0->getText()); + } + + public function testLoadSlovak(): void + { + $filename = __DIR__ . '/../_files/documents/docSlovak.doc'; + $phpWord = IOFactory::load($filename, 'MsDoc'); + self::assertInstanceOf(PhpWord::class, $phpWord); + + $sections = $phpWord->getSections(); + self::assertCount(1, $sections); + $elements = $sections[0]->getElements(); + self::assertArrayHasKey(0, $elements); + /** @var Text $element0 */ + $element0 = $elements[0]; + self::assertInstanceOf(Text::class, $element0); + self::assertEquals('Pondelok', $element0->getText()); + } + /** * Test exception on not existing file. */ diff --git a/tests/PhpWordTests/_files/documents/docChinese.doc b/tests/PhpWordTests/_files/documents/docChinese.doc new file mode 100644 index 0000000000000000000000000000000000000000..db245953e5f095115683548e7bf4f68c1a71c49e GIT binary patch literal 2479104 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|X6$Hi4x5jWf<(R^44 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�=v_!sS<#Gw(curs(`2sEV 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%0AF)l!{aSA2{b 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µ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

4;o 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 zro�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

L9FKT27Nzt^1(8G+$dad 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

mle~cVSId$RWE2O_M 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

BrpZ2YwDm2nFUMo3 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

?4keKgG+&Z1ds~d+zO_Fp*r& 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

gW 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%0A*1YtRhW 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 tMU9`-cEP0HC&LvI{WE_E%(t|20V z=tJ^vIn1xMocA0`eW$Zjm83OY&?Nr_h-w)y$=!sY`}`@Ei_+b}0sC-hdgFVI9CZLvkB$^! zn-h^gd~}BD@~!ertocQcsC&YiN+zl0t@w4KRN+}IwY?DL(V?+iN+u#Z0l$o4m~aLb zzvpj^%mfg+0emc6NIUtT41(=;{y{aUQW1K{gb|*5^D?2zWF52#%Ay$&SbU>L7g=0+ zo6uphvSDT%0U^nK9`m2Rz^ba_Qsj_GanL3rez+5;=IOXLbeVu*ve?F=Ls=tGWrb@w z4zzJh{)iUWavlN?Aofmte`D!nHD_&@qvj+ zCw-6{0j2O0UdFwyZpy{Cn0&Lf>2<#>zW%@#y(W#60lSSEOu8tUs$GyY2>v0?T~)+7 zl@C%l;|O*e1JY40GL(>Ug4Fvs=obwJ{>d5Q|G6jf6Yx6|dl9AeCN31gIMm|;#pM4N zYi}7B*V}jZ1`QHigF6H#xVr==*x(l2o#5^g65QQwaCZsr?hxFapxylMyXW+@Jx`xc z+c&(N*)z=E*LAJ6zUxOwhokDMtdUZR94r&_r!>Fjmrkwa4UP5HyR)Gn_@MC(bV0c&se)y2Y@4&mzn;968Hn)>EeKt{J(Sx|HGDwI0CqhpE6>^dypUO z+OMZ%MwhlI>Fz$|<*o<7aI`GMt0$=GlV+5KcGipw$Rz5xBx_()Bdi7NW%~GO&><&F z+sBfSW(3lcl4d{)qcWoZ=NQ8OM2$vVto>nSNe(UbP3DY80g7#INxi63(fH}IM2LLq zNw$%p@;cX;NXXK|U)mJ=Gwn&tMw=0DCi~<9=Q-Sa@2_|7yXxu*<;S9)>$RP#1?%}9 z+*VAT^hkn+ogYxGBR*MXe`YX4-6~!H)~%+G1~yzCw`CfdE10e0Z*d9_g^`heuZ^sx zRqYNtBhvI&rx+d$V+5YPube|~BAD0HEA;XAQ40d<+lsUUd`>!ZOg@~%{LVVzHK_592ML)GBGQj_GpN5a+8CQcEyeaqn+@`#>(rg~7!J&(KjCGPh1^-vu7HBZ*Cq&WiXGD-czE z0tN?#@D`QNnX0pXR2>_ObXVhVa4f~Rc;Q4@4JtohXyR$GWUZ9$DyPS-&&V`EEzfiS znV~YGL${o+L2L&?c4D{{+}V<6)M!5TVC`>g+7wMzcB&x`ZQ`d9+=7X=TJ5oCxoe>o zXhLq9VZ);~EOmt|TDWj7)RSW-Lub(mx#5{d-%7bL@Mr)FLxhMvMB7Q`@ukV$n3BGQ z#J9?rb5Nv#{B$}3k}luUC%T_83kF;;`p)FE0dADv_PrDVychO%J1c_igRb$RT~(Wf*H z^K9k2eNgc-@*h?MAkheq)pZZ?eBpd53gZFAUW=x>hrp&(1;?huYOP%tYq1Eaa=K9F zE1tK?O)1SA#i;IZ%?r}Th1JynL5D-dxE{7!!_{FZ($(N`}8XU4T^JvcBJay+k z*P3yvCknbFJ?HwuB3MH-C#2Ue^gpJ&rJ1fq{O|m1DBEdZKkhi(tlO%IWPy!X-j-O* zT(2c`dj=X5ww4KwW7OQvl5sG8@&JFT!-W9ISB}5Jc)aqSv17n0D;}N@z(UohlH)i@-pOJ{YI<(^02UGVkAz-IDH-jX-o8ei6HwC zDT$krXNFo0GMdMok(lkvx=FyME_VBw>%Qmjn$(EeEBKt7brSbS!2>=6lBB+`D)Sh; z*L2L%kUceqIcZ{@A(pu*y-;A8a0~Rc5NG`K-kAHY`SYCQg`?RikSuh(zV7=_6OnJR z%wJ+9m7_eAD(-$Pt5?se*TJ?7dz z%_|sq>RjoOt_eGw$fWN7w?w^78lFz<(&uITwYb9X>U6Dbxy2*}s}WV|$nMF6+=*JC zWL`%eG#t&)T&Hm8>6L~ea%YG=&U*pwNDuk}Q z!W=sH*Zn6{m#{v4{XV!wi03FZJG-coG$!36mfEslP1I;<4QUg&R31~B%P`B2ix-7( z$f&H?Sc8NyC6KTSS9V{?X}h6rqhR>fLiPgCaQmKwnB_m7`1)8wke9{1HqfkHYQO8O zrsK#Lr+pbz@cvxmdbXBK{CYpY`uaEXmD_PUiW8PBqdLFvl7P=mk@C-CgKZ|ay99%R ztgPE!l|HYQQS22vC+9fdc_$R>na}IvY{x=O;1y&8ANF0!=8>M&6d6#tiudcqFNWoD z`abb2IcR#faocm{&&UX|y?bcl>(0{%a9?l}Z|&5iow24>G1>9U|9)ihTs^=2Dix#R zX|lU<+Zfuop!@CGK#W5-nN3jq)4j31@_OT%&1)YA=a4O%e>HwN7hV&tQf$xs`BxfS zHgpF#Fg4rgY>c<%3 zW}2GldF2+!jlLf^EEbVAm$_xG`aJ>unC90Z{y@q_d7Y{??P2*KKMNrFXprcZkTfCp z@I*e-H%=`QX>95j)KEmvBf6+*L@JF+{rKKB2%+`9k4cRYEF&rT{^t4`Rm(YUeD6Rx z^8wTA@33CM+y8OsIcV6zPd}#%>Q!@LDEDe_Jhcwy1L7?2U*cP~12JhMNNwe18n6eY z(k!0O^QPX;w&;!P4h1d_GBFL=HP14cvypyUKZq~IBc<4V0JW0x$HwQwUdGbF0$;eK zDrHoNI7B~~^NWG7PB*=xNs`HOj({g>Ei-c1-Be#l+H4|*u4h??4prJ}Wae;&h)jRy zzzDi`zWMZqcgHp3wDt(E7ZX*n!Iq0{I}EnjA;jKE!0lW)p|$>?hDShE8(soAA zwVWR&n$Bp#&p&~%uxdhKkc;-UE)F+wz0thSOLnr#^4?o-SsU$CLB zs9Y){5YQebV;0UnYr8BO55e>iAODUeuXWs$ultaQDb(BkxO!G%j5A;DvElcA|48q( z*}-;`3W%~5`@HVjzDP7xm^nZ9={3~jBvzMQ>QTnf>*B?c)k87eN3K(`%;lmb7i8%W!r!(~)Vih~OvpfkYAr zchHXHTY>_fj12qU8~ZJM)sf43`i<{#s`>Y|S z6uNh4a6~PIbL`L0i5DKx)@iOEOQg;iD#nnoH+dIJQr91vzIB&J+kY~fjZzjgoG|c) ztr2fBc`OAoz?yn&0+)^0)xF-HcHeb|PvfE=VK3|$T1wh|3MQ42ydxO678T@v(G$TP zWtj0d`*E&fIuw%f{6eZV;W+&!X4SJQHNoFM;ITE{t_J^qz_6FWy8@tZ;A2BQl9NCYlU3}7QXy+bSkg(*w z9iH*cgTu@s4s2ZnwH)XYj;=rv#bcSTU3JG)M?^WBSeC8sVmo+bpP9=(Yb&PNL&Kk}DsBgbqo@8}>$H(+O{ zUN!o{<@Ih+$HuflYxH;U=a~z~hJSPbLb2Re12x)6 z_71V@n1+;iG8zl$psIZh6>^%urfpH%O4%c1V-dh~BqdAGNv8RB!FSI*`N|`IZ5K2m zY>$O=bGLBPv`br)E!A5Mlq-Q;0HvOcjtmfTd;#mg-U#M@($yIeZJPN#;nZh?V%6h} z*~|DobANgLZv}8zfhT!Va!XQQ;qaBOW+BIrzkM`VW!OJILRxl!vI;@vulSUhhZ6D7dPj>$Ap%#9zJ`NYG2`P=+q@oK!ZlN>jb9#DWXe;KiX z3t70lSphta)m<1M4cJ<9*U%td_SNeqNZ7f_a0T6kk=8PiaItqY=r|z3@T++eDl=0c zaCdV_tiz-1TBkGfR5y~(PGE31Gcy)Ue<#`E_qemBl7L|B$*M|`r+MX9@tBOTp%&m% zsKxD|q0(9>>vwvKwO*5kZ?0;N@F^K&n=b_XI8=ka-ndJdL$lyYK|ivIHt$?m60=%x z0_oqj=aBB#iHGQCkH!ghQid4g;Dboau(py7xROMW$^lX;9pBvOh-7k?Oxy*{w}RRp zka~>=P$2dDLoP#j^xq$seiJ1ZrrJ~Dd+mC1}dAZ0Vl0SUM68=aC9$fz*7`FmgpO9HO&7$GAviw5JfzX%j3 z2d)nEjZ#z`iflfdD?r`zIhygX8-JWzAr|0(qn7}EN%~IL0gonSC+~TlL_5(T zar*8yq&NGU?8k^IGJ~Cb1p019FbG31)l8Nf&cLlibZw5K|5g5+_46IXB<~N_F8&Cn zWlwt+NkzWf`LN<`yd zwq6y1Q4(Qn^b~K0Oqv3JZ&yDX3=X1H0Ps)Pg+J46zU|Wj{WAgjeA^+AmO2|iw^^39$OW0`!FC57epE5ON zFwmAUJ`i2>C_Z^HdIGOmy)F3(Ihg9M^E!}pewuu=+K6tf;ZSito>3YP&a#DE+I+z= znnF_E#9&ZCttNt7y2s9Obnc?veaP1D@fZ;WkE@yUeapheqSIF+a~qD9sia7n3!=E; z(TXcDV+u$tHWU%~8sgH;(g8T0iB8{=H}vPOkyOp`f@bxN%X5+?8S0qVr=1e3BdfLw z+a43R(q$G-cvS&j(*WgaW6L5xZHQgRnwhry7lV@e1nicwmp}Yw6!t?t^pZve5#j05 zEE-bV`WGuvHq@V@&`R-&Evvuqt5?c?6w)*r4y^4T!v={Ig-}DK4R=qj>wb`LVtw&%YLJ=rN~A`O03A+0mc;KJAn5u5#n=B=1>MYF&nmN= zHfo;zk0nK~c^dG{^3STv`xE9h2}w-I1k2;E3LDp?OKPg(s$YsvP~}p~ln~NVWB6vU zY3V9V&sMdUPY1jJ;z5o^A#db)CezMp$}vTtwLH+Yk@-#hAG^P>v8XJa90qs8#M)2%6vpt{Wu`_TiGr{BsD`a@&yFaTxW6!z zisURz=k=L!PBOO357XA9SI#-p7Z7kPUeYg1wY3UV7y2#T8R;R;UYfKWQy({A0MW5f3`+OA*nQQl;FzkgD-TG&+WLUtH)B&rQo6bm zbet1ACK5Pqj8S1!{Vt9&DMUO8U=*!Nzve)o*&co@h^~_tu$-(zvJgI8l#owEXt$HGVjM7i;8KtJs0g8k+fn)9o9R!O&7koHIsv-@0r*@kbpVI~wal zDha^@It1Wj(3^Zu`Fw;H8IQ@8n3{G4h(*^{)Eu-!P2%bd z{msS%qCz*E$VykIB)mC=36MXcx-9=<*K}_G#)I^sbp^4lM(H{OD9f3i_5G zK%_AbozrObnpgpR%!i=mGAHfyQE)=I)&_~eIHKrn4GyoGAmOSvpb+X^4eB$$4bnOM zf;~Qe?$W?GfzZ5+Ze1p59WSr!{gY;(JHoNI84QX>v%+aS0T@M@dWp@P@%RZ}LYOFiKSso1Due;}t|H_R6UFs+cc!TK9qk zrn0FzC-%C~R{iBx27_9WoMjo)XKyI+&e0EH9@Rg(tSbv#u0$aqrW5eJzagyht}9z` zrUr!o`vm(uEth^gHez>A1h3y!NgN7_^YQ}-hQn6#8Soa;k68*aQ|D;YT=e~~2TJii=SDX1V6+MXlVA2z;RC+bC|F$C0MiFM8}t zlqe)cOES~zhuk@3FIe1Hr`ml29UhNZRq{3I+_A(h#7HA;1 zKb?phhwe2qVbGu`-I^iz0nuwaXTIy@ysg)IT1ocF(k9p28`kf$+u#{0VLNA;l{Zw#rv zs&}BV_zH*9W2f_NLu$5T+e~9Ou>|KrFdQ=tV*i$Azq#2!)kpO*7{$KjtFi3yMB{&( z+AN*bJU?ZqUi&XCqonZl#Fy7FZn=x*T$&mIPwhBKuSF^E|GE#BLT7Ba9)!)YGmUhgYF=fT40 zt@!UfyykJ%kovdKOFZD^m4}QaVP*c?x-0XQL>{x!X>u?z7P%ZN1$;!NCdf8t+jRY?jhugaxO0pV)0VkmjcbOzi3GeU^_XtIFPxmdj*VU3R6vqXsjrzf6FGdfl>h4tFU_HG|4_)1JMWoeS!} z7|ATy!M)-XDw@3y-s-U~8jU}5--}`%`??G~BPzDy^YW6~t(t2QH6}#G4LHo|i$I%r zjjlkv3J7oLirSP#5ghMzwH|Xk+*rFwn=7e4eYm>S12Yqo-we&cV?9M0EiA9xbjedr7YVje&%qgR}KV zl{A4Ma~;0rlpT}Hpokew!H%QOZHxSUE@=-=RhIDpzKSfLm~-&L^8Q%1X$t8Zd8U7e z`HD{bu|R2@@`LwpgkHx0kXw29sY-zNZ?a|g!=@V5rkOeAlY|uP2_d|^TZ(KaFJ zcrO@={=SYiLSk!e`7Pkc(QHf8gdq$C-BrecVTaQ{6aP_3$=Q%)RTIdOF5v}we5^nT z=;Htd8AX8e^a(`*a||}D(+RniSsrv0emotC{LvX^92X>caGS5bDwl#YGtBG}4+Y*w zS5dDa*$j16ERL5~dq#}Q?@M($W?6&CdW}U1LvdHPrcku%p1hq=x%4c=#~c0AG&JEE zZSa5t+q@8E3zcG(WoJ3kM$qN!i|ver|_lR1PA@Z+IV7 z5DOU^%Fm3@atRhcRbbH)Yw1;nSJqs`h#Mlx1{pRm)`6Eqoa2Q#6Q=c6cpN^*+J7sA{#`<~orop9c6 zSONBp{a3T(qtG|Q+;hW5HCZ^PP%$ft?RQjG$|Md?1bC|;o7*$fde6x2$tFj~k>pz+iD9C_S8;ulU=ugN-ijQ3u$KR4CJjRlOcVLOG0%;buR(D7 z6THx5642;hP?^PN!ow-WkHc#ukfPb+zsbR7YA9}$i*t34e>&IZ_tUP(7(V9#RmELK z9y_+$y&-iea3g8FlGoSMCgt70p+WOSR@fK!R%RI<(gow5a3Mvipm6cM9mM_s(QuF$ zbx2WeiJF$JIYUaAasB3I?u^x84m^HN#`t;@&;~({ovbW??})OQ?}F|eJfu8*C_oI2 zjFix$;7I`Gd}1hubSZ?{Xfy{e_{ob+S>GYmU(&-PD3|p+rf5@YQy3l#0ht zGD+%cTjSMxUzy*hhrJmDQGMxJT?w=8@P|t(fov2B+7cX%ar)|jo0x)fNNp=?&lz@pV z!1{hdwA4%w`+mEF-l8g`s7f@Gc+upcLE|hWH!`zxJ3h_$rwS?KBh(>6d}oPJhWB^p zETsXm?MnrU5iLJ+DpMpuW#h1nG3v$%HxutBCx7;q#w2C1%u5hlL0)p)xqq?OJ-f4< z?ak3)S}srl2jvLEHF!V~cG)-|PPg72-X$onuqyAQfjFrw(U{R>os`i57H1J#S_}7+g{DHlXI>Hgg44aM;d0)PS6ZQJ7mbpce~bX z&CTjQ*RlQ3gyNt~l$)@6RaW`W5Z#%}ibst&p}FnUjoVAAy&TwL;mzr{>9bebLV;zV z5MH`RM_K4Xt7|{~{-)z(;1Kgx;Ub-uj?Ws4lN7bummW(vOm_#nr*>y5(!g3$TK-aY zxb5}Aa!P+7|FL^MG}Z6L@CS$T%T0 zMbMWrc_qle`-^oHKZXk{gB?rA{!dp7eve_j6l-C|zXSj@XTW)jD8>Y|!&L$?&gUlj zrf06U>tOX%cE>SZ&4ciT8yXp1>lg-E7NDR1qrUCnEqvtJPmI$w2ZJ|$bR}G;kqKS1 zpu4RW%#dBFM0x=qo_=C~s*Q8XcnCV|&ne*JvBie9Y2-@i_0ULss5$`ao#ANI}jliaWD;svNuE7*kzbj($BurYhm|8 zh?l!kvBY*>g>ecE7kWch!R{$McXOF2^mYKsm0`*j;NhIz2RUJbj{%kxz1L<;%g8yu z)MnCru`1SGqmjeiE5X0u^TX$poH2d!u2^JtTbjU1gsZS_NVam&+MmvHORijNVTawj zYm@N#{p3lO69UBaA!Qk(qNgC|d5_wHjr*;hJ={OGlmjfl@fKr~7YaiYg94LE_wFB7?aQWZr$N)h{lBguM}L45 z-EM}oozb4!vEo3&#K6EnC8uZ`o_p0YPqQyqier-zjH)+WQgPyRFIyzDChjEl;LPHQ zT5QWg_4K2c|4k@P#A29^F>|J&`V2~5)ds+@r(W^!I$;Pu6S#+n7F8Y3*2#63i!s&~ z9CnS?2be)O=A{WXREF0B`036It%2C8wycZ|>N4HBvnv{eNTTFTZNrUcw!7Ho*0!2o z7HzIajn5Sm2hg^bO&JVR;bMKUiv@ql?P zkJe=m*T>aXyp`8O1YIVx-2xp9d?<1UUxdbB`IjKjWVJWJg56SI0?sZ1_}tl^1cJL_ zEO=+J4T2=Z>u2l>P2$AE_hX1-qQ|3_v1Pb~{P5fx8k6REcuA90IB$;^hY(lHh2M>< zw|19d7T|JXi~Jy}Ha{)F>n1e2=rQl1{ys|~p2gF=7c4T%AwN$Ak`GggaGsSpX*RG3 zZ?RQAD|?8#{5xBx7UO<1qMYq9A%c7Ot+K>@iyZ4c@3muc%#Ileke8lKTA+oF&q!K8M3PFLe7D(YQI{UN15F_&Ga6Z-F8Qy~~z zdreW_Q;LR^qNe2#2TLCegvlFg2e_FK<*$lK4+S^wNX!m}U1`^)XDXNi=hB9qy1E;U z0)6f(49eKC+QYB*O>KtKAcp08E6|&cKWknNsiU{;i`V|S9Ht{HuFjIxuK%m=CfRm( z0ju0y)oCcy#soXpV=UH&`CuJ<82ap;-JZ|p)i`}U9!VEtPpJ??D`U2RmEI%2ilg=I zl>bHfznrK2estWTGDsP;1+;E8`eca6(V-o|3A$0#2d0piaC{ zXR>SyY%6`d@7BO&4M(2T=wm1Ed#ie(aXRfcg$O|Edo_QV)*Qz_~!M%jOdi|WSF->t8-lBQMVQ+zk=_0UG52FRwAvC6H zmO-C$nDZHoR&*A=B|bxrO&Q*I%rF(tgz?!gwa7Ndj7w6{?0AU?YtxWq@=Cvcf?OO! zKrT4&<0%mRhMz6pZALv!$hZ^NkH#1mmN!rgPc|HXpww`=AkDz6r$4Qc`lR>NriTk$ zqknlrcSng{;we7Peu`f(Y{PhBbxHV9bM|gVQ4I$=Jr%w=NN)f|%+E%?on3XJI>Hxw z4pI#@5&uf^gFG_&A~z)?Y!Dfi$GGnHnn$*GFd{sFG(=W;)O#f1xim+?Hru9IQwAP| z4S8YJ4}1T(H%s5|AIz%McD531JRRNtIZ4E7AJu;nu~!(FV6f94tz=zvK@Jy@&FK^9 zV)|bC*ePwyiX3a(c0#zv6Q#axq3y1Z?dRJ-5ArcMpfsc;Iyn+H*F+^E2jdR}v2}}S zdA={U^2mJ<%2Mf-h>-LnizS_ctpd1KU!#Q2YEh}`C>$NN0Z|e%i8AVz*K3>4a=4PU z)U=dIKB+sBnJyAP4i@DqoC4`R{iBg`;^ zoM;&_@}ocM6#X-tCQljsABWci#osk2WF3W`8h*8y7-5@mHewv7jza;ytmC5So`OQ} zt^3&=3E6%9N?oT|q1Wc?IJU3)2ZyjZgra>>E^r}n(lEw!n0|}I^G6sB46w7D%%qv~ zwm&cu?@ng*Gbg#M6%_8W7 zKJTT05))#iT_{BAH&^2);Yq6HH~#~376bh*YPle==C?0A&2R#r^A-V|K=}9MJsKfX zy!eT6;I0Kon2&~nYs?bI=#rl{jAAhA@=k>P4RN9&(;_oDPk6Llcu6sP84PF=L(n9k z&pt@l&ME!)MApBsCiSOr4N<% zcuPuzf}QI~{2ACT1dygdicyP%+cg%b!noTq5P>LYUgiooi9HN0Xr%3H+M04k?}Lj; zT`ma(4I>bmqO;%+B}ue9a4>aq;D>6o@0Luv;W1EQfTkp9oI69nRG>#-P7K_7o2p_? zzcGfTzlfJmVSuN))s*INq=6avBbwV0v;efv;&Xf*rr4#a$41j$a?6%N{u+*%MleA9 zqq1SXehcqQ6rNo^HxoSzJ5sT|`TX8J@)k%Q-}O?5XyPke#6&~RO%t}V8#Ry%py%@J zI`144d(ifQXM^S%hY=avUc^O3Coxq|(k%w?*3T8VUka@Mp%d z`iy%%T`tOoWAEW2Ec&A{wLSDe5Sk0?wr>$T&~U7^4(B?nt;Oz}wBUkzJ&`s<8~JGT zK;zu;>j@>o&6P_a%RQt0u^so#H4oKKPp3mC;y_Nz3C6pVEh0%u;+SxTD3lKhM89Hb zw4t2q>4uc~?R{NT%KOulTmQR(Yn^M4N@oxfYDVxxo_@NK1IgqRILE9ndA?`9!I0>a z7L&CnmaX8@VE23;{cQ2}D$50gWl?>3YCm=?9UWjYe<*QgEgzQbbuP;R9FzcgBI_)) z`sb_e9H-2is-h*puKXUnW(eq~+ibJTRTY%FWGPT*vP!F7*M@Rf`EQT~c zlTcepfmuJhx9)?;yVd9>PzYV&Luq;TWX|IvJBIa~*WVnk#hlJ~HRJvpbe`SAtAsTl zl*R!I&e?0$z$EUQs1gEt&{};S@(8^~$uY=cKIhWAOg;>|a%ZL8-P@3QP$hwQ=-FzDUO0F=%RwP7bv?R&Gt0dwYDaZ@Wpfnn5hFQYLxBwseWxW!SCdu_sSn02Y!Y+8krd_ z?oH7Bwg%nsnpUwc8fb`RxME(_$>txR$~BiMfSOY@1`gd7#4>ras35Z1k)97=iwR?0 zz>(aT$4~GsU-1Dk6wQOh%b@k7U{~%9lbQ|9-upq=%UAI$!txRq5PpH@7*%Dt0J{-( zE)U5vBUL>NPIkZO6?2hi)x&ilpWJWdttXW3Ezv^&K%RN)ZaW0HzyBk%TX@jOh^gbr z;mum#8_z7HtE9Is+Yq66L#YDpg!=nU;)WSpM(7!AsvR;#c;e5Aq-K77CRI`ZoOUIJ z|HC)`@20i=-$AE-dsSyv?j^1ow<-uC60exbYOG>1&I85133y=4}H; z9n#bvFrx)%T|6odOP&|R<#VawxSj+>ycq@VDTYCLG_HqE8Qqz# zxFAb$AK+ab%E&kYn(5?mmCwq!+L>pI2&z;%J7{>E_Y1iPUXI$rH^jXe8}n+_{BoW2 zjzkVd)>Nb(-eAuzK7Q#Q$))1Cw%4~Bx3LbJvqPmrw(e4x#xR~}AXxBL3%ZMa)Sogd zM#L|+3~Vf^DSxicV6Kf}kFWYzGB8;({10qZ8dI&7rU!xACaJ1PC~EKf9kWAw23|{U zivsz7)$!Jl^$EhhTuqJ}JaN795!7MlgFjqwo5&p0G0zG@CWVx5z&hIMuQ@xLeZH;`s-#ieZa( zJ1sx@neqqWr>U@rR8M)~rnPdM;8(dOWA>RwnshOO|!TM8|4gh`=U&@|66S!%Q(pRI<$J&smFs0yv+Efh1SRx;HRM1OW-Lxs(gZY zy&^+5<#th$gZl~uz8&o@ z@^D)lsGbaiRk!A*v%l)y$wbs|xhPLB@y*)kBkoFNq_?4(f%6E4kr83b@SJT5D`*>H z-KkSQ#Yp)54-}Q2j%a+b-`qLt`HB@B-|bZ!Tg#5o|CgoOWTZ_{y3TJ|FAEeh8ZZQC z*diK<#c-unG6KXQQ4NVIGZ3!fKNBuLmIn8}sG%OJeH4#m)>%7_v2Fqv*;b~}0diO|A+OSlMv?ge( zIVE`Co{kQpr>Z=`<35Z<9KUl7`X93)BxtzVzt7!ly=A_{0O@hyHDG;^dPF)|qhGxI zk+SA1q=vaO_SAo!2}%XImqFFMQyKR1m$W8ZH2h=$gJ@F#+LLOKcVdE>P?gr!9P8z4AI4=mbI zlw?*!R3O=OD2kZ~IS?&50NYP!dzE(V`XKVxD}>BkH&=axVR?BWY9%#I{waFQ)j#pE z>O55pCFHVbrf=^n_YL=n{ktO+-Y$A3?0w?h=eCK;vi%N3o{s~rNp<_}rh~;88mTbIdyyhQEC%g<}He~+Xu^ufpAqf^JV;?SEU zh0BKu9R(0=bqUV_YS_#PgEuBjQKW`Nf#LGrwd~yKhO3@f32t z+NPh4wrUUO%-t!7sV95!cF3`DTU@%FH#wy8#(@y z87oQbGK)N*=7&s>hxdN9j0%;Y=a8CH+FlHE+PlaoC}Mqb!A?2)#{h8kQHt~K>EhWL zU%28h`n?;KlGBY)^PKv8$yZn=Q&-QR$k|GcX|MpCU%Yn(n8bFhd!={*85DpX426YF zP`c+Y_>|}U1$O!PJi8HNiw%io@bYXoGFO_c>!7wm^=naM`HV5Qj3e&PYha^9uf|I`axS>V$)e04-YYD3d63bC=3Q&o{VHB@l`=PB>_MD;c zbj7A5usdhzp`j1=I{MvvD=Y}A_ScR>akOV#1^bsHhY>DX?`S!G`%I4S5%yrO_f#6< zaFH%h^wxsHKMF&{e!>NyDJ@vPBW~uwgxO{tV4k%bH9DlSyW5^b`Yh^>yQWza(nuJ* zZ<;IgjhQa$q~Tb(uMqaFnCAu=ui$M$J)_InRf%Ua8;vdXWYp};WcbQ$%jFsQxk>7o z(LA6d?Bb7JP3`?wzcAEc4wu=`W%|*_?N0_q9+P{L^qqkAUX1({1=907d1gBuLELBo zZ$gX+yviYYBG3Kpd&$A39KnM72Oi>R-4`3GWP+a5^lVu~DAU}o6nrZ6Y{hCv$jUOt zA$LLzVwt(QVNu~Kox+miM^?bH-db3-ohyrYFg+hCRG;Thye@~p9owN zbRJtc>x70Da#&dyRC|Hyw?}G^QB2ptcUm{%LmABG(7iUppA_9M{yb^|rW&pgmd`#q6g{3IB#%Ymt?y60p0`1-3@Xyu^U zi~QWJMnWKja;9BXD_!K0%v!s{)0kOQoX7Yz^aMv)myN7n^S8i19oUI;UM8EL3k^et zX8f~jO-I=XmkPPB0=t`%guinnNUHsz~}2%OIAOF?Q+EXRu;h2eDo&&w(7~*Zq9k|!?2h*eC|W54(oS==^|A5b*PmHl?oBe%;>Z(WXj3M z6HG`G(6Gs_lSMhvaGY4c6~*&DV}G3c5LdtO#X1QEK;OcwXpSY$aIxr7+ysas1ilZ! z*9Y!*DOM_I%`%64NixG*M!YjtAXicDHVqCtPaPF-JTI#|B? zRPnkcVtCpcts{Fw_f0J#d!L8*Y3Wi1&&+xoM~hvtF@D@n{uh-9gZIfDDS^vES;)pF zOcAgF9YhBpPUm|<2M^94L%glX!`aAVG)7!b3kRYzKCgHdO5Z2Hb5aHV>SEx{7zL#}GL;yy z^9YX1?dL~`Q?e__&qXtYoyAw7Z&w}_Hi*FBr6SWt zfTIs~>09-=f1o;R2F6~fW^hH;qJT$BC z&O!7dhoeSOC>gC4PXws@2^&?+wzWR|(kR5ryi_>~WjzZD>K;QH9>~j3tGx3TQv2|5 z=MSl0#@Zj%Y?MI<14e0v!I4&+o;l8z)53o(3Tc|KEHcktab7C-D{od)79O@ zuHL(L?fPupr7_b(sKY<}Z)4H3&@2SX59w;MC%1Y7{YdYDAEchcBtL+#VrPGSm973| zRaDGfwat&BvMXBoLMrQ!AYFEHS1B3nrlrTht1M)HcLbB^qx-vwJ9a!v z$71xvZzP?QLwqe2L!6in4$5d$jfdw12`c#BMx0YV$HZA~OJe6MsZTfV&Gt5yC#gPb zz1Mlj*OC66rVxf;|c1|yH?%nQnRA~=c%L#wg5SO zcc$++s!1t7DH8R z(F4{0(r*PBlb(?K|H;(|hXe45{It#%-r=+$2&KIt%Lh2h<(_TTotK}}iGXN$pi;>? zK?vqmQi=7g|FHFqPHKI-BP&w0$C?jJKX>W*NoG!lZLiC$uvydq$E1IPMF*Vt>!>u& zg$tRAqijbizrNpO!VJm^D|2D8y)>Xz{W_AwzIA`c7|0fT-Dy1_=wauo1<{D4j1V zrc?n#W;h>k==6`Rfo?3cYSlqeH4wUgEX{o!+oW>B_?0i8V>(#}bfM+MSM}X^Sh^hG z1avtm70BECN|3JRo;_k0;Z7zw*m8(T5T)Xtl&N&8sYTHN6K-f~wR<|4Q@J72Al!h_ z4w>|g$K)UsW&u}^vY0~?=v)n#4kpMc@&7tx|L=^2|BF8-SwcLYm&3Fyjy+Ls|4)7c zFAHlkNG#HSyh9OmLBl)H4$Cp3m^m>%ugwA^nLPX9r~XeIAi61C=drGOpucHuz+>a_ zX@(WRayhEV&a~AWcD`{om&-PY7-sk`2&*fhdtefHbMjIH8qnrXTbdt;<`AL-95Mf; zH2*IP|KD%_$F)dIz}!i^z$13|5l1bHp5^TQJ-fioQ2exRa$3**A(n4W6zuj(QeJl1 zhU1QcnVH$W(bq%rTBX+@p60^U`^?p%w{5kiJrp?L1VKUu_zFRfr#dtbWzbk{K=2n$&BWOiuB!_(RiY=$Vli@F``%M zEwAHkVIbgxf6C*TpHotd23Jj7YClzxEPYc91ttQ;PpW0llo($cS~xP|1M@tjdxb?Ee5rt_c@yJ zb+Y%}+^(|rtM}yd?Q0re1!qe4Z_mqg?PBvvO~HB1TkrR!N-pSytB>u@)3=>3LV<_h zJV|=UNAYY%-bme_4_X;bQ7umu15$TA3OeW4jreKuZ~|A z8tiOrgNzrhmRIji4@*n3#&nTChY*phJ)a|V!@ly^e-&=U@dr7vJojM{mJ+>#oD%!( zhIPC3>K@&PB4y&oY|U(JyC2JR``a;f+mDJE3d(pG{%XXa$_+!yD`GPG5P3aX!FPu5 zGkrddUrcMQT^QZDcYYmG_-r@)^0sXb9ZFw3yLig%;##1(++%G6(}k$(K_n8C_IYw& zbo@Nx^}fr}T0DpsQcN@SrU9;}-|?j}RW=a%-AlPW{?%zLc~2&Hx0?M-7ksQ&e5fT> zCy$q(=c+X%G?VyM`pb`NzJgDOzeiKaMit zd7bOTKDKpkgRp~cd5Qn7M5y#aOHBUb;KP;7FLV1wH)##STJdS;<E(-7j&{R6N2>qAci7Z+Fk?Fd!A^h*wi;rzPXO31D^F z&<%X4`;kNaNwbjYtIF(#hOp$o=tYB9xmvp4yD^m@?Qm(*Kc$Dq!r&P0o zab9up>hluQdtA=YrUjKj?@{;ldGzY~Yhct3Kl$ ztr7DNm5`V2htHZtT9rTKo+-$a>jToZoX3M-=4E&@CTeY~osi6=&@YBgqPmnP8*Lxi z>s5{qt(Hf8m0N@91iVRy^24dL%Y{n{$MDIQ!`hgTvnAynclblSi}w2)P_E@)RO*-P z(JcD5)xGYJ^GJ&I(mT@kp`6~)6YBWoF067#JD!wOy(RQ@s-AoBOd4N+E1$25&*p5t zC-R4fhlY*KqJ>`I_*y_y;x~Cr&HFht^ZEiDV``PZewCPwer5>1j1#W6UO9rDni0LB z={8q}-StWzVuidwfq@k?)@)a;=?3rm-P+nLHT5(&)$d99INT3IJ(zUKtW>=G$_0Ad zHEUkG$VSxnLn4T8Ye41~QW}cYD4gv3(0s{|Qk+k_xw1`L#A~n4Iw7|AYg}hL_C43z zDLgx~0dB+l2Px(BD9b+@3hFcS^Q`t&KxD9Y=WW}6?)AY@3wQ<3dNNf=`HeR4=g?&o zT}{4L*M7=<&XsT0_I)X?jrE!=lF+*tE|Gtq4At|Vf!LM5e>jgU@(~dQF^LCCQ0oJ4 z=8m+^_;y(A;hQ?v2; z75K`pbcRHsY zUA)SndGsaphSpq~ZnK2$`;W+6z$+CH;mSXGHBjEK;sMk+X*Jn~NX#f4?4hUM4cioY%J-79z_R}Unv!2(j1V@ zJXH4n4GpmUIL!kjyR;uxmW|lAe$=nIny61Xu|yC8Fy_w8Dk?j?x8JT{f|T)39&dt) z-utR00;6^G^vXI4^{KyZh;|ByK2D_WQ(LPQo5+>ap2c56*i^y+2D1;P|932EmG7^g7HKN8r zhRSdt;vnY#L;(rre;xiK#O5w0LIXnt{ZEnq!wC`y#Px4rd;!0d5RgF- z`0GO8Uw@DQkUbC(&?+-v06K>U0s;;S2@V3>WeNto3fWH$426KXK!NlELu8OIU;eg3AD3%&tsqHD18qS(s$KM*91(vH4{XjMa z0r}LFav=s`0Y3Nt^a(T&(iAkg~=!0;Xh#DVY{4j6|ZK;#bdMIYVSuI@U061y{&6y_TjwsZ+B@Vtmpqon`ETR_t*auwNZJ7HirKX zH0l?q#qIMyrM8Ln|3C6SG+6lm=N5Zk&W~X?kw^M(6#s@)>-6}1(J#JTyuUX1-{|0T zfG%4AK)378@wPQh_}>T#(QxnYO?xn5tTSB$U;5x5cP>3K73AwC2msU8o3+5f5~)N3b>-I`7bRn>PXi$uy$}4 z4%^D+X$m)Sg^!p-T8AE6hkzJVa7_Q#a?)*nzumh)*Lnzm9klYf8(B_6~{3Msz3F)RDvU#S-*SE-Z zg3X2u?Hw9?3g_;CIPHQN^6G-4E#y7_o8Cpfw zd=%6Jy*zypcfD=a%yYtXgGh1}Pm7BUHt=Iau!rjfXvI*K`>Q`C{sMuen3 z#M&2WnR0X?M?1P1FLcmy((SYi}VQ_~Ss(RpgpdF%;N75QX|M7o3RJyvs)M_5{y(0B@3*CkpZ z8(ppf*&)6FwIGau_aT2$x&}*DY$7}n#w?Uvo^f_E6mnrWGxa@FS|mUdGwJQApq02O zthzdIJLp7#?01y%DL4()Ccfk+u5Wv0GWgmUH3~VZE<}V7!RkHn6Q#vH6ZQWTiW5GCT(>Py);m~vT%2LdJRw!DIDIrsG_U&+ z{HGBl5Bjf{Z{UZn23(~(bNJ`B!)6-*133FqwQ!Z-kD9m*QT1Z2h+2=Duo*%+Z?Dn&iBoo}! zlsB|-xo9=VG$V?QFlQfqW^?@VOtv#gnK28EjgFjyC>B`xau+XiH}!QVgh4VgY<%3I zxjE*esf^%}k+t%QUucLXmLqOayh&N3R1%*07#r3LbaeLrYK?w;YRmco9R;(8>+9#K zT}jeCsiJ>>s743>-6rdin-DJT2$T)h`rW>uJ|4aC0$07@<|8UOF$FD^s6RL~%B#zT zKkjkTx0%s2njgv?(?c^~p^~*$$TU@gJ-s+kQK@uL)Iwba!OhBDC zqd>lTzdGNpqWneC;oHzlK+~ykitD4!t}x`p$(o93$mj&(cjnDUFz^u#au(pk0=1@D z^Kj;rm#W*d@Im{@9py{1De@tg!Kx&mLoH4@98VYCG<+6*hye$p=>z_ z7WH>%l(EG=6a*!4^)W!uQ;SjO_-Wo(6lvcx6SjEw zV2-}~uDp~*D|LoODlG`+wZ!~;6q@{tP2r-o)4ObvWGn2g7JPV~uLzCu)qa6x6aa=2 zBuFtuSTQB^sd1G^byPwt*R9JPzpID3S{Q)a;8~j8OmJwom|_6muaN4P2x*-7N@J)3 zJooy|3NWoAj9B_gq9m34#^!HCe%FYf=R5BhHAaH*zn_^46RV5INekhuDF28cO6p`J z{Zw9)Z*<;6^}VUu8JMi~gLK8BM@Y`njIV^b?Sc0qa$nuYUT|3-2-}U4Wh2EnK%a4V zV)dZ4(#W7M{Y{xNjaFH^B3zK&G>k171_i9Lu|H8*7*q(<{Q5#nO^u?P>fYvZSZ=Oi zOiT=M&J1zR_M%_%1Ir0x{(N+lZyJ4R$VRj5 z_yF@Q9=e6!&TWrgxoHNbEv?LkHAD32j3w7Y4i`bx+v-e}AWQ%(jgl z*SAU-*RH#$#q@&WCa4*o@-H9h*SWzZq-oW|E+Y#h4!HnTKEgu;Dp+;%*rt(iLladf3YsK8 zt0lWC5#t3P@Cp5oci$DZ^2uaDc@ zKiLxq*%Ql0Xb597iR4hQd=NO`(+-v#eX)#QM?C6`Z%j4ftbX`3ssP~#ZMy(u=rc94 z+URO&UQ70%>{G}o@x|qB_vPrYQ-=*><_q2ccit?KojDLFsW4`K_K3hw00I({sb@Y> zFu31>AJqKL3f&_B;TvLpSs6UppcrVm#{C+wX(CLO1JKUU8(ZqMhmV?kG; z>>JKtHLd!XtlcakmyJL)pEa4@C9{4*r)nKWpjps(tP7PyaSnX7cYFWo%hPhZIbNno> z13&u2A94oq9;5WN#gZQui!W;QNvhFbYx|--him8G~($ zHc0U8D_`I4nSapvs;)U0d{aC2pbI(A(UgKX|Cr&yAQ^f}V)NoI_(5(_h!ZpDgp;!) z(5GocVwX!X=n$yt8k)6I{cmaMrf(NxhA>Z0nMU-%fH7%cOqdIB%jF;WwDS(hn9U7W zEZKMG<0YmrjNTuoh*5Ak14KB*h9%aFE9?Cv@ZFO$>OUgrOrSnq8)MW!iMran0%3&3 zFrC+z#FzRRgiQXH-$++u(Y9Vb=~X&nwU!6_)*frU5c6iHlNRK z8?_+BOCqcO_-QdqT2ip1Fk%R;f1UxcrgNKir!M;`Mj2oS=!iYr=69k^a@H6rQer1G zTU+?PmVJs6W@{U&t)SP?5@Ri_24z4_xg}U?wWTEfvZsND>IAa@4>oB9zQP5+H<1#K z13r=_^V@Q6zPPU!IV?PuEO9DaLc#pC1KE4N#w(g4DPe{V9F(e|>EZT0#Cb6N1DtN{pmmFdICvYY!y)JVbKZ z9c-QVK7eyM7>pPT3glYq=+yD%;p2@w6S`#Auy7@ZOk2{(?PMC;^(kD$3FKig{JE>8w7(DbuSj4Is zqBHtpG<+L*atn8r1UkVpHIPY%n3~+Z`{iWWP9wNMk~W@CpC;+WUpXN`i}T=nXosmo zm`GA3CNQhFnQ?a2vv*%&#!M-li_jK~ za|MGCl`|B`k1?L&LY?5h;ECexkD#hug{+?P11(N692v~&xi9j9Xx|?-3Bk!Ml$-j5 zPHv#~nc=8Yx4H;KOnEBACuNA$ltJ+^7ET9d1bCGq_|jb|61~dFX~whwF27A94HidD zIayQ2DG9$$rL0(K?n1pM=5@Ss$mRTd@&ECqH3gAzRHiIPua-b zuGK6>lT{3;mOafWm8=K{o)ASwb8*bPDY zkUrJCascm4$y1FmY;7-_6Ye;EdvND{cXrPAlwNg>Ly3^i!}q7QNiiac+XI_s}A-SsRR# z^+To{=vzAJn`B4>*A*_JgqIP54Mh`gA(m?l!m$kB2y^`&-pVsskUnwjdrx2MaF;O__!*9pRv^IsBYsHXh=g~a|BzwL|q&c!A58K(-;K^8l)i6e8GJh$vqwO#2sA-7-omb)q->w>@QW_V06Sq0P($uZSq^ z$3bn;GpfQUp=AX{>8wH20s~fkDkQj{J2}@}A0ZzBjb$pmXB4BE{6{nl7SqxhW-K&C z_n@>$8rI)Y00$G#nc1k!Wdtf z31(sTGFi@xoyqu!l*{IAtpA=AZ^HeM1=bbLDrwn?%sITVdUseTPFh1i(|$FI$^Wi%_2F49oyCWcvfR!LKTDEj z$>7OAcow5{p#88kmrWtmRW9GDMOJE@xoZ$O1%)9^uXn;Qe0_boq4nTqVzuIC+hkZj z8H;{>(d0&}ZY&5C%;pE6OFdnQc<7-mkbz?p5sW;KB{2RTRl|uLQ7Hg_CW=i~6P$ zMaov%d84n?WRLp4-}y%$gd-W}7iqA?M#KPpt+x1%bQyv90s1@O%^C_h@WpHq+asou z4mF;mrV@=lfpWa>gLg)weEIw(PFqh2eiYj)f^(Io77IlX+Dco7=tz)F@@>TfOrD+Q zQ7(!=?kGVo8#^=c@7m+OyJ`=@c`<+50@%^O%`u^g_*KfE<>l4FUS2%3Rh242e!ORA zXUqyyuhtJ|dGxi)5^n6N!XcfRJdQ95C(!2b@f@&!u)-UKn(A12b++cUe2LQ(;?2yR zKt8$!uum?Ack8AeSi_a1i#;1qIet8p=WvQmot9Tuh>=^OU#at>O^l-MO+g3omD|o# zRDNHMj>`DKw!kzpI?@z>%?J9Ii)?Vg=#TD*po*Fr-60xkV`YbKN=}#H_*5y*S+gNe zWCh&u9C4Q%Hlc2^@(v1oE3=$`8D9$S3Uu?}!ZCDlEt2$CX_rp>lc~_J%1Tw8HGkXC zRjY~x)ah)s#1FV~l=y&Eb!>!_OmLnxQ<9<*(nft+o0PCdf9>JLLZU`d8 zrQezLI%;(Gq=&x}T<%Da)zkn-MV2U6sxVSC8b?mt7v#&OpbG7Jzr&Boyb-i}$EMxq zeTZnJRL^=lN}+x{EGjd&%2`;HG^vFOj?KBFkW3%WwQyvdCA zpV_?_!XgKFNyYZ=(MOvY6PIAr<5AZ0NeccG1Kf4JODIb#|bB%?9`S&=G*d)cg3uZoLH@ z2M6!b;t330PEzsdVghx4(03ED(ar{2iz#oo_p9{_P73LA&{HaUj3JT6XO5dT65|>G zd!H4wuj%SwwcZgu6ex~i`0@C3^KkXfsQGJ$^rMfOLBE#*PBr{p2yL~r)K@nO^_Ckl zi4b2!*hIwmg0*v%8!OkMKfF~74BJjdSteVf|R|1KxO5* zvY|n6WhUB$K*cXa%mC zy^&_y*93?BUaUc}57xBe#PVv%!6}~a*{vY1SPY|G6q79WBX&cRboVYZUV*N0biJ8V z*CPE#Dj?nwy^Xg8g>mS9+KDO>CQ4Ri$-gjuF-*4s9xB^9)ibiDi#2$-?Y+S*IXO*d zHru^pt$KIGBGd0NXwx6OsR-0kLSJ`DJevS3PH<8Kzj6Fr7AURFC6?W6VY7>MmkzrWhy_n)Ui(Ee$gqTI*{1L=PJ(=`o3OO;O;_dpB6=SidDVt5vC61#++GDYNu)q=YN&W|v)F=>k?YQ#7v3u9ihDutcURhKSg%d2$(7 z`rFLh%jq-!MXD^d4a1l@LQpt^w_ss1@UW{RT46Hi)9ZbPb?^P4YclGTR!9!XSb>Li z8Q;;4mWie(ZPTtwhCEN}xiR4X3SFr)o%R+eVxO)>*MSHoyLyN$fWMeSJnn7g%Z|pF zL0A9vUhlNV7kY=)^J%cPSAER4zG7qWx2rtQF_cYCyu?LIj}7p$NVGTV|B*MhaA39YB`~Dm zH&|+L9?BTcPbfT(T)q3*tv;etjzC?%&VC|Zb>F}@adBDakyFuTTfowARywfhN?Ixt zhyLL6!4CAtE`gwr8lomo+U^)QEgvd#5$AWcj>L#9>?%+h8GX8Wr!yLPo!&@@CQn%G zm}%5fG!X=wE~5TYieV(=ffAQgC?_A_WuJ2rBy5Q|Jl0U$+YC)G1Ze}c6L&EQoW7gE%47pNcpmAs{WlQJX z88c9)@a{8|i;I^cBYcF)+RP{RPz@7$WK$i8PClN2)P3Kd77#uZC6F0W)X{=_cg!Sg zc7Q*Xy%d3CI+NQ95}jJp_ZL!5SwjdMr*l##J`64}4PjbA{z$ZZBk~$&U|b@}it{c4 zRWY(iEExObeB^;H&1ruXC0o!LA&tpUSj#FrcRu&vMhb_}5m~Cb29)iXu`lXJR-M=A z!D^d5mF09!eC0as5ZVG&Xr3XeJpid=wLq@P5_3lB!kcK|GkIin47p={qdA5uPL@Y0 zH$m`+L`sBrcG5i_p$>{tYEcUS*K#%^SV6DV2x~9N_LymB3)5tI@X81E{3W@ybqlb7nCYx1VNwGpFh-aKMwwWLfUCD1PRn5FV$`jx@ zcT~UIT93S_Nj-?oa1|qM7pr!cNo6V)FU3RNbr49Xj_fZS($#5Bv{~P2R_k|TvRO_` zTKxECstRqbiAMyn*6^K0EVPi#4i$G+TQ1BsNz~F89V4=QVoGo*e5Fh&uWv8-&G~Xu zM?bCIy0}$}_4u817w5#qUvGOZKq5NTcq=S+waX%FVuQI6MT4U`f`V4vP=i-4Z1^_J z0%l`ym)o`B-!ia#=n2t#qtJ(%?bEd<# z>N_!In8pLOUC*R(==kSsI;eR;YI)5Fe>;i)dxce<`3vpuB_%9J9pcj*4-{F?Ee1Cg zs_6E;e$b}Pwy?!fM6NwrRotD&yxm zj4u4wq%5?is$$XkeQ4&J1^HQx3}Z(1mO2Ta*`x1NMlZ6)p$fY}XGApVQ$TW{{VX)) zX4)_7;w>_Do6`vfaoS0OxttNQacvVpNH1q~<#uG`1DqDwde&quO|yei23A2$)7L2- zRe);?Tfq_@s}O^{(`Z^m!emTAS?4!sptNqg_`@9PZAc9+-+nR(yAXBWk9|DpzPm3M zZE$(1_!agA{yD&My5phJt^h2Vh%Uwd6u$If>zerYdlR1oj0w-Cx}pxo{*hB@u2y(6 zdi=yu+q<|q|B-4@x^#R&Z6|>iQ}*yEkzWAPHUJ)4Xgj)*D*oX1g{{r&fmK(};ml#| z?=>><4MhQREnhVgNltvV!4^9>4TP!H7V9^eb6&D98uO7+X8yU_iJsKbtnWQuXbjT| zZ8R$gw7sJvBgjdh3CR0W{m=DkIc3sbmq(*7?E$9TiKTG8@lI;&PZ}eCUZ-D}*#xT} zJoi^ge4n@VJg$ioKrYNIc0SH!&tC zWok5W(-u;XLSqD6!Q#CK1RmdVa?UK@b+1)4X3t)PMjUhB@ft~^qAQ!E-=Mz)Ih`jv zD?wW6LqQRNW%Ie>_5$r!osF-gxINAwcr$C+0*;liW$`i-Sj2|yJv_?BHlzCk1rXTr%&)O)R-WVDXTvQexv5+mfAo2LEv!@?$c)IrKP~5a5=ku8QLeQBx0#zk}*XhEiCfJ*D-i^c3SYu z;EVYAPkNZ_SUxKbm+X0rL#>&4*ht8h!oIKjF3e?kyZu zq{dG^j%IfGEA*RxpmJyhwxzSSgypNxAmvb5QA8~4888`j!bWqwp(lT5JE^VrgVHej@|Pn)*& zVrenqhTa(~g#$bjC;2*u*qnwD{p*lC#|QMprfE=Q#l>XU0=9@}nMq*FsmX0kd>t$t(Msc?X~dK} zhCRI75AHL+>;k^FCjyIB(UfCgi!*m`ezMH`BaKS*j3u`(^Wi*{Q}!#D!4-2(e;=tr&?AE_E;PoBFKtHRr>hP|Yv+y+^a^8+l#&!(13gvBsji}++b&1cghEo- z4ly=1?%V;V>M260QdV4)Z0>3HpNJ+Y9;a|NIUV&A=FmZiK&`Q?k2oz3!LexzRhMbr zV1Z7dzPGEMP&_Rrv*IeC*5YUS-z&xKxf+1XV9p7+*dX@Lw=6f>*s#-Y-r_Lv&eYM8 ziHdhUF)N6wgw-`pSpqO^w>M;qGVL`f7m4&?i({ZH} zlTX+Us@+8{wHu_jml|HP_(Cx~EtH8;>mf$#=6p_ws!1HQrO#Fp+x?(qSF0!Kxy{pN z-n1n|r}MaqBA>8-fK~(lqBb=2?H4akes$*7EpIx8r@4-VUA=-@oB4X!JhfpL;+f=j!`Q6k2%ehl&2gg9Iy+ zWt=O2txGPKEOy5=T@vN^MxD1Ekr}qOZxpDaqmL99XGYIQB6m;i@{^w|*@9)W#hRqb z5T=-(lYl2(7dgU8BoDYEBKKnZuI&BbTDK>m8Hv8QQYeF>lkLLt%S8s_@+U`W^q?rn!6($G|O$SGZuG|1)r0vforJJPQH#&ilaH68WZ2+7i zfnU7h)!bw11Ka{=LUpXF$6)Zgo~4js#_(4dTEI``m7H>8{M#cowKY z_ebgo!8#|VOuP>)PKR{e^@CUojT8`(!QWh(A}F;;ZHs>VQ$P58{o&!X_tzTX-pw?q zGdQC#*?1<}s<(LIyS>do|HoVX+aQv&*ei$-0#;&Ognsce3b$gAE|-WH#*N!&s=k1# zp%oVmcbU}#|1DYgquEvXRnfr+hdH!&Ge50T-$rJ3z{3yFutrCEgchN{z*UbnjHa*| z?~Hg$kow!__fGmh+B_d)XbWEw0{Dh9mZ)e{3#uXf?h#?cKK$CePr)89wqjkaluV?L zf|aB6g!f~RitJ14QNLYh#fd12+xVV<@brVxcQ}^^QW=p=`7Gc8js9o_BA~J zWMJL!`QIbm?0iLkVF9ki(GU zMXGMng{u6e)HlS%j*VVD^xifLv6w4juQn|(KU0ENlwD*4vj*Gyb}|Vtr8deNe$ci1 zBLA}xUZLLgCQ))rC!to-Ne6-3iJbQKtKTPpxidW$?5C8K`j7>-lxu`SaRLFJu#ps+ zd+(j?`_k9v@pFIP2j2Txnb6RS+9>np4#Vj}1m)`0+TcL5bjV16A}0AdgP&;IpVtHq zDlIlbl)*0ZnmPUv$vLkVQup3B#LqJ(K!E?t*C)}FIkLh$_y23 zr%2^ouR_sgu`Orr04gi-~Ejfb$pTpKzFxg_#2Wpj($abnO& z`}gB&C#RQ^DLt_icbP-3FKE8{mz%BR<0A%KGCbY8<9U1+DbMM|H9Pco%?CQ@F8RU-Yu&Kf?7?TZz(>jp4nSZ-7%`d~t_}$jT z6W^EMOP(p`thf5AtcH-nC7mrM`8v@|msaNplsCPfiASWuRVdB$%xwN_^fSv%dh)p# z6Fpw7#WGswHI3=b8Huv~+ai0D>H2bh@Ss4#iH&|}7{iC&gZq|#^Y=5h_n~BOc&*P! ztST}7PGtc^|CUd{cZpDdj^AFP#8JxZ^(6t`*0#Tr0%y^U>fMm}rvI4e6KH ziy)0Y)Wnjuf6=bZ!cWFm($@ldMzEYSDt&L-76%92r;W!2 z&WE~FJ6!}-9)f`eO1%MPKu^Ivx4(A!iQdPB`iVY@{G%K{W{CFJ(t2Zl=((F-7M7G( z{~8r%kCWFyx6ZL#b8aW5vZmrJK4fO^&zXa~2%u7KFWzfFhx# zhxVS|@C8qs%^Aq*eP#hXB=x4;`i9J;o?{c8rFkBxhE*qT3FdZ&MwA5Ks&c<|3-f%( z%9=CiBd}-Sc727&bObu}$Vc*qVxV$Li=F-%CRqJLRtR^qefn8_S61)Qt>r`o<2_Ey z#uG-Rf{KCbATmcvryUy1M!UxYe8fY1&JE6pixlQDr9oddvkd;Y*cbZgqQ99AOI#E1 zu57+c!dPF?_B$NbWR-Ox@A&3S3XI%=H#W7DQoq{;XWBF_CMMH1$Clt%9_mmXsVQcl z-rqA!FBes-z{uEm{P)`nmTC2NY-P>~S^vx175kUJ-e%vE9=ib_ zmAQO^r1k?oEyPBpOTNE8K>H3w8p71yAQ%m}!#{k42KK<;n5pfDuBg+MPt&?CQ}X$< z?^U;_+U`3M_1m2Ysp1HSmGfeFD&S>Ql&RB#G)hFsp|Gt24ThChkt-Va`bBWaR-9iJ zAQ9YJ$QbO|RjzMfY!zW8jo%r~ab56LIp1qTod37aP`?oJQ6~Y1Sy=!?*%|P~AtahDo z4d6p>_WWQU-}Ync|8GI$19a zd#7wE^7Me@vh*-Y*{w&L!LuV_Q*o#PrTVwq!7Z)VGp37usi@%qPcUgsVnc)Q$}ma! ztWIRt)as$1OIdZ6lZ!P_66GwB7)%-e+1vp9eY5L-^Xg5-r1FcqTs- zC8004mJ4sxXsv27g$p-z@+9i`+XFcZ=^?XM6{aG6O&Um2Y77$n;zjgU_<1BgNXAlT zTC3MTA1?*efJbUdfmB+G%$XU2MRonrkP}Y8k%TGg1!6U`)NsP4_@y>KO>%$fP=EgRlUxZxWIj2#PQagm=1c~esBS75yxf%a2Ukc3wemhy|`{>@P;MM8*a8a!)^%}U=yMFqv)0}?5p)D0o3O)DZh0Ku;<23 zx!GVXKpUMpf8>haHOq0=J&9!>Gp=7M!X9Tcsk0B=*5yvj!OcJ;xXFFQJUtZw%}fml za&#pLzlOuNOk^PR{I-T&`oBHdd&)FdF{`Ln1p= z;$tl^{~VewO&}x`*Ry2`_*6MHNN6=x!zf6zB(gxVrqMmjQ*-!-(iC_0aa)%Mx(iS!pepWfAo>V9HssL zF#B_!o!g*Cil4>rT1zGJ12uF2SbKQ%z0z^@|3+H>#@+xlwJ3R^T-VbB8ZsdP*0wg6 zvN{jn8E2XCXIXzQE$7!eQ(8{jC74^AFPeGD#*!xCidbf|7bg?oF_IorIn&SQ5@7Vs zlN3{ApFaE@ROU$*r#IvJgq#zeARvvE>M|i#g31K^eh-^ zs63BP}D8i1+rv2a-Wa6dNB$%nH1v#Y=V=ec(6;aFM{`dDxm?q-glmV^uQ?X zVd&J0EYMsC>uoe9#LkJOWfZHOqbDj}n#0yzAzdN#+-#pNpS?I zA51`Wd{4}+E%5J-=cuhPLp+&5JUYqdmorB6-_(t1{4?a6P*{pYSy$p>p9pzrCowfyQ^K$R8a)&UF-7U)ao-vJmCjIradx&`4%aZ;nOXhfppqO8HM< zcE)LKAPB@LaU}h1s*<#Bi#P}mNE07332xxDuoMyVcB~2%evCVBGRs2Z!^SR#9wVcp z^Yin8%c+(zvI4jkY%+9p5fOD=x}MwVuqrgP$%I-GKK@2btQj$guxyOqCwg-net&@q zH`ec4Quxy@#uM~ThG+in|Mjm^fkZQE&VI}IA! zc4OOiCQf5Fo_J#GoBbVozkgwlXVzNxh4ThSk#UXzIJ1$8H+W1e#k&d!7;btCi4T5U z`O!4iUYjrrF^CVl6D83=(%+L(pD8u}tvdkxB<@f?*783pT7G%?S}?bb`b<`}je!94 ze`2z^Zn{Zl%w43%zk!0=wui^XUgy?))s`jsF%tRKaWv8&WJ4ck^||4a;N-J8k?!x^ zD}AkPFNM|AFtQvrQ9ElFefP66w3h79_H6s0%=Vk*S?eNbPO==pf|rg^n%H4sULf5L zU9VW9msN*9W|{dl+u~MW40thzoi3EF7er@GvZVRDJiT5M8r^cWlz~BR4L;nQhF*jn z@BK&4K%|{48A9z>9TJ1?KSzGZ4;i^8ovTSB8Ih({3e;ct5HPzVT`0f@0GBIg>2y|b z2LiV7_06Gns|~}l!)DNZcB}E(gVfa+hLZ77k&^LktATcxaZ?zBUIRRv<*b;7JA=iH z9i-4AJ2P|nySXsdJHJJtte4!r&DnK}Bki4+1MMTOYvAg_LM)n2!j0{N>(R7YmXMb8 z6i<_7QDL|Ka`}Az0?o;Wj=1}eh7<|xlv-rOV>LC6cpX>lpS$y^89bJP7EIbPJP7H= zpdhdZY@XfrvtVAo1WLB)Xm$m~w2>_)HeM#*EWi{AYf(EPy;qbzdP&E)>7ygwE3uRQvdQXPq-a^E7OtDN-K(eapay(Oe3_sDwC07+w_j)&;NWcd$jcMSKbby} zy-$`zN_acGKvb@pNu^iiLEE3$VJwr|jCC%)_IuJAFU5m$lG&d*QVRDEg?)WSWKwry za;&yquuSDPL1OanYm=$Omp2qUoma^wrTI@xTsJAVO8Ae!x?o02 zVrI4&SSg_t)fGv^Tds8-iRB1+LhpmxQ59&|D{?}BcGd7l9{$zQ)Td>$Dc=4pY4k=k zhc%))^frA+#ye)76|x1~mJHz(J7Twaah$nIUF+G2xFz!)!vv+Uhsp^w`^ltR=B!%m zmDR;ye7oWpfo+@xtCPOyCJ4WAEe8a7#8x8M#YoS-J zs18C!TSm+=nL|Rd6Qlh&6#V0`?sg8|#bW_BM_#{Ocv2PKXnu%LrC|rx5O3ibKpa~r zaky$(>al?p_99{=0&}DJt!W1!C3{N)w3EO0XM~@wrW*Mp*?c&s-9}_o=gDc=mdbjG za+v7C|DpiN{oslm5m`pIRS(Qcmp&u1_nEyzkhy)y8EziRn8fL<{}Wfc(>C=hTTjtuC!ozXe%Nt9qbYLXO$?L4T2JO8C9my1cqt zk~Q(~mXUyf0JrA@Ju)G0#QW=G6(5?CNftf3>81};rYaL|^f-DNUu5BC9I=!RJx%l+ zG`(RbLDfp_(1eC9<#vm9hYukZlWxpF;8((72RIlv30F#o!AmOEwBj*jTj$$Om~#oz*1B6 zwu)NTj&Q09pPX>RHIo^Sq*v}_7&1|5qk+|)!RY_@UJ%NPlZ+EEC(arAk*6pS-DH3{ zBZi0>0#!Kf;*w|x$sjl>=HhOw03e%^9r^}1aLUqO)bpq<)kiMbN$T=4PX4aFh{lTW zEhH+(o3djvH}72J*_%0DS#;?)H#+yFR|jpjR^3KOn2u`+=kztb1LV3D3gQG`iinpT zx6=Vmq&&|(Bq6TaKKam#@ZM9R*y`h4IJfWB?>y5iyp%I&%v{}N)q4}$0umz#JwEuF zntJXL4>`5zkr_U_N`aK$hfAzy5a<}>5tae>_fMOUjr{&1qfdXYs9#>%*2Qr8c4`5P+`rqFTvfz!(Xftkq_}J;BH=vcCPT~_B-QT~lyQ6= z9yHcjgNy%b?&W{~PkdHc_;Pw{khOg%RnGx#N0j9%t?O}az<;yd_iNwN9Lik4ewJ4j zA+ZGn%;otw;NLF7HxDfRkm6Cmy~gY^(1INh>Q%dFH;j80|7fk`&}(Q@{RlcuMqdo;TaO%X%a+i`wM zm-0!qNO^TOP4qO<(}fDRB}C|LC|jBN*KHbwY%OjW=ERe#sDG!{Z1oPe$lX^XOr}Q| zv!}IJhgB=4YZDsU&2~^gCPT*Pp-|Ci<|1bz8%jaX7>Rv29XAPg&&9DT*cYE)bN`mZ zzyhVoWnTQ%HGp{kYF7-0h-kTp^=Ws!vXWLnFpw{zU50ar!Lot7Fj6)}Yw3^k3_rc@ zpu{6QOM2B!X7rU#lf~}l$pSbeGWds{LMJCum}TM{PqLg+lXQNc7bRGTMvND{>!IPOnW1oF5UDt5@Cx2jEb3_N=UJM-_CsUE0cUiCaHHTE<6E zSyZqz)+}cYej{bK883H3b=v;rUuJ30-~4mt2mjZuxX_ELMupom6kK2ocWn@+FH@oU z9zla(55lRgtdTNT;GnIlQZ~?wrESpCilzb4a*QYl72t8$rc{Q|+Snw1Z_?jW{wm&g zS_z+-#JXuxrju>nE3!&2!4k=@Fv^kotz|HpZ{K!!8biTR!G7+aA_u$N*XlVn-6%Nqhbl5(p+U6;PqaW(l7yo{*ZWDuiGf7= z>90vB|9(l$!hx(DlA^zQI>>#h61CEYbP}3o&47OHpR`jn^q5##0Zfk5JO{7acP38%~dj3!o{kjHE%LA=%d|Z0tZU zY&{IR2k0E`>b}KZonGH3D%wd}qIcScfIm>CZCQM0ep26P7YT-O5|b^8a25YpG@3jhAG zRT@;&R)gG-A;1kjD50*qq=W8784I2OG;9fW}PI#@zops_Zc$5v(kWGaQ3KhhhX(Bx@v1Bk)~%v&HdzQnPk+{;;av z2`wJ4Jb{O{1n`3TtlQX96!sKCCx^F6opX_h#|Az~h@Yi}SkRvF6>mt4n^N9}2Ls%* z9}aW=bm9FF7bSg&e*fjMFBS00RcS{AvXj6~1@Yesapy1Jp+Fp(RAasTjW7KGDkz}E z>1Nn9{(}F0JDq)V1YgByiZuk<YIeZ~ZM{cdzk*2cZP?@qRv+Q>rxXtYPh2vn_Gu!??EoMHy;AiAKK|;*x{#U_A%Jg(BU5KKmR|=c;U(0g@e4L1Vz+xl*cW)g62o^C-j;L%0^j2JYtnwutLJ@t-N0SOO@5wgkN9Hk>HXb?wv z*lWTI1V4N2`G`ft_U&j2HMlpT8Wi@lsTUoBFn5`g2NTq|U8^_SUDo)i*%*jq#q>zS zMQ0?xwNlvoTJc(vdU9XRa{=#qLvKqn&=NZ`^jIwa3)hM7`VZEK|NGx;{T?Qdwl2|| zIs~QXBXmkeA=4piML)lzYU}K7`Z(*@!Nwqam7;>!Gp%y(YLd8iXj(&p{ao zFsh*K0sDaR%h(f!BB+zVxM`-xT@e1#L3D6jKT zVMnfiPtUV|sSsposTHiJOy*Pn3G={?G?-2ER&RAHOtd1KN4jiDNF27(2w`{dFC@PX zQet{8%6;IDp8;dD+r2;pS+zz|HfGvnP4UTNMhSJYEvLvwHlP_!c*{KV-0Jehmm+R@ zgp&CWiI@dea)W8>ARdp!=&4bn!6X7x7XhaPwy(-Z)ifx4lrY;2ZIwIoYw zX+)HjlE-MN%o=93fEX?JUKeNEqx-Yn5z~Cc0QlWLj|JrF&3eMB;a*j%B_F92>#C=P z=7--n={I%*S@&QcW{ApewOuBQKYZrFLu0tnfjY?A=NXAg^nOh2fKHhk#*$la4R>U| z?CZ3YzuhvYQKH^NseSI`gclJYb~61AHnz?1Gd1sPofMOTnMUNkp&S=8htni_$PH}- zrpG3k_m{{bek)xUf8a_&=16Rvb9z|vW+pTv!>hXdnW>u{V(|Mr4iQ1xnIwaa*}tfX zxAeqk`oaAGipu4@Y3U=?Ko@wHwttV18r+tnHG|JiPQ_uF3kn1rcb$?8I8anH{C_Z< z7guJ79|)CjLR~dd7i&7`{x(A9hIVLUEz=>c5J~<<)ptn>Q4y&^;VfplCUv#FMLOT^ zf^qzK!LB69!9k(P9+$7vNQ>MxsfJ>{0Ex!J)+V5dSDxJstgb8Q)timbiXUW|{`<{( zJzb$+i+qyI6lNG*EnvsHhffYfv?Qu%K~Mm1|GFvh$39z5kqUI55#-tD<4Vl!~j$t@ITsk(eVE$A(Ko z4ndrxvAaxo|W}Qc_}2@YeYE?%eZT}<;LlJ*03ECzg4L4G1)uRH4_x1 z$-`bMvI_d2d(j5F4URnfdi?!$w5O-n^_0ZS2x?EZDzAgNP~bYCdh7JR3k{U)89j7) zg6>X8ziANX?qZw|DU>+a+oIu4Xoqwj&Q;Qnagl1Jm2A=vN~n9w!mKZ;_&GSGI{TIy zM|^|PJ9B7~UbxN9eHbB%P$9=5KPE~`hd{j*EGbb9Y2HH9emi{*jBLC#8%-p_?LRSv zx!%q0>+kA&VR`6z_IGG1{WfXNoqYwC!x@lnf~WEQhN%@blfo!BtF!?el=CqY(;Ft3U;^I*|XNiqQH|H+I-Gva)Sag8j&{>xu!Xy zx{?E{SE+%e{E@$Aq7*XhE1X9xNLeU9&JS%Vw|J)vI?!&l90txQZ4;}rBO@U_Nk&79 z`(!*y^LgPAD^!C}3d?bdS*Z*IUpk_he`Su5zX9Q&_yl#@nDrr@MYZ0c6^AJc#Y@e+u(DeQr#IGz!}?cFEXm66X8@%|`{x-fJ_Q zX@o>}O3-NrTS_?h)w=@a)W>Eeo6H8)bNZR$gHkG;(q3jQ{;n*;Khp9{%i53yzz`>M~K8q*Db74I)f4~x&D6KBn4`Ez$~u!<@9;u?74jj*Rw7RR*rvsv`2IAeLvDq_1>4A^5oQAEOp&@;Woye4 zFh^Fs)h=@Go)bYa94CiCmoKuT67h{`!@-BBtHDYTSdNhHEfS^o`w$%HuylIYS5i*#Tne zkDcaW-#0s<=r!3EH-*EV>fQW&-9^g*ej^EJWi z%iY%dYJ}217@q`ND&;Q5%Ol@Cl;4z+;c6vgRH>a*pwsgOy3tZP)rK<3$~TX+EdCqgj3g~N~Aw(i_T2A3Cl>Tf>bn{Oqf1!187mDCUUfW zPqXx6rpuNPRDe~r0{QNB>^E?G%Bs2Edk0qG>h+TyUtvthdTCbDkRzq-Gcw`-9L>Tl zqX6MpGR^ad130D!^@DP#+QniBia)Q%pnE%h7C4V}QhY-W;+JYsiR+g_)wc73bNQ2d za~h02BVmH|Fr!Khym1QZ#39NQmhmRs86pA!3Gt4ToxQ&i`#t65ZRMO^V0|{*BdlCs z*80|#4q7y9Q>1yOh9-}zfS1>VDj%?q0S+G#SM`L5-{>A?TG?0h?ts?%( z;i?lS<;2_(N!aiFdXBmXvNty2jf_4aB8ee{;kf4|ai@ADe-y zoebi$LQvcMiWC3c!E-#rRh29->ct1Fjv`KK)r{sqA)u!6WD<{#7&Df&!QG>9BJSw+pJk#k8=GxTx2Z zyzJgJoAI-9wKK>48<*5==b@e z`5EN;fLJjRpR@M{yR7yn=n_)A_8C9b|GHRXmpbKz=D=nf%7n$q;!MFZ&FBg8m?fdgV}JGGb-o_dK}5VG9g$#uRt%E0md4T0N-b(_g~!B%)441i zNrzX6wVE)m))k~hJ5JjTw2L}YD>Ltw=9y2)=D)2Bby{a`Z{o>J>68IuonL3M^|us| z>?LSSC28rZFh`vkK1p2&QnJ0AHla~Gt#s>W)PcT}t3gduM>g@JANjtq?Bwrrh6DQ6Vl6 z@PO$5e4D>>GvYcHcl(564HL)0<$u}eTN}6Nc25fi?Jyz5nxAmitK87sXu&NY47zk_ zmx!3N9g(GRO#qkMb&8>XIRg(^e7lbz2zZ}ZIy=`(x+c1ZUC*HyVJ`AXfBn|8{51<3 zFJQ{@p+=_v8Hg2I+7#eIjcrWegfvO!eI0>LyYZ#jCAtrvU*x>OjI~^r*PMx2`AcFFHpt%YTEEhdD0Z6ig`x;n7K=56Hhjfg=z1{ zRN=g(iAkp+KipmgU(UX>fiz#}qF88BP**2;jt-87-(k3^;15h;b2d+w1p%5oukRV( zvSx^&7l5x>Tf6$KKy_y8Tb_djXwHW3)ckU&Xq>pYfLbS_ERxK;iUP)eM`$Tq^1oP* zCbbFhaYqjkjv8LyJ)K_;oDuJozf#*P*EePUIXN$3cGn(%p~W>Q$qs^7N$^!o85A`B zC>@(G+)*XD#avK3nYx~uVcXn}Z7Pf3@A3RMSg{ZIyR`)O?v$fYSdZK8>yUo5Rlr_0 z&LNiapb=2^Rdd(s2agPrwLKKXXoi|I1^l2WvS&a)vEU9)qW9;^(j>Rb@s~J4o(Ry4 z2dUxXC%6Bu(b16d+}G^BLi4HCf5zEROJ@$j!L}Bz2cT<*zEd+qf{wwVySD zbnE`0>W%w7jC!(ye4CiN8 zcc*e;Xn!|wv)*-Dd@n2Z@p5x(3gvdQ-2-!_R$tQ6GW-eX*lF#`SmfbaKS6xM_JTR2 zU4U%b;^Z6DQU#4Y%0j)1J=|80AaryzVYazUMii)p7L%ViMomCqMk;1rw#8$OwMb=_ z^sI+ep|^zo_q%0#R&{nKb)I)-N~#qZG<}v33|%_IX!jc1^wd~5ZcH%=M7FXFy6QZ8)H6SAdv3p_hLQ0)53sG)|9)bXKIp3#FhMEgY%ucN8uq*p;%Sjn@?GEdNt`c zVfuQZw!BcMx&|N8_=N1RsS1Uuc|`glYPK|;#1Ah?bJ;0HP}>@a$hM!5USk{UTXNq@p;y&%bx*ftF^zl zRG~;k#=7P5r)g#>I26l8l5}!%>65xpOX@AZ5LU;-&DrDSp8ighOQ(!!v2_Z_e_}*b zpy*PG6HN-md`p+R<@voF{&1P%zf;|E!mCIq6jTKBSWwpkmzn4<-ek(k$$b+wu&4-U zAP+slF@l;r*c{L2Ad&j?faoBOK2MtDU6}oW_~V48(K(hlA>?S7q9fk_Mg&#}*5+pH zXu8QyhPDFU(%d6Rx1c3IB9)2FiuWD^hELQ7v1fXk+x-a@+4qigz1C}$-G3)aL7gzt^3ZY$ODU+VNZU7d=pQi z19?XdsDURmtEIW`d2c($dbSudIlQ&tW4zSX1s5lU8#nit+_mQ44a@-**yJA8@*EZj zTQ0ldT0nk(5T%^5iW|&(B5h7)F4P)~AKNfZeI{(^0g1aFMI2eTm{yT(w!9>_ zq9C+)+RJ46(sY*%({$&Tn7tP^jO!;_e|cWUd%?}EsAvGn&RDqP-ugHM&Z*Thj7sSx z{+<_XBbukMcmrR(G&Cz`OP@qixxLjQ$_dEl4h~$&gXiFIN1x%*JvCru*;->Y`I?(r z9n}%w>8q?XM0rS1X=dcubUxN;0$j*l~dK1 zQ5$(i)~P{8ZA`Qo&>o*Q=hqW53HqQEE-lXD`XA#uBiuY1i%bT|%|iW5 zcYni!**8O5x@7{lSn9?3a1%~nz>}b2*YFxoYb1E%Tyml~uz^MA4Zf@3gY>T1^N${N zcBy8#YQqrrJ%{KEaca-CI652N(U^%RR%NBFvPz=325aqvOOcZzjYNePG$!%<5#@G7 zb-ioFcS#r+bHrGZ^hD-qu@^LR1e;>i^K=$mqr-8Ey-FwK3j_>=3)#RUut7GOk&?-v zqWfTyu_}QoIWwCP%F=ANcX$U)!BuJ}2Sv+7iB!aDw4Mxad0o_~O&|)?ihK?$|8lpV zZy`%rO4*{6CRG8sxN)=Wn`4d9l{umeJ95K6>{O^I9iSK=3noGurA`BoiTkH*)9*x- zL%MKFK3zS@BTaiy4_qumJyB)SaoLyBlKL-%BcX)9F>4dPEbp%)eNOQI@lSgOiq z*@4ZOo$Cs2%)=vTQd);dXMI)Go!2`5O84cT zkemQST&~n%Ned~9yb`f<V?DV+-leQRELL=Pm(9q775|T--*5=*DmK6 z{fugBy4C!R$;!$a;cBV4H@5rU?gT1cT&Ryxo*78OCO%ei7_9H+s3xH-qN=L*U!Xeo zd2_DDU{lecj3xIYw*f*3bO0!uMYDRX&*AZjydpQ2>Z-8RMny^WH>^^EAWuofn-X$T z-xU}pINks-Iqb3gic~!WTcjx*5|}2ug3*TvLTe4A&H6myV#K|XO)x^@0k;xAb5OoE zisVu!MwVjoj0t}rMEVnKc<46;IE$xHj^rg|hw{?vcEZp0T*0^6Z3XHy9m%reHYI6S zNwG02Yf`L>f%=CAp0WGKEu}9;H{Rs~$w)<&u_of)Vm44WhTnKXvVEg~n*Y1H+6lc7 zF2JK||5m@t5i+LRxHvAlOICN$&-7ctCB zTe*u*PzYoz@iOgm_D^y1Ze%$DhtUXDoAAkl-}jh|r=rIpeRt5}M@H%pd$tU~ zwbh}qzX{bTVt9lXe<{$!%Pg{}RvM)dBcp88mlecRr__0a*Hw5@_tbY5dtw6031#%2nRTfm1Yv+CY3;ol( zoguU>=w=+98aHT>ry-Py=^{gy6K8OT02vTZFqj&Bl$dx8=$MNo;mU%a@WzL{FRNu< z23N()?b;?*Ore&u^>)+?wB2eaQk~y( z)oQ~TTIMUAGS%%>h<-AT6frAy${BKF16ov4=ugqo0~Yr|^f9SYhU%G|VPKjlwy5{D z)VveoO-6acE-AY~Ply=t<>;&98@fOZ7Yhp~30koM1z8<-HQRKU0hO@x=)_jinVy{& zDafg|dLWA9tVAHMA6Ucpm)lctg06~k>aOceV+DO}TVjofz7*YzmNfTM{p5e^2SA8W zZAReX8KV4cS5(V=pfL{r_-u)3z^KO!4GhuJH<$iRPfGF4@uDoO>)Dda69JaR{ju?B zfgW~$P&5JnL%r4x4{v&-&b^Eb>dh%lKv*`9&~ESICGfM6rmv!yW(p;g_bzIzjD2!;=WJjFDY)_v}u|g+Hq3Z~TGotgfMX0t4~96E<-nyg7@OGsaGc zW{0uN>=~TRId52`QRa$zaffYU&l*!&p|eYlb@-zcRGsqOxN$S&TWZ>eB2rQF->sUs z`1Mes+xll3>g19?@tBEWa_Z|vgW{2@&O~a8#bld`!{Ly$r4d4cy!87gybqvf;qBkx z>6!_TN?Yb^cK!1Eflvjl7sF01K%Aq}VtOQr1HbgN;IIJU;0-r~l2|?uhG`5{a-*Y zl`ToQBO|w#&UaT|!9xQax!C)d`IPsJ%(yNiQ`@4W5PL!pKCVF(_QH>lwA|Y#NJ;1y zCxe$&upzljIP;!+;gf^VhIiZghqhFa8k2o0ArRv9Mg8Wu(nrZ z5C=e=otZ9{fbd>D99{qJ3jZJ>Xt<-VnKu2?*9>)frOx;<{L*wAKwP9$+v8h5 z(H8UstuJFGkReNNKslo&{}1Ly#Mzt!51W4QAvgZ#Mx22QgW>O+N<7>+exh&z3do`L z|3)Z>#QsbogIlq14uO-Qmrtt^{t4m4+C^keZW(-9=O!ZZMTKxfTNeu{5>oUPb@b_4 zONE7{SgE3z931644UkJqK2#j zC#XHTocdf-;&LX<)vYrXVk`G@CyvBphyyXMGtyHBEZ(z&|Ikawrpo+0;i=&P3on&I z=$J5#>{BI&0f@nV;QOK{&^CSMtfLN`+JzSMdL+ydbpHmfjHm{bUbq!?Wk5IUz-u^B z%kx9)$hfx9&l}LFV^!<)<+Pnqx>u>W)SgaMl-zmwTOI1zBR+;X$Z7iFD{qK!# zz>GUcPapiy+nNRbsd|nqrWS4WYpPP7=(X~29!Z1jOhMDvSkxtW$re;6npM9k?X}4A zyYviH1#1|huYY3YBpPwrLY&f{sI+8<*{mzv(h3}I;plRCmUB&bs;w9wid?9usEnR1 zKaXILklOgw*?;5@Gf1w=y~aI%s_zcF?zDqauibVxtwjyp3FF zC7@?GX}~^6VJWg}8vW4dMc36`w9&8}7*^MNwdA;e$P|E})boVr!GF!K>986&DnX~h z=lZp>Y*s?zoqo8gj9gVE+)DwX5+7*19CWDN>kv)*huHf?g8zL!{c5ku2mnUVW6bv5 zVA^fnQ()EUhu@5L2%9tfjNed(!eOFPT$>W@cpfB0ZD;qYW$+A;yfcjwR?^~|kt56l z10=zwU8iXd3fuE23}DQD)sGVvlS|l2a5>7^O)24y)neXd+TO7@aN$SXUO#}ipsXiU ziLcny*|KSoylCw^bcszY%b;0-{diQGtwtk(D;E9Ws6F4+F@_Sjqs>#f$j*kUc48pG z?M_;i0N#}*b1ekevBOJtk$6_7VGAqhb+Av47g`6`$7iKQN*v|NH~=*==c?1fA#ZY0 z1$C%gBoq^17$fwu<7P4Zk%sNcWRI!9#KFILew-A}MEF)upS1toC;YJg`oPcyX2>(a zvtB|Rrb$;GwSDU3kh`p(vdw1qkX+FODZ#>nDhe1)Fi8+8aS-`)@h1ZFIU8yb`Fc z!w+noEBRM*Kfg~~=&(}i8$caSl&~q#Rme_H9W%R}q%3MkngB6PUZf69 z%KZmn>j0Ofeu4d#O2qZ=&fQku`4B3tg(_zi;xw4gkELM0L%!>|5+`E^dV?*YrG zXsbrnY0&r;^#%HOdlagn^PIpP1VdPFtlH6qPK;lx#R2^iW3*@b4zhP1R2UT=+)5zC z!yutX@|2pZVzSWpkvMa)G{=Yt)H9i3X`6Xks!8nKIR6L0pLYddR?B+S&bO2U!2Q>j z`P+qHEE)gBlxi9E$+kB3{kurhc3&Vnw7Fu4J{JKssocrpnRlezSnbsKR!CCDOi9Te zjjkc(N~pQlO-K4w?BzRA@8jbK4w##$VYk^TSBnvSpsN;a)kx4`MNmPoEx0q@t5Q57 zFJl@5S9EQMJ6dAIOph<~lguzs+nf*&I0a~I!T-sCg^ZdevT=COW)+0_Jx67Q72y{6b zswU-p*KgRY-!}+Rt1#m9vFxmpliQ?I@olYUBXDj}&PI2=RdL;CdbGytAkwlybIPXU zGGa7Ynqq>(1Z{<;fM;z?q;?NE+vZc9gr|c3`FZA$aLoAK5o&aQgPNb8l9U{wLIvD! zH@O5o-e+Z{{gN=JaAwVH7KH4jOGy$L)hRASZ#tS@f%$UAWj`>r=6avwe)|Ad7wh|X ztaUdg#gY8~)>`#U-d}k!J4GW%TpMt2scmKg3ehO;Ga}&JTH5vo*VHQ2|4I;fT8@89 zurYeK$i8Bpbf`r-&@$ozcW%$e;n^AWqkb5ALG|4NK4JTAA3s@opMM1qZ$G^YvE2Pi z^Zz8)7Gj}%JL|iZ5)FuO^!-G+&fR_|=YO5A((d*}GP#DIG)k9-2Rhzx4iozySH-~d zz3=FX##8(e8k(NNdzjKLRS!sS$C*(wg{NX>WshL{p}2Ez^!6=W@E;w*uAq3u>S77X zY)ffSRP@hE*>=>tYB$DIjE%zL&!H~{f3qcePPj}~zMLUOP%@W{T|Y%#JKGa8Dt8oh zNMV(QKl+8_zg>Z+i6@j#x{tGfXQ8VXCI5(?%bw6^OC=L9aOsYT_Je*b_Sxn`L^1T| zt9g@7Ol+*NGFH#gOwKY4MX;a1I%C5aWaGZ+v7PNef!`~;T}remrp8mn>J7#n#0DUv zq5bUitikPsm7Q}&(%hU9!&;d_x3q3FJlV#Dlr~}w+pBo=YV6C)OQ(1*8l2hM6y0r` zC_A2-xvPdo%bodaf<&eeBJ+jQS&5(YGP+5&P9Y*(o{|ETJ}(0Y`2~fu#yGV(>SYEu?57^{mPdnT@FQBJPb~Byzt3ej=$HSE#BDn#q{eb&nav-J9Fu7z5n4@%DoO z7ziHP53;C-sXc;($Kt&FaWtMj%d#I+a~V2Cah-9$wjL|=uLf) zEahnO;X{s#X8Bh!j!q1|i4P6Y)1h6KT;sn+F_;d-()fkwk%oNw1L z^?3uJb6uvVi>dBhAl-un#veHu^h!LReW|SnvXXh(<*#oudl*EVW zhsJ&qD-wX$v2<+@tnG&<;GeF5ciaASKGtP%cVE?~vg3nt4aCf`V2>+qzAPn-|2Y{4 zsQ)=Gd-eB6E7y^cr+rZjZCP&EvGBb=WAD>yZ`-5mL}s(D7qk#FzSF*fBV=i&tn#1;YWftg}qQIpG>1poSs zu=E^HVe+#a^(AcFq_O(dshkHWNLRwR1ENuSLTKD(#G zxlDz!^-<55C|sgN8w1mw$gWZi1deo0GrF=X+!SLo1%GLjR~2b^0whAWg^k*10da(a zQP5@xV4 z2Ld5;bg+4zx_Orm>by9*yVs;70{EooX%S)^bN%3# zuDC`sV;jWQu{O$6a-d*A?V{DU#tViu(SE+6VrbTDRJI-S>+3&nRE5!%+MAJC%W~Wt zK19HF^Q@%}zcWTlRrFT=9>>a7C`Us5N88HNPyaM%V#iEDK+|zG29WPfG~0V8VfX7m zMuT%@HsMU9Thx=Oti&&qE<4ka(8|AC9#&-_hcuE{hS&<0WpiX)CVVO)6OC=sb;Ep9 zV^IkZWKP%M{Yvh2vxa>=f!!Cwpyz4w0)EEYSy)JNQB8pkIOFD|zl{QM{^(GtCc1zx zN_Y32x3z^zFCadV`oA;$FRD}mwK6tM36SU(Yl1lSUsEZtEq^p`hVsDNB>ZRViW+1r zfEnM2f%S)F3EEnpOJ+{qhVSi!grBna$+84gqL8w3g?;BH>g_rO1D<;1N%^?Lpqs)D;PMw$&>s}JAa#h z5+7MvLad`~7s>z}EI%II@SMBmq1S*-jvlVeP0re)*1^>3Bq6}26KH7aUCR$Wu$#2Eou zL|vv7ei5B{(i>)-0M2Y6l@MQa@?P%gsp#?QHvf&`!S7BmtM)n~Oyx>JjXbI52k-FA zedWGt6s*Bez$i6M5WM5W&rM0-yq`3GaehpEd{J8)c9~LMf7fMqDDmgj<<-jPv(RqM zNyQV3M~FV-&+3NSctq6k7@`FsUVsa28!xR%XQG(R93M#{_~|b=!SKsjW*ZcjH6;T z9V?b%VPy@;%VT8c+7|yMg+D489>R3n$&tb5X+@QESYA=J&^v{cVAbbB`-gLWX#qXl zO>-|-EL!;tvy_MF0bwryjc~B4s|7B2eiXx}J2){MCEAJ!q(z(8%;Py|+pUjhP{TFn zaa%dDSlvy@lvpzYl(1>?UZ7}+-V7V|*Le$}Ha*j5K*)b6t!no;q3>MJx)=KeG)_qk z75%=rK!K8|yLV#*D9G&y`ua>Gd^2IOz}nnYiFg14ssZB9!p#8X1gXxJqfF+V7#;e! zlL<4xDZ1;IhUs&Uf`Y}&+7roZoLzN4c`)+nt;BBOzoYw5cS0w zqrW8xMcNVt@g7p6GRX&#Fa$(2!cNdtQuOg?H#tBUdf(G|fkw3MQa>ibaLG*dqvQ^$ zUt_82ffofgI?3-UuT+@ctXc-V0m#@)IbxPlRWB@4324iiCUBYg=rR3m;{Luo$zzlD zNgK=nr3jQL+^oZ)iI_zRs#q|pcC*_b6O2_~v4sY35R)_tHnO(5qR%$ahKyGw$cnJW ziBBgYAz=O7D2g|poH58~vw}l+xfF(?+LoBhy(UZl)xHx4>>#{b*AB{1FKGk@Lt4T= zmN@{G7H|T2Fss{n8F9D-1jF)XICBzgPj(@Q_isX*GH{6JdTmTLG*mhq`nuh z#k}D5J*+EzIn;+U^gm@I-e2ee*Tf%$ap&97=f{7lJ5?jb2ZOqrq+^sYgOj-1CqwEu z3+V?K#8z((n!KK)jRswr0=~-VbZ6&gS=1p>GF#v%(&`Y653(jJlF~(It^{1Ob-%yV zIi2qq{V5;kg(qzZ2>r6PDa7I@qG ze7KzRIbk1dG9~L{kcmT(O=4C1*Qt$x;&a`OycJnaoIoo^fd+^H#|KX{wXUDk)TQl2 z&D|-@#;dd4z!LC}Dt?BV(iVAQ(Q@t5e%a=msl(;7^lKnfKve$cvE!WobGQ0JJ7lA{ zB$~;ogsI&79OZ*JWu@g*8n4n%UpvGK5o<0+*%FlN@^AKi1nIYSQZfaZ2oyX#Aq4~+ zn-Z+lE&J(R^Q)hw(}v{;OF}QNpQt_W?_Qs|T-Ps50db%Qi=WL}6w}AS5h{6XI?PZA zO76*I+AYT9y;q@3J0*3#5Oe>JsCR6yvune(+q7wH+qP}nYHZtW(Ac(Z+qRuF#*FPW zey@9N>sjxo`3tTw$2ia9*!OZvN$0uWIMG2}ZA>=5VjW#MXaZe!5Ar|D;#1T=z%K)X5B!lTP_Lg;?zly8r%(72c<(=P(bmX*#_0~OBC~pgNn)JQiQ1ZIQkQ>QuR<787DUCq}QO%G&YqNsg_kdwh)xn2ol>~=~>JV|FAd=Y@` zfFHs8=JsjG{I8!sRaeap1s`48d@Qn69ML3M@yCUX5RTL&%mXEZq9L-W-j7vgc8gZJ z{qbUW!^_jLMU9wPF2~m4!5&2q%U95vwz=|AunNV0T;CCVBKp2#_y)VR{SdD9`yMk! zJUVj&pX=FB9rRbvhJ*bJiN=z_Wj@(IiO(s4zUB)aChtR9xT92ce!!$_I-t>6I1{oi zLs018PUG$-Qwac5jb?yB&_m8g6~9TpW)HuMe39orc|Vg=`aqbXG2Y6t5L9Zv>z&jD zrXG(6Y~IK72#*KAPzl?nu%kp5mwL~FKE=Pt=!B9SQ!s{=f%qZ&mE2H!-o)1F`(5Q} z-X(jcfG4Eyqx}aN{TY%9AMzd{ls}AknC!r;0W@M?JsZx=21Yma`w5PPPAjabV;V_X zSr7_~Bynz*y6aDfBOCT9$q`o_{%(TL1Bg$23i)inyGn>0_Fb6@>(lF-Ka{GxjJnyx zFKNciku1}{bKql^Q68eheJMT9x|N%aB8Q+fWhG{KQrQm345i**W@`r0-7>AzYR`ky zThtpx-lX63Kqeam0*weYpKlU>-ybtDEv@4W^b{sHWD}>;^L8=k1574o+1#(^qGurs86h&bW<|K@ZX1-kapjVg#2&`{ukfukof;0CmR}p_MT|Vc`ZHkvtoz} z?swBGYQK53YmeSr9B+?_?r+I?=wPhdpq7W?$cD)nwq7&96LtB=^4p3X@w0!QL;!Z5 zgjDi~AdmQP!4g77OIP#s05h9^T!jl%u=h{9*L~kO-Cs~&v@-@ZQgD%TNYyi{3G+4@ zM`+5K?E8=bHx8aN2EBNG{ZBAaeyuWC1o-@e7q(1(H%Jk_tkF?09e0@osZyiK8dKV6 z10*SyltVWH*}`E)UiRqdNB(;^1er``(s-u9J*7b--m-)nI*KZT_#66R)U6z7ovrFf zaaBttEl7mNr@h;uI{?_o8tkcFuqJs z4wq!U%#<9`D~?ShiAI?8F^T45B;lYnE!4RjSnbmRjNCk|HET zO@6~=NJD-3&Fxa6-4Qu;vnvFrhB|>--vEpIQYMQnA~Nuw)pla)%mT&AzB_vQ(E8Y- zn_Bd)UAd#FWp2wwWHMvVU1gHI5xOaiVB~(PA|+^s4ff%YaAf7OsHV>RJBag-ntb_G z;7ya~Wjj9ZxrDg{&)UzQflqRckoG<{$_Li%#b(+Gf3qf+t4!W4RyNl;20I}np+H9Lc>|&CYIw4@$Ci$RmbUKYeO49PhD{W+4BvTajB9v4@y8&g^gvl*iBm; zv00D&SPb5Le9Rb`Lmzwu`4tzztfcE%T`idM<+Y5vZn;^`LA%ui`yfX&;S4w4aC3bx z@O3x7U`rMp*N61QXgWo|Nr*XRx(M<{$aRsO+Fdoj!TF=GChcMb*}Ve*u~9SPFBYMw zq?UK2%@RyK&}guiIp`Y>EA!{hPQ6+eV>+v^3>0E2e}(#(nG)sYiE3KtJ@pcF=ovH_ z!}hRHYkVX>nZ={9O>4B7w)rpeYCi2)c7#iCJ?dsr1+2)oNQLUeSeMi7m=NCU4QV=u zH+&MZC#jdj)+AC|b{R4$7oMoXkrEu;x@7XlDa}f-WrH~=>?nIcg`qPNxIqx7?}vne zUI<5y=d0eN^KKJ#R%M7#=?Gz*YfMI$^S>(`*XeBH(J|*-ir8y}Yy^+7vHT&0zG>x? zEnYA^r`4*1meHsZ13J%ToXKw8$NQ!<9AJ4NTMO7GN@_y8z)$M?4 za!$@IYQVVadBxv)9#Xh|1lVKlzRxP1PZc@4UHTuBe?{&;YJ9>GeBPaLpRf5`GP%G< zg>{prh-zVfZZ}sZhRkxu-YDy7MU?~AA`{xQm>>0CR;am>ZwgrIgh_dtoQ@$~76@&t zhqSYT8W=y;e=;qug&U>|zXQG`TU!YQYYD+FTcc(v0UI_si*$CwXDAIN59ICI_PH$;SOX$mmnbMg)BmU{A^tr-pVq#}?GN!l&NsdK)uQ1|vn0D$4ufm(J=y za}>3fuOxuejvqORjWU9aEYtjS99K}t1YX&+gF2VXEC`M!!1eT;=sVl56trO~{}sB; z8BCd6yIq~%b$~e33mpG|~;wDiPe~{Y9!3%6w{CCq?$gPQp-I2r`H!OnJ9i(61zc;@mzg zAq$)fiF`1UPxwfX3Pk{)dv+U`PAKeM|3|aFgdGkJi5x`1)3(;| zBF5R@c(0G0(Ewb+_HKR7%e3+Zrm5~M`q z4i14r9B=*-=^*z+5Vik$gZx#a3-(fGahSK&AM2!&M(4(Dsch$sX!wq5N~}Ta_i_UF zVkQ`zBx0Mcs3-gXsrFjyVJPcm653;bkXLDhQ3p2leFB0*P7;s=a0Obxa0XX#wk(|Cdh zN1@#|vD|rWii@Iqj=?JF=dnC6tPHfk|7=OzYt^9fB4bSay@63Aq(2YSoPnA;N2<(v zvNLfL3-?lvM0hQe14DA;OxBOQo&Uxw{*TPE!-A@Qu9cNfO;3p_Dn2d#`v}XdYKP%* z;#40F&E?9tp%?kU4~#!6Fq;qbtVAGp;cCau?4`ve|<{@4tQOU$k<1_Hu~!MK3ehl{TVWJ?1f z%SIN+)Y;z-oWIhFTr^f{h?t^yDW0rRhKHNb9ZqZeQ{;Gl1+E1``Ss8P##FzvTNAc! zV;>!P6l|a7f3YT0SwPE@)xQA$V`p@la>0yLku$G!zpxkf4P~3O6P_I8cPC$5d2&|? zGY32dfA-uDsf6$kk92H{+$}}S%RlZmAPSWJbhw~EgJy<;g-?K`uS+bjdPJ_=eqhD- zd_by;sHn@x`TV$gixX1O~Fx)8Euz|Dg zj^^>{|5hqmdv@L{LPi4oHYN`3L#L{o|2-zd@FHK;mHi8!(0#i$5TMWIiz zSE<@V^%wFNworZ^J9IMR=+yn^?5?7A!8)1Qg7^@1hgegoPG9CCp0o^aBV(INXdkci zRz_Sx=__tZkdZ5%vIVv*BEG@P(&RX;!}~mWm)c_jK5mU2TUk0hiNzATGspN7e^v&-gc2Hp?a@-x4=gMR}fxM)^iKY~PM)XSfB(m-DqAe4Bs*Kt}H9lAamTDJ8r`z5xc?KUoU=K_@aPU)4I< zEyHMo48B7NmRyq3MUV5--cbPby8qL4_9)I32* z5kfY%n`R85b+@OQa4~X!|1ISY74Ttr^ zD@$4ZY4A8NV}xO9=o1rTg~bmlpNg86j7D`Q$8N0&od1t~275TYJOC0Bx-^ZjPu{ex zjsISYq8yeW6?N)akV2n55S77U^3^Pf)K7iTj|z@?wK6-ULWlIHt}dNAt$wf=%wb-0 zy^j0Dt;Y|1UqL54{+T>X@uXP!n3Ia8DUKRrk5U2@)qN#R>Pwr+_*igbF;g^bv+4e~ zpa?}RHM$d7=u5`p`BmCwE!qZ$993Qjav1cxNE4D^5RZLJTpT9WJVF4TfYX<&&S&fM z&3FE4J?@a3I3cYUv-<+M_6SYncpV%IxAC0@u%uhnYDuMfuKWAP-Rs=~&fkxK7j;S0ta|0WaOupeGZ{=n!mICh+vfj%r$Mrv%8pEYS zJg;&;S=QjjS|j;=3y%(Q!d1le^)f6fky+=&${sLgTlx-Vog>hfn|_#8BH1>$Q> zb9Ylhrtg=Bf{kIRk0LSC@9RRW1PK@*Wg$=^+YqBq)lsHTCM0+W&zv3wctE%y!l5~ca*qO zIiBd@Ojtr@?A^k=Tsegc#}}8wVJIVWOG|kYGD=K12kRKv8l+IS4)HuMjfmqcn6JfX z{(G93Em0y6M-pi~4QY|cNAlUy%-p;4z`^3-zk$6dhoT*jVQlyN= z)4b>Lbv@2U^0Zo=m}qE8*oM&P;e=;`69*?Iw6VKBhyQPbLG|aU33&g02j`d= z;uuF3WZ0x4CU^fG4F|V#S_D&H+Zy??r59DK2u_R=i18Y<6S9V>Cs2h?qd_Y&(8%rm z&cqxi)JZ$iW#y&)mwtb=&jHHCDUmofj^{)iaL*S(n|BXSWy$Yuy0p7N2Uxa|QDBR3 zp-r=x8C|{wS-Foxc0Wu$nCs0=nqqRLZyU{S|4Vmpf(lCwk&&MVlP6?Z{Ett#)7u@R zdeUh>1JUYp05)GAnmrmxL~P0wZr*{TYy#y0gWI8iS00-()MmoZ&K?bTT<>ccA|pcu zRS8w7;}$PvY5sWB>1u)pYqC=>Psz{pXM^S=q{QSr$%vPlO0(H;?oz4-i-8R3V#5po zLg@)T>bb_we(q1X`5RGV^gcbJ#Nkdf9-p+62Odq*h82BY5iR^&mL#woBMo_p8$GgA zzNK6|p8k_ow+=d^`LY)XaK%ZgkM6YyyI;&?$pkqkk+1x6kUk`2m{?CY%;}txv`VzB zJPO6nh&xD@uws}nDy_EfJ@!`Z2Y&@55>S3}1(#$0Q$mUMn;C5tR z(5BO1heLh(b=)=1#?otS*_SgA& zbJBTIDe6&L-JX%FN2^HeCAaYdcFhAEc7v&A zTg^_VBpo*^L^>JCNlYW=C+UgstS7pC195w*S>JL-;Ud>K+PRtMGlx1K1o-HV)aIVn z0yh6QOKfXFWo_=;d1I0n$K`?$gq^{<0t;)~U|F!BxQH^ype>^bcav|H8PYz48r5wI z0QAsLB0spdHF=QW@BZ)o@E@<=lN<2;pzdZ^_y=pLrs|HU zuI~>^FfFbGRbWi#Hk}0H$MtD=;E|u-fd2w|m}^1f8(7n(r8N~p{or?|-U(vtZ1DI@ zh%xfV^yYju~emES}#xAJ@zY~JY0W9-%2%2GW#V>&*x8iQZ&=ENVD7 zO4=F_WvWnd;^Wdhnnf~Hu_8oi$f@dR1S!cKo?{HeUNmQlY*k1L=2HW~RUOw;SD*YJ zCjy^6yFJhLpFCbi?w?-(6#%x(icN35D^8u$fZ3#eGww|}_JMKCBb}F6mWy_%&V0^2 z%&U4%TqOVj24YH{BL#myjuVJybVzB+6;-su+MEGPj(WkWXHo3;pR6kU#^?)Gf(J>f zPqu_?qE+>a6ZcxqjJDz=)D>rlVM7m~;1gB>YVtYK@TGMxD@cus0xG2Bi|GAMl4_#X z)_M0#W+`*#HQQ7caB6>N?3(pnF&D3au&kbjZD_F@wdwT|mb{@GVLOf7Tmu9!&+bOY z=>2bFH*-jhEzP-IRZElh^!<4L#LoB*ry^_5Oue@!QJPI=c*~XRe*l=$ghz!$Bm!d) zAbVc0s2f^IH4HSCr(4{2asPH}x`kvpjk#CnBwLZ=N2l#(Ff_iDy39xtnm_?F#ksE@ zxLNJ;2o^t<+f#u92(y1p244P1hWcYJO*1%JLVx(%+@Rb++PsI3gQC2{?Y7;tMz_=L zxPj&5vJdBrG%V31186*mfT`{9&NgTFL+?E9Y=77LH{-@q^@;=@H}AHT;XIm11IMy( zAj1zge#(kUfW-{#peAYz)~h8H)i|bb4N0FEyk<*|0?xXGDKF@DZV$Y4e#yJdV;RlN zWz&3O=eP(MJSQeE>rB`~s5kMHht7G%u#b~W0sZ5;0SI7fAXfO=5r`*I(>r!$0lhy_ zrW53`Z9oNN1%?#|GQl-_ENQa6PO&C41PE?Cbc$0Vb+)FIEWm*hpQWpdfa2uY*7H`e z)BghK{NUH{lLMfIpp9?NM7i4vp!Zr@Gl<{Z4ll<-nY>P4syJ#Uz&Ow-)1V4clZIfX z7*$VH$Z6-1vj?6V%&##7{%v2Ue4a4;r-rhyw-YwA5$$o&!;i=%MiLW7k5fVtoG~jT z){@l?4a=d`c&Io6>J~5DjuH|b^v!L(N6+EArhn+oa4kx}n9xTiwHoR?Zj{w{??{~8 z(n{Ku-{;##amY=zR4cWG5*Pulkaiz_Q**lFYL z(QxsospbLP%BH_mU#SWH#uBTRho0a&C|V{abUIVF>UtF@pBAA*m8DFryBmJ&nF2Co zQV6I9<47?BXo(zde`;76Bw`G`{BoIqlfQ;GB~%7Gln5HW;RaurZU0_wkSUHuM^ z&OXUK8C~irA|!~SOyq#x?H4%#LB#Ai5mU3d};IJ z5H7h?*6^l8e<@r<`}uM)Sx^uZp}Qf z32&E>-$pmk1qmMm>_&AmWL@P`EYz72jHVwe+5n)M!J-0&&Pas!wA5ci~kU z=nWg1Wq~8(wnNeVmnNH4=+5hT8cix&Hd`~2@#k6PHEN9A5Gs<<&}*#bs(mZ`@A1+F zoc6>z1nECF458m-X0!T+O~?{*NcytwD8DaA(P3c~rNfyP>6&y-c<;0=lsG*1bD4}3 z$>G{$lL-YUXUYzn&sPz0m8P>HtOMOMZFjz6`vOywojV^n0!}HMA490* z)qfGN6Wz-n+np0*6Tw?$=>PXpdxG8y0tzG!tvK%fEuHeKl{{KMe$Tl8rZBvXh~f$i zCf->ZYoUfwnoco#N0chR+kv6lLafuPfoEs)>yHk5(3JisG5}D*r_T}y*s6Bp8{o{q zPVm?`vC%6!n2)ZRIvmWJC=QBJQhI!N%J1reTUF9JzFu0V1?{K!d8P@+g4^?EFKX1| zm`w_+0^Sw&>cPX8tZ)%s$_PWs$s*C!;y=aIRDW`N^*!o&+feHRye&FB#m@c}xNi^c z#<&+e46E@O1&l-wngodiIS*F3ggYF~Z;~|ufH#S?M(czbEa4k?uV_q_%j0 zH}l_OX8(RRwb^cxnbDS4)Z>#76HTQ}>>bSs9bv3+qzA+s;c)A2hFg0{p=!&9#L0m^ zm9h)TdF9gRqry-=`;)4;-)!=vlqtC3$qRqs9>7{2!3-21f#LEh7yfv-!!Vwh9!bPL zqL0lDtToCEy&PONGol_ZVD@e|*ecFiB3HDGWV>!?C3&{_bs<6jo<-_%QrZi-`b{s8 zg$}Hl{e#pA@|ntaqNO*6eC(G3co_=INUQ`>4b?)>w@N-mRn8ZezK`J$AMef0JZ?thS5oMGmRg%Ht&fg52vll!b z;{SNPQ&ZAH3AND|xUva~SqX%bNrj7^vA_E?^RkAAt0VvHN#^I$v3thNs+xV87F0?d zZZZ!XKfG_<7yYfCeWlUX7MbGPAgI5{ia(QspO)hB8!M@B0NGls7q z1>>7rwa{xJIHGrbfm~~y9DG%EYmD!%Qoc-!-WtM8^)iSK|L?Y{+V{$f5CZ{Q@Xvu` z^72s2{-nVY0OIfNtuAmn-ZKK5|2R;}E|$j59(SVN+bWKAMQA1_j>z2*%-_4Y5RccX zmAa#WC(~Ug~WHQMH z)0te96_hDK`HiXg_VH9ygbV4Wmfzz%z>(D!6zPD`ff!A#$I=fV9%l*E{H#50mTLB7 z^k32S-u6;zWzaKe)B&#Hu&1QzB4LU2AKn`^bLzc>diAP`s$l@pTxaskJgHTS$kuRV zICkp#_hyjA<3>h*K%?i~yYqhBTC>CKTk(>DL?%yB>q3?45Y#r1ubs^1!=cfr>6@0o zADBk{1{;<)(SU zAuldl?c`-sZ;`dd&z&oiv<@M&c z^$pf@mI2u%Jo#Obo@Axh#%bw+rU!)UQi{belQr*%pR2w-G0e)w%jpg41gHJGr&jU;* zuNx+xE?(+raS_N_q6YShmd>Cm)UH#k*rS1f-9~Hp8Aml{5X)p8#E+JrUlpZ(mJwuG zrZR~vGqeXX3qc!m)JS5?XAy>yp;LgrU(&YG<`!+F%@J*0c<+r0y{+`T(*SW#2FHgz z&&Zfm=W?~S<3acX5et4{_r%RjLFPGQd?((+K58~mNa|3J=)3VGnmU&;WK|8dvdBYR z32GJLd2nGVZSnEA(n^Ve^B~P;Gn8h54_ZC12kU=p?mh}J)4-1}fkM|c_+)kus#?jV06?se|SdpAGfae=cvETjLyjqiCV z21MxLVt7ATvpwFZDz#gL+({(%`biYwkCe#qy6W@6&Q@wh8fLow=*9?yVMRG3NvR%J z?EIo{jG7=}qAq$%N=kZBBuNh?K}N}L4_H&8t*vm93zg_Q_FPh>KZ9prw*w1}&>4f? zeCTqT`pNrn-T*k`G_FSrV)Co2rwfyMAlHdD4)dr#c?S|hdZJ5h3^o%9)kIO1$~;J` zd`DEMWzHtru27LRJOe$-EjQ)2YP$rEFQMv?ylL_q-ds?%X?tZa{4M6^VlW!9f3u~!iqYM*n+VMj+E`>=UP=$M<=9gUcH;e@7XT1}Z z6$brzYXf?=@`bYJVUe;#cQC1u4kXBKJ%wJd-6fWmcgi}#;mv5d=m%sb_e9R& z1cXVRyYg2<|9e>RUcz?H++BO*&T4yf{9zgF$~esIo_<8ngnQfgu8enyz1Y!A%Apy$D1}@yrCHTELq2 z{b;Bh^2B5+!lG%o_T5(^v~%aLK<_|o5xQ527xq?PL=doP&nf74Ib8!`-ro5NA<1)ajD zoWm?-B+V_#v9-^$LPee5EaXms(E=h`EVsPnPp6Ch4MQixuTpDLALI;s(G^k57WnGu z%Do(gF7PPt-xidVGQqkH(<3{q_vU#o;fg#DO}4Ock5^*aPI<*;btAvfr;^W@%b7cs zUxS#K-zX0wSDl&6`-oLTvp``XY>79K_lPRZv14+xD@rum#Ve ztT~;}YpH!2>SvW*EAV$lM(xUUTA!rks73Ojm`wc!kGZr$$AqbAGwO-7EFMsw>wHRg zt_U#ab!|ij0wf2GO3Nz+#fYO@_dy=c6I=)6s`x2$-hzY;KO_IpBRD4x1SZ?MxS#@| zN`N*&%?tt&>OQK{nUwjZoy|^?r2)u(zGnPZc!?{I``*Geh z^;O-0Shw6lOuXv@LcY6&?0#}Lp4{nkTo{lN^m_Q!d0SLt{N5}v%V^Iu9$13EOQh2X zA?fzgMSV!;O-lFf;lf)aeQ^?X$7p}UOsmr@J<)1V7Mo5Js2=8xc9<~e+wIDr)rL;9 zY&+OK#ZzlJLSMOFkN2ObES$}n(R|B`YJ|0H+R63~>Lj4}sqTK7Rh0AfV)Si;pceZt zD=y6ox~Q3set-ZisHv+63&gwbF1-&9WfRAVeaIjx2eMh5P7Qm}YEa~HMn4r+6=5Q;~RP2;hyF9Rt#`ZAkJvA|F$}o z+gzntOQBYA6;>~>s_d+}YsyiI7cN9hXV|2^aRsTA+EIaOFl|nZKCJi{tM$Js6>~9F z6xnI?OFykqFH>X4>cn5Bt@2J94vA^JRo$W2Tj_(+pZ9Yh*PfPGcO2onbZt2uJp`)t z`D5}f>B}_QqL05Jg^@91XS9b?UXA3ZB1@RUlFzkTP_f&t2iY>~lbU2ITb2!(qQ2Le zg=V&hUvyj+qmP=4Bhuk?S3h)Vo4$GdmZyA#( zCLEia*?99N7U7D)8S}DRN8hK?xjGsff!$FnDd}aXgQ^4K@GC`rr%qn6u+*MSu zM|$Vn+dHVJvsuDcop^|SqB~ciub06x?HcRa9u*`=uh#1aKsn+PcW@@+A*PMc99{OX zdA&-IKicq4JL7K+>!Y7N!1o>&>OgT6wRd6WjS49mYG)$rq0~)RNX4`62s9ObhDN_a zb$Cp4Tt=HNfc8?W=K=J5=kU#zdM|5BN*WWaLRSQextuNB;pj$-&}9tu*;Izdd4gAj z^vE!t!@JI2Li3D0wvR~0%717a(5~3(Z#nP^d4!l(_^uwMAuV;ZamThNg(C6UU+>T# zE4~i`p!>Oi;|mM48AEZSbAvgIA1kDWjKx~_x8mu3^!};i#gu-KNOI(Wwa*5SJwRzU z+l{2##u)dV%B4y!5+>sfIoR`jfO_6PjjjOo>&2<3l#$)#m~@g3`2yIqnGi{+>fVyQ zH-`Sl@>A_yT?teAF2+$o@v*S%0K?`)+0pzqTCE^l_fN=Fy#}QaM} z(}{v|_N{c~&o1m4flppN?+3NT6@>(`R?nrM7@$NIcRLmQfvoYu#lN*asLl=!Uq}kX zu@I3A^V5g-33{oGBj*FZnuZP;NhYV9g+M$zGPQsEKn@BwYoIjMWvZ%Tk(<%{v0rw8 zks3P&Int$p2_+KC9hr2%$iyCsgP{PL`FQA2HQg7Kh=@{zr3hq_o7zXLDIamxe?vYs zn-XJ=W0XKb^}9GT*pJn>%wQ&B$(}sUo-O%iIvQ#t(v`*8{z=lf)#^XjCj{sIkd#t{ zsk|MBNnNzf|9pOz%I8Z2#97-5Sf^T$S^0cn9T7S+wEmWeyndoSyQR!cad4WzR>WUT zO693AKj|ewx|KM585u}p?~%lfyTt~GR@(yr5vxP9&Id*r<#!}Q;-8659HPjjv+CPz55j#$35rTDEjOQd=5<~Gk;G8tt|ZC|83oB5w< zyWgU&_R27NLOsNa4iC0!Yr|~1j^d7dXfQo51vJ5?xu#8fePR>OM*a$70QTj8&$pgW z3BH`34z=Ncdx-^!l0Ub53aOAxTp^=uJ98L%{ZF6Q1O^Yo7ok#JH@v?wCMHWVNl4rO z0(3S5&ZE)A*)Kl8XE31uIh2$4u!og6)|8?<=0=gk>3iVpz!dloHU4(BSwao&kWSCv z_d4d2iT!FLEEtQ0jMFMw(NI~cpvnA*(i9lUBb7*^;tEcB;&m2NC}uJ9kTcG^cdz>9Lq z)#bDg_3>^vP)>>r`~6#p84*2Mmu-U$ZeMr!*hhMM?s-mW^?D=~hxkQnzc5TLMnutX zmRG0KnifN>+3xo3zZLnzC{?#EX#zI$r|;tjOKUu-49XC{4pdc~^*;{WuTOdA^WGq_X8K_$TETYAQJ58E41jG;crCz*Qsg1QS$%?Lr?zRZN7s~p^ z9{dtLekf=i2!TW*77az5LEMEuLIi~FEpxhjPAU_39BqGEz0ZE|zh8TMJ)cM%U&RGE zuAS36Jqcd|7qkzDVY&FIlTD#ENY;oeT2mtA2tsTo0^xS&C;Ik|4#yVvFAsNXYHbNw zxDqP|cOFmfJ$)Bv8nFj7&FGW8)!37u6dM#<8Rg~*6 zUbp?Tgn6s9j2&29Y|M^ZTVJm@ve3}b$gA$w`z{Y`YG(F{1cG?+5u!twqL{_hL>eLM z?$cz^$8Mqddj5TM{gxy}(X6v#^8xx|ke~ZG?=YRWFABA;NBFe5O+Ox{?&3qac8fIhCA=4Sy+eDm^i6psetwUDZb)T}=0?u@SI5G~ zU(l&6z^%4E8yI|u&dSzO?w>`#N5Vk1Hl#1-$WiJWQCwDDCZgjZdT$)eyS<98c(#7- zfQ&#F_Ohys_D5*=+OWM00YfwKUTQ}i;s`nWAxw6Bd)F(4C$ntB)dBejIFp+imz0(k z#V6?V&A#@vR|x2*iLD3KbVFEP{IV{wys%!W!pLu{{sVBiLgi0VrsUv&SVaCMa%MVX zhin#VH}8t2LVEs*&KR3_4q7=YrIXKz2K1fjq#sO=
~ZJvOwbW6hA4Bc^jQrQ{$_m5bBdVC&!d^K+nJ`;Cw7p z#Gh}BCRq3S^$T0Xn~zx^zpqPMHx(Bv`AZsuZLoM7DLj@weHPrUtUojci-t@aNDXM< z!Zcs4#(3Jom_&mzz{v$56i!eDp=z`kpHgGMl4A$v$E2{*PzY>q{rdkMGXi4e8jznv z?4%8d*u!XkZ`2=4s%uie6|-X5PVlwA=vOyy0q23HLv(IZGelpbnnTDPQzYC5hOci3 zi{V=TP4g@)Zrv4A(8H0EIvm{JZfA_OHJ*Dolwjv-L;#b|rFzJ{Oz^IpkkIP!NZZZj zBO8-EKGu}YtjK;?T7)8FNI>cEedlc`ktwsXd^j1Ps`XFQoZ798r~kOnw~MK!K3oE3 z%qO^vE2WjjY+X4!2U#gZR`Mx z$kx>47IJ5&y38Skm&&BnI>0sBq}YzQZ9mEHBOLgD4j1!p&Jf7NgDgK{sCGO%H`G>F z)*~9sr+1FyYUZ|AMg~xKFG!nfTQ&K0a zOmO+UzqS6p;{O5h5+|cz=w$SrqrH0X;~igC;a|;B2d&Em_8-tBnS6fdkEyD=I)@wN z#l;npqy(?j;bOA6YZW9hShPI~tTa+T2kWSz1PdFxp=G>|x=#QfK-&)hMuRKON(YUl z3t*XD3(jH7CQvB8IGVCx;@}StMPOWymE`PYxo`D_p-{{^KUFVIG!`SMH#IC2K3EFL z(APVMpkf@a)|Xz^PE(94vDCmZe9qI+U;RHU$6mA9xKEJQKJ78pcW+h2@)+*c<=p2H=j4&1u2}m)eOIZ3@ z`~gwAKGqQgwdZ&7Sj=QebdfDT$dD@#hlGEI;E}Ap1lSV}$W=;3N%hE>g1+z!CGH@f;Ebkh#vF z`0{%JNOiS+4K)=SZ^CNOI}gl)tneGt=mckKcDg9}0Lz1IO{4L&Xf|GS)>o7;o@_x| zT|Dff3u0z+Tvq&$nxZQh&g`=DeI%u(2iN&e>cRKW7We%;(??n>B3jv((YHJNwh%gNVYKXDlY`rYf;Dh4G)`bX8pPzN~v`{V{dF} zv4$xj|867DIb#Y^o*qt!jGJx*P39$30T z%A>~o+j#5&S}jELl>qF`>6%1&Ek!G4j~?U^_c0WLv&x(XMa*>KURX->0yW2aS-O~l zWo*Y!d}6)tRf?{V?krSvb$XZ6CLFjI0Iv2YzNJwNE2aTS%l|p8EynF;h4B&_Rx!{l zu96!gHO9fIh1Ytw1A66bV{r)LyO$>C|3}n2hS%Li-QI1?#@kZ z@7P9Tr?K(w`#jG%?}vQf*Oj@}f37*l7(W4lF#3dfm_S`0(3in6v^iWvits!$l8=I_h zBKVTMEQg{QiBO$HtOaVN`5ON(z|V2Zc6u42X)|wc7%#`2bjqyxp94uWe=KPKB?Sb;<#xK1ZZD=?DR%WuKsL$LzYP>?CC;?IbJH}O_y*qMOG7g zVy56v4fhSb(p8hby%`8C3u9W4{+{#;U(~b4XnZjwDyUPG9o}Yh4M*y1P??Fc1V9;4 znm-c$K&H~ZSdx!4<)(3&?@DsIG~XwAc+twLCoxsNah-rb6%lkv2iX(GV%c#wCM~o= zu+OSU*4UPfuSf32+eG39#&53semY`dXw(^|YBoSEQ`9z~Oc&2)*bAVn_9)9TnJ_<^Bi;(_69NDer~iLi3F+7jQFRi zBTwp^8`Dd3RWYi6ZC?%LBTCP(vW7++IgximZOK1=Wn3*uivmo$*T3MuD}j~5Fg%zG zWWqmn(rXG&z0^lXUII>7TVc=+LJUv&o{q z8JmOZD~l)7J}rX>i@#~ryMI%xE>yeMDSg*u&xn|is;^xBJb`hApATX7!`CDtigg9W zNyQZh78qrRq#d1c!2FUT;Tkmh0JB(#(70`N?iaOB^b_cL8H7gSWhc)k`CNqn`*Tb6 z_qZ^1M=hKtDlx6UUF?6_B4m=D1Q;P)?7b{8r*xlv`j|+6#t@LfW-kTAS@U!H#0*)f zUrm6tv}n{1&!vahdX23L8nB3XCa=1G*SXT2b6`O=@}g?T2;I(8iz23h?`VNw{(&(a z1-Ix$-`}ql7%B9UA~Z67IN{uU&MWxxm*D;ASV(N9mhqsRIz^mH2ws6vyhWX|QdB0f zqH=HqB$Yk>TKFQgYq=2i8RU-=qexYWOp(YUSM|^kjM?UEb-BMwxaNAD>$?N}bXsJzlS*IeJN@4MDnPC+|_0Ps)tq{P|2#J=@?)@YsDz_C81S!II8o6o2blyg7#6 zom77-0Hr-`Z0Z5e&*U2^wsl+VK&-heCzvv@dQGhOi#KQjYsSRfT6s@e2OhI}q@<`H z8V6X99vUcEVH`JRq@piU_$x@oW>un2*z9Z#*LKcGlZ>dz+K@8%SqARqI0R02QEyWb zGojc8Ziw{j-lOv#=1Q6K(;ZJRJ9HO!^a9nZ%B=> zd5sR1k*)S-*(kOUblHOeW_BaeQ-Q@1c!pF2T}DRzB9#zsWTlF`k)V|ju6M;ranLXh z^cH_m8v?_n+)dy|?^kbw>w>5H;^O&ejkaZ+4Q{o#$go_~(b^fllA=g`W2pnk*mLD+ zG!Xdy^(o|XACtiB{L})G*%qz?8xFVZg3h6Ecm3ZyaHqlH>HFf0omjZhsA;G52D8vY z>zdNq)s@1}nwC~1z|ib{Iln3Scy`{1UhfO!_Ve(J^Fay{g*;RvUHSE`g}drm{}@=>Ylk^0XcLT@u)gst_t65@41UAi6j z_PSz}RAC?^?eKv|?(GffPR~=hWBkS7hymS7GJwmo+g_iR43J^1W6T-^l2w z%fBPU_lw?lD*v0^H|#ba73`DB1Jh*t07!VW-+XN+v_+E>1HDx(-|Ih4%AcVFZxb36 zuV9duFf$+4p>n4%)JP zSsm#jIu1vnuCvWl{~Mt|ey;VtuV^>;bGW)1rKEG-Y-Dr|nQV=(H9qa3 z_lFD7tZH6>Q{s_v*(D?|q<)WeiYFS`=>5PD{Q7GUixI${=yA2)#Eu~KM~0}h7E}Y( z#)7!iPi4MNBu_%BEd8w_x$ZlD(n)a94^Qap%lxMs)TmxLjcA0Dl=R3z^*Z#O zorJ?;hmvRd+&slnGQDguSnWB6tTF1u)QG~Ko)A4hXA&AcRU5U~okqgWE@iZMAP%lb z&MKPUQS~r`*R0Wr*kbC6>_~s9n&l*#;gSP0kR2Znp5SK;_ckBRyJF0pOMrS@OMuEQ zO)|3wd{_|n7ufZ5|(}js|2=AK9Tg zcV(eFB{Ys^xO{_gr|$?`9fYw`g7GU9E*tFWRCirl5*@Lia42llc57Sx+aiN~Io{E? zj>F4mYS5(FDx(2!*O^0nc->boD{^}G&Mx&2*)$^G-wayYwbu{!<@)q z6k#Py>9F`ho|kN}b^01*%aiK|7{Z0gE<< zFS4JAm5;m-uu`axJ+s1D)k0?5GLdh9hs7a(G1$=p@`CN$8;Jgse&pqBW#aBfAZ)em z*DDw$llo%50kWjlL8(VR8hKm^Cs&q1m5wc_Tbsl9BAV3C#v)#Z)feIQRb|8D&;U@( z;(xRU=O@Y5(6w=Oh(l-d!syWw0CVCZcYPdNR{EL*o$SpjF_K#V^N?FD&nVJ%XPi?! zAgpk^Q(C5%BS;jih3YHVnNf>wgruj2svSywnL}2G^E84~=U5jr>L^txesabOnpO+c zb1&LiL7f6!+>N?}t1}o2T8|lTv)J`y_t$hYA;;IW3098}bZ4noewVr;f(F)fMZl5~ z*6z6xtYY!AWDq!TthC%EiwN;I(RAs+LgdG50*i3`!#-xjXRCsKJ#C>Je?Li7Loro(r%hw4ly72Z<(5 zd?)SnBK=c|>JPaOGtIjOSbdG#{!EAC*jNU|V6lgk^p5NS2XxFHK}C%XHGP$Wd)@XkzTJGV~gYF{}%10fsC8-L^%&Vo%=Un)e6+|9f^JGG1?O|^_4*k`~{PB zUXpxj+J3@0FWzYJ#`y8mOv4~V(0Tk;Qqts*flwW@*;|O?IT>CYJ=@}nR4UnTp3tfhSKW*pPMT1?u@zQxs`l|3Dkd?-h+JMQb_1=@pV!Zy zBfbu18a!4Ae={1yTN|W=Qjw$Sh+9i0Oa806Q0R0;EiwWDWWy~%@f8|aB8}dny+=C% z53C)buKWB)A>%uJ4y_hw2W7ML9(7u`X%TjX0d>v!t0P z%7|}~0OnvYB)mJ7NAYiz1c3uf8%?AbEqNty^ZiCRnDh5;Boa)RKkLO{>0h2#N zJHJh@Vuxr4p9Xh8i4JF#2DT9em z<)_qWY1`_}5Rr~Y8pgOdZOvI`q|yf#vi9a0hYhzZtP6|%`v-YJqBw|DV$+{BEXC_5 zM_qMF-w1fBD+dd@di*@wdT`}s+S(_ZJb41FOolA*I$O%XWOQZt(h{IE2A70cP(}os z)58dxUG;sTt)8B%s+r@1o*^(?zt2CaCJWWO)Ed0I=bNc_4AC*Jw0h^R@Z-RvI(nwB z!z3UG5qPQG)neYMXoj~XnMLhsKUelJQBy}H)0H~;xigmn=rf4)jugUU?}RyU_|F7V zoM)fXN*Z6j56Dy2K5_H5T5s_8bp1EH`9B*Hk|U^Xn+TX2`9fdBPT#+#`N#5{9IYV5 zHlp|C1Ci;=xMBt8!uIRAudp;mrv-|}p623mu|q%U#bz@RQ`bE%r~O*|*KXiby~a(K z*RY!PTb;j(DpVA(4 z_E2eorX}w3SqPyy4S&w@AJd!p!wNflu$d4JICvw5eR)wVp6vk|>|1B}JyYv>z#rXM@vg*zvc`}(&dz!<#f-&-(6t^YADWhS|8GKPl@YF<6jdDo^ z)Iv((s-M%jVPN_U`k*IaIbt#S&F*bUFFf7tzNbz+yr=Ie{QFOR`Ghs*k8xxSO~x&G z^z^%a7+TGICjFR1*@qC~lF6Xk&irEXTR-&ci7KLmM(1d&@)NRzES~3Uu_a3X-`O%} z``&9v=(><>J~@U8FEx61o=w_oUxmwoB z9z1UAm`3bg@cd=uHHN#RAOQb))1NTDUaYYbnKRXDqoLIg&f0D@=^oBeMZ zb5<-_R^)~s(m?9JBog_w)=c&E`1rWfMgp~k1=qN79v3)oyAPc=Q2QrWvqV@R^}UlO zZR%Z4+D{!A06p48P$dCM1EyRdBMnvg>ig!n-BlQEb!c)7_u1j&r@8v52KPT@_}?&5 znz_0SnIxa2t)L)2xkDZRL66RBl-pCtX7k%$9cS*7?D%Q(K zjjPRBobD)Bu;`(c-?1Dq&wUQ=Ib7Ys9Ye>V8A(HAsale*qS1ZQat-8PR@P=vwuS*n zq;XD|!~7}jKZn#XEIb?SNN0j^_+#FKO+t@srgckBFGd(pWOOBMsA1`dM?;a+Rc+)I z6zFUoe6!xrD`diAG-rPx6*v*~qs}^Ru6s$dw!K)rgP9+$G+M}ffbA**@iuV?LMsJG zG+ryEzU>{;0BiCmS?a|Ir0cr^)%6cZTQj)?yi4&l2m)L`_^P70Avs35Q;KDN~J7-L8@me_cTIXFI-!K~^oG3$_cU761vD4JHX>v53CYz1_KueReRg-e=~=SEve zCdi$IqUweEQJ06gMlP+GoK|Ug@1|)rn7_D!BF}LxLMGHut5GW=^D)`+cBRy0GNCbS zLf2^$Lw)#G?x|C|&PrmH@6{tH($|yAa~n+hW=seDNA#eB0sMf6Pb6TvysJ?5mFxgu2qnT;&Xp4zo#zkH?Hjt z@4C|Vu2J6M-|(5$viijr!UJDcMN*0KXmxr%7nvCAQz=~K;?bpR>cOKbG!f*}&g<%- zRfd-P+ao{1{vc_p3>**-7+Vah{5T!ZtUT%yR60~kU5W8lEps!((l#YB)T4$p_qeU< zB@sB2j*Kn`0$obx{r?WYaqa$K{CtA6-(Y>jY#+HLQKigFGCfPv{Cu}`^-QqzhL8c6 z6COZI(9u;7(KzbSBEY|D50)@>axLbA0BpAo1&&#-{XcQFJAMy=I+Y}}F>$5hkp64IqM->}BE1;19h>?1_B?uPr*GhO``vfdMs@I-W) zaOt95Xw?z*9x4}2OjikWlpb&h%>jPB!Q~BPB<_axK#a={ptp3L_tysS%FU?-)5Mgb zG9Pk$M1BDM?NuYcgDF_XnE%a8Dlzz@!tSsP?>|D8$s!7Eq+DBX_Z)J{>6psS-rW`W~vz z=ag~$ibf1?WkHXaOpZj6a=?e6CVjP>ptehop>yOpA*UP^4C11wLfj-qFEnOO5YswL z7Z$-;wFIqlM6<{fV1>BUWMzDo)n~xFwERUc8Qd`wcEudG*oS4&Z4jcCVW;Br@K|S9 z6^^Z>jB@4&S05T`>7f|Njvq!N9m{i_7hPUAupm@Q*BWF5>BY znw8JIGm8gFsj;zAM(_A55D4r4@s|9}a>pcl&%FBW;}$f`x>DTt%iDM8xv#)#ZE;NX~uYo*mAJC-GxkMfbPA~VKx2BU%S%0soZ zg3`Et-%7~)$+SD!cnL?#KgMVacTX0BLAy8YRncrt1l4bQi|D4eBtKQSxeB_A!RNd; z5&ZEKA=>aFP_tHHB$)4tSVkqKoQvOh74e0tq{>Un%M+W47R@(Me|Q`pP{s@cqortr z*Q01@;+@S-MG^aDO&`<|PAQOG+~|`}Z%p@xAC8tt!-RY`c;QG*Bp@{uG3}%@)k|?s zo;3KJe=vuyIc%t(OrCe8X0Tri@G~RuU5$RLgCOaQSAIfNAno`{Q>SSHDdS4qz>RI$ zX+4&p^NAE_;NTzkp$9r4MrFj4V(=t76=#Dn!flm!WpG7_IWZg|aF`9#SDTpe!}i8a zKXJ$hvIwKect~?AjVrY^4Jh?!Qxzs^2?mnXdU={N@nzcsycu^5-jB->=kFv`-~}Kg z1>=tw7a>>|Qm7{s$qdsaM5ztaQP{MEU1+>S_eN!smot4Hv{3n;wns|y%~ywk~AI<3sK&Z zo2r62O(q_}JkmvdPU>l~I)6kvlfgU91^=8r7*0a6d?u*z0l6qRuX_4qId{bXCSy(1`E$sV`)>%}g zi?OJ$X=%=om;ou1&*w|#B959?QR5^z5nOt**?<8Zc#U@9bHh=y)&Vc4SvMTN_156H zr90{5C`_8XvNg2@%1+t~YsS9lL=q^`?vtRw`19#IxEWiWqIqUCTvJmiwJ|WP{o5YW z_8f0`21;67iA27WL%~!EYW(v%OgLYs+~uYH?`YIt)x!9b@g$qgIyxFL!*c0nD|H{< zmw$*rnUi_ewuaOX8AGWxC*FxrGjR&i0bX@$KRwP{rQb0ssz9^Gb)E(F&zU#^wak1d> zYf{HEW=v&C+4!ReW8WylUzvI2&xX-$PCgN`@iEo*63Zf9!=RW2sM*=6cg6OELS*QiE9XRFV%FO>GTw>sOL9}(gS zKH&nMu80K$Y+kVzR(}&-954_5qNX4B`ldL7+9XID8b(Lx^otu$V`=ehwD5S!Nvf!8 zygE&_o##t+cU%h~Umck>VQTM=eLUkI;-rW#v62>(iI11u_$zs$#KupkTowQS?P5jw ze-wS4?R*X!Y5RfXu;^W3E5lh*mKn5IKJUizVf6OSo2Fb=dVI;m z@PC?#tc{Q(LaR?jE*iOULF25o+e7VMfWY3S%F*83Z_Q8Yzz3}DJ+o)Ld2&;gVr<-q zq}(lRB`^ghG$ZIRXrsTDFF_6a?wXhY(N8YgnAP_L^_4t6RlMdt$*u(bqyCMdG$1F76!Us{$ zWh`jL+|&eA7tpZVc0%;FR-BK^4n&gQ|MBAR_kQznL_2;&q}x$o2?I4b{aGng|9QS+ z?|0HBLGmLEk;CQ!5F`EnFaTtGZBo|8A574adi%+h;BJeGct``d$vnnfwmlx2(rwJG zg-3gSz+di5I1ix1maxz`u~S+?9J&VB*fve2$zoH9l9Jd3|>JD8UsWto}2hw{dUP`hFZpHUmC{6}Rl8_oZyu(1}+ zx(7e{XPXDKYVbx@`X18E>d9ol9kEazZ{{z2#0QXdY|a{z`lL7L(<+Ww);ldUhRe?%wlRnu;qcx>{p+KX^%voM#I^t3 zAoPN^j?F79JTT;@!pUZMKCQaZe@Rz;q8oaLbHC04OT%nV0e*uvXSr3;ajPu|kYply zrQ(g*IpP9)Fp7Qe{ym?hEXv7#ks_y)E*niPWxYeDoygYSKGl!Z2JI34!Gg4`;Sde` zG2RV1R%`rg?k_ibrtVC-E6!$y-9nlimh=9)M#;zlt`$)(8zZn4a(9z5d|kd&I?HaZ z#T$onEP#;9###URnJT~7;VLHDC+t})*fXRd>i=9GLvG>~&OdH)O&qPJ9BRAIcNOaB z9beYn9Sj7<>1gja$41I9FSeVJ;4vAJB;btd(Z_SPaxK4;w9Y>sMe&jwa8b(vjA?@~ zbxs(Jdcf>f>V^kExt^nL)D-o=ITQcK8)$Cd6S;d20}RQaEr2Gu8Hw1y=Dc10?VwvR zUwTbnxIWp|)&jT{>RjlWftNjcxZ`gsD8z?z1`ikX^S`{!VZ6F- zLJ~ygi?yZI6)S;k6yTq-_h_yrwoscQs)C$dnfe{U&(j3V#jtV+3DHC{25|uL`e;;ZE@0<1SLFMi&~o86uoLYJG-PJrt3w+?m=5 z(R=Kh5@TA6Zl^K`kB=3>2Y?xe5=u!N+WWuy-Zc>Wr3*Bh|GMiz#AKg6?s%AA`%*n4 zun9k)PwZg%Oh1O-btj9B_Q?l_7P(CcdG6DCTDAf{aLZIBO$Imlx#t$?oyQK6B^2k~ zce;W=d78VETvXRnze9KMJU&%LoG@h?SFK6(%JRV>lUQTj`>enbW z^~QLRwlio->kRorxLIx$&PUKPFE-+jh%2qn=cRsd&hOe@>f8xPNHTeb{k2z&2*6xm z0w62Mkh+tUIP$h}lKcJ7m)mBf6ls>YnHxyhzFEp=_+U+#98%&^ldBUu;BuWyjI+*I zW3gAkFj3CJyP8l}jdk;o@yodFD?eYwj&MqrA7wGt0e<|0xxbV#*>&pgsMSlliiAR5 zPu$S&S4`w$ZQ4GuXVy%(;~1K!+xpw(Y zdcFkR%*@Q${XdS|?Qu1eF+PBTAS|C#Dn|H-tY$6da1IKh512ypM4&k{{S$6ieHPWq zCJ0_5oCnX<$akaglWa#h_1YI%ziaLIKy+|cAANdR7UHs*l(l*w3#Q3fXd3vCOLRL? zGC$8~*5ydB-YNj~2vS8(8ZoBD3ynZ$Rb;YV?tg7BO0b|_ zXy`6z^Y6)2P4~uJj&AoUiH0-f?7+`EgO6;-tt9&{sA z3%%2%d(@>#NW2XObAHucYd8M48!5G`}g7!s5YybS2*_v(x8)?AYO zxP#~ueJ>F#n&kkb zOVHdE;quy@N%>r#T?~fWEp*|}rUKMv=MQZS$L`elL>jrlpW)`HsO?l-r7wG?ARVGK zEAB1BEx{~Jp&63f44$py;^3mlD=5mg*YJkHt75KU=v~(EJhG@_MoNWxp@BqTl~NT$ z`%8N>08tD4^C?t2-Lu&Tql9u%96Ai|ndtTrKNwe?B?5CbwUd9{F=kRfvbKh*oISmT z6;-i#b0POxKcOR_m{)gV3WER$bPpI=q8}gFC~7hngCVBLCzvT$B-sOY{{HA$^a&>{ zRX@QX_*Xd)YnU~u0nX00rU+zWA=v0R)GNk93csjx*a&dA4m|+$DVg*+v(yQTe;J)= z?fww0`hz=@&bf<=kTsS}k4o-N5=?KJIE`k+S=lQ=$sTw&GBt0EWCjXWgBDO)Oojgp z6CQ(_sE@gF#+6E7v<1}U&RLPK_hWO3@NlzJtJ=ZS?#Q#CP~Fg#e>^mOGHR>*^?o$= zy!fJr-%&4ArRCs=2i-$|KfJd4+MN`M1z70sh{>)CNs3(&V#1=pZ=q_~NId$@ia{LT zIwZ}MG*zLlA99I?)i}ed-wDSSAvy`B6Kb3(g8{U$%KYKH?T$Wh$K$j~e-JDq*j}!q zP0oJ0;T&4Q2uWt8@OJqW;|&gq`J%_u=IA(a!Y7Ah^-HhQomeP{T@gl*y2O^U(QI~l zVac=~wT$N)sHw%#r>&DB?VJ@MP}bqerI(u#fUGyk&Nqa(Mx@N~g;MI=Lg?Xk-TJ-h zb=n%LyYklbwcj`+E8PM%YKy?YSu-9Uv&=$QjqTaGTVhVNpUZYw&9N?I#`6m@76a0e z8pNKOYnrI`gSn9&!#RAG$`1Fium~8R% zP#EeD8~d|E-!tdSG`YQ41nAn*UADr8*t9C0mkFlTx!oezFtEUyH4lo6=<7uB(Uv3V ztzVGM?$RArTimcftCT1YJkCP52i+ROPC~ok9?uWT8kO~mk}D7PxEvEZE^I!p96XCn zs1Ifen;@a6uQ`}pxUl^xC( zXE6D)*ziNQ!ipu|o~HUmMzB5irGd~390~M2r@PaB|38J+a%P!bCzXxq?%A2K})55GN_B z)2}(1isngK7DsLVP?cR`dNI{0gZYw(?TByZ3TPa~20fZo?wk%-Tb(cC%l!pR!fhc; z9ja^Y;nv;(?|!=9{MddI&|T>OPlAn34Jpy-7tWhmd#s6ou|42j*lzsx5ErMa*dsx< zjhb-i`L2x={ml)l4CYzL&N{;qpew|hYG#3b(HjB6sqKEW?j)YC8^Fq)H?m#P+q-T3 z7Ui|;(?Ol@A&AK^-9M_;?sSRqX`o%OiUC z7x2`%TR*IBce^Yvj%2F^q{h*;Hda?F?yKKk8>B;1Sl0xHiL%q5&!3`I4}`Ch)fj7! zhu9+T+}+%o1^*t-8O55^*)Z0wOd#-k#_~M1FAV!x`$zS0hvyd!=nQk{#|^xE2i0X= zl+AhC6ICPkINdl1WEIFam;wLq``ilcwNT6@e7k=YI^;fX^$;_AIdH!dQ};*=M8aBEm%b5W zLD3nbte{GlI8gp)kjv+T?(}(-@d^jf#U$_znQ@q7OGoB(dhNvUppWu)5ctva3VyNb zhg=JvUa?myk1?kYcB7f+B9kvJ3ibQ+hm}{!NG`^-pe$W34i|Abh!wC`z)~Xkvd$#b zr=g`4F%nKW`A<6%G6s_@KQ+u(zJz@^D{P`Q^e3`9x1W@4sxo(uM5disFr^$50ENa+ z0^_mA8M*U`U}!n7vr!at=$-j+etJo}(U$=9mArmU0(}JtjHW|>2 z+_}Zjo@+;?(}MHx#8tBn3&ruH(uA4QS8U?9snhP31YTnpe%B>+Wzey)9+m}~4ZD_> zjX;%@QMx=%a=n_+YHT(zb<`nOG=urkN2jOzkp8o+(Hmv6uLjegz+4|z=QKs4&4p(f z94sh#N@22i05?|WmLs!LOF8NF!U8GzB!6Yvd?@4g>xcdp28DXN^XS8AHL??+h_v3( zi88A-`YGZWROjV0_GLFa!;3S@9`G2*n!UQEkaQsOJYS-*^E^rJ$pm~Wf;;w^QQoD$ z_LkAB_9tb;xX$Hr@-!L^usH|butX8Nm1*?wqYn?T$Y=u0uNdnqh6W_$W*0Yuy?w&c zwT{&#Onzzju`qq_PL&N6fa4cLpIReOni*tj1SqSF45YB?v3omq*lXSnT-)NahRTXyTC?ag2LLlFDNphDy+wye23*{cZ(`>ewq^9l^| zc$Y{zN3b0hZc2Jm77Jh|Ol)E;B&a@aw%0n*DvQ(*9hT0o-8}terA!N_oHK5;`IW~@HjclLEW84>L@_4| zlH$!_C%ZZga0zfv|J&(Jh+?@T?xTeL`Cug+xT3%QL~n*6!7z=!hqHkOGV&0u6fZxI zV9mH&2AUW}iWf=l+V9)Vf3tLlXOeW8gf_FJomktN34=RER>I*W9H9K49s3N*=az0H z@(!4{-_(Y0!hz$M5jJj7?=}gfV=}q8V{Y5qRPrnAji7~PE)-BuJ(T#YEXAql)Fp#f=9^a6mW(1O|F7%S58 zlwp&DNP$?#AY#2ta}j1~#!kw?Er*asRV2BChAOICAJY;8amtiaMw=|T$y;%8kxWM~ zqDm4L%`1#v-|jiOF7%GxH9t*Tn8SlmLr(YVuhQ}&ZQ4qV-h8r_MhdbI+%IAc*=>!I z4oMa~6^0j$yZy|irB_YiWTLH9K^clv=oJE(b?}luMU)vemTS1NeMaXmd7-qwEc_SL zb*v;#Mfr8--hEXh%9G#RE7@ceQC*K~$kCN2p>|g~3bPzXr(PgcEgCd zq4gd&`mF|IX_GHuqJNyb&yXq0@0O|2_ZCh8*~oDew{6<<_kL$MNzU)U-_eyRlZ)h6 zTRm}nT#iM(PlBooDY{fw^zMcM`WqeZ>Nqrl;nkId`qPIwi%Jzz zBxV{5Zm&m#I(0A+H_28Bj?6b4E$LAO5x$t$OkpjLKYmX;E$mn3f^8%MbHtZ> zdJ&6T5t%3v{c)YULc59}1=3(xK49QF?lWu6ArKYr8XWg61DeeNZ(!mFpjfBpiM9tj z*}n$ZM4EO#JpB({u?cYd(%_G;cm4kTogaqBCcsG-v{(1DL_lT#__W+)ygYFv*|fosvVcy{C7P6oGF;x8EHb8%riZ%Zrf8hT;H6TIop zOc14T(xklg`%}j0Q-+Dt)7~kTT>IkwU&AEIUQ*v5El?%n2Frm%zd}aAjJQo8G=l?^ z>1Q|RMKhqA@{NznXfv%Iw>tgs%9ZkF>-VfwQ>2xYNCw=i(ip=`VaJsXbr|3a9IQch z?xP<%E^6dwH$fsJ?oq4%w)Wj~oABaPAlik%T@W0z$;Fm8_W4rc89y+cu#)L}AF*nrDSbUE_WXLk!ua%-u=0DpSgXp2`R3~`Wo-pwMB3stH@!F&X0)@ZUTrf7?t8n3UE@3xyy|m zMf^zo8HZh>Um&)oohY$QQ)|NC(IqYR%kLffRjJ<#j^Wg>_~*$ir*)6Svd(N5x~jO7 zvFipbVGJUT8)$?Q6-%9;9vSqz-M_awc~1N>fdh)8-%u;@|5-uDk(M>YLqh^yu>7rB z&18cgB9WJHqs(~{ozG&2dVQVU@<0rD`ga?A%;sAWNm-;e1VUqs-xo)7cpx6x>s7i3 z9=9T;Z3B3uk4hsl*GXK*P~j+2+@ zXHjFmb=6Uh)6J1Q>27#kCHd7!L~5)=IlCs1UhYYnDcUn4LY6o2XuFkwaa%NpGmBuZ z)awsu{R)gGGXjKHHk#mw`sn2{y%}9w{3&hB8jL! zAN4G}z|T$I72F`=Rv6Bb7=#xfuqam!74YKk?u`s8+JUTva+kM9f~}WQyB{K_TXX}$ zlHpL5qH?#=nkP~RoWS5zBKLi%<2IP%SBYKmzes3RdIGUr3U)3r#cL!%60Vgo+qP`x zVT@>_A+503Wx8@XT3fOvY6h`flyWL&=VPdNz$?l2+r!Ro z_s%=mzxT%s@AKB)ft=nK3;@&pNIf8E=i@BHTkOK=;}fy#W#r%W8y6tvX(v!=rhL+T zex9-^GCdp!qvR+*spckL8X@Jsm8Ke_ftToL)+DWuowM}{mX?7@NzC#?=J{ZML|k+{ zCzW)bvFl)^o~+CjE|HjAvk{9W#|VXIczItmrMkdWdaY7-?5K&fWrF-?0h_TGhv^zW z1^VHK@apCz_rrM!I?|1rhyk{OR00xRKe(|a4$(;ImVyFWU5`i-p(Ik!uERy>Q#w2m z+&DHvecf`x*z~WRGNKR;K5_6S3FB=7n~IIXP&UadOfsObu<45h77q1(@J}oTzX+oB_s~)eyp+Sn+?I( z`W%@UUYWRTptH0yvlA-Ed2Xk5ljz>qI6shQ^Jd{y71iq7+3)Qm!Jj*E)T2cd6A$1~ zc$^MmO~F#GnIOjqpE7OmpN!y3i<<&-E% z@~flNv0uuAiOnd}x!;9+MaYi~qOqkAk12mUj||?aLEuAvBK>6O)$L~gtt})MYSr3b z*Dei;o~x||O|oq0S}r$3S|H`_wb_D^ViYzyOBBCPod+uka!LI#Emx}}A`5tOdD!IQ zzFm833pk{wl!7|w_?1>rgHWEE-!*6^oS6Wvqxzx7jYd$r@SN5EW{+l{n{2Wj=CyYN-6NYh^nf`fJ)Z!D&7@98Lt#*bi3 z_pl}=irh^RxR~-+n$;2j?}Cc{H?TdQ_hkMru%}}F4>u9q?{m=4uVRG>LjPSo;e)>d zg2_w?g?!P$!NKRX?tIg!XW|wi>)68yeTjW|n)av{e_wSC%}5I=m8;SAiVkyp46suJ zX|2_F=|dr!q-6!~&1P8T++DoOoC3euH%uIg+_znqpit7HWC6b&-auu^L+Q};>TqNA zQ~X9VLE<3nfoU~W8;tRLie#11uEf3m{p z4Bi7#*|jqD?eW-<;(@HEohUe7joj+A2JPHNr2h59;Azzp3kZg@;viW%wvyXy`PVZl30vuA$|IZMR^CNd>3(3J6_wH{ z>+KBb&Yp*wp@m*fLzdiFhE2(%FlTvcavybFx#TzB;g~bhvEAVuvl0ReHq$cH^0JJ; zTY7fIEt&!UNHEdTSp<$EiJSs>s{WM1W{WTmU%xx_K+P+XmJ9NiY}&LN z#y%CE&r9SAxu72_<@ZSk3b8J{uT~%Qxhemy&&t*Bo>z~bMlcPJ5CO7St!9%m=3Wu& z%oLE$XQs=t<|6`l-NfT6QS2;SQn81d7k=+HQVT)oBv{aC?hR)I7K{SYRyd_2#S@ur zxTEMj=m_#;*t43w3FDi|9tj>v8dJ277gDgh{J^c^{o|eD{lobTv>yCm_*){Lzzutm ze&$*p-5kv7#Jch?524b9uo7Pn{B=Ct}4 zzg>M!!K4lERaDfDzAEV5oFM^1eeO1rq}8QeI|qMbQ*;HxSaQiNBZ*WZ3^|Qd{cL;~ZNk`-N_YmX23>k4m_DfEZ*M`< zDO&Q-TJ@eM;(lv+!r=Ci#uEOu+hn8d|wi?^Et;TlJ*tU%}wr#VqZJT?pb?vp!`48VW z#~AN>Klh`-RP;N8`j{>)e(~=5ZQa^r`x!lcTwrHSSAq$xpy8^*J*dn{(D0>#b+>nQ zyBCxyJ@yPcv&Q~L$r+Hu0{(SXXkHz7=Gy)Bb75yk!o-rHS(guHzPD#k9Zn}H{+yKb z3`RS+{XdXN@dc8&2%xEr@pq$nCv>@lR4Q^^wTXQL%Qa!#QIY2IJN<5(s2=i0EmvJr zqKEEOrYxXx@#@g9yKsi!mt zMFy)B*)s#cM|*R}(UA8;;KnCn|1~x=8J@*#JdYB52-9jdDIFe5gl;l}`~xY25VnyTOSSb1GB%mL9v`$HSy~ctF7f zSUsfb$Z#wxjvrmKlHRGd7Avx-i!2_y-I~7-gkE2ptTrht5vdCn3QI5EbV487zI7Cy z^SX8cPX>KxL)3$po9#9X)|YtKD{ix$bD>bx^tqCE z?Huh7#*Cre?;syOog+>dWu5*xfAXk>NJE&ry0B=5=g_i&IUGw0t^S|t&6H8%5voq> z%N*AF3aMNaN>O`>)D+Q!WWu3))2E$xsbC*F!h^j_lX?6YNczLzf!xSd3PJM3-s_RD z%Paz1Y@w9uZL>K~Gj~1~IFsV;gL!1-Fd8-Ls3( z6_a_qBJ+RnCDF3FoT3zGV=r$Hk9hu&heP;ofyyg9yu6jw{BQQm7~^^x)Z&ATwa|Ys zr=}5L9QW6eiwx4p9{HI9Is!eoyr^#9gpuUOm(q+hG;$M=vD(9}-Cqyyf(}oD>TVIw z!(V@LyK#=MYpbsPK76q`)@b-~V*)lIK7>!o)bG6udDrV*CNm|WfDTYaI<3y|;_!aq zYaCT16vk}$I~qmbRDP~F zlnjZAG?~>(tv{!Auk0*w#+6lwIazU|GhB(({Z(^Id;4XLlDI)DA$Hvwr%1}Ds^Kap z#Lv>V5?n#NntP<<-FFZ7_$TG%V!75lcgC0YN+;4pG&)FGQ|6hc_Z@z=o|=5crEoq2a}yIpscNGLhbD=0@HL#h=b?2Xs7~+1tB3_Q*#^qoqy6$L$dhe@d2>)Ng6nM$5AnEu7L*C$l+dW?F_K;|5h6TIo z7KKH7W!-Q8rcQ(unI5hY zV5!u5uu3i=AGPb7*PT*}EochMi|gYiumW5qj2v)Fi>F?8npfO7x#$0^!%nI(E4yM? zks}qa^XcGaw2s8zv8WJtLKfbR$j^KUqT*h}psosj%rS|-r41%LiWM8sq9{LWVDb1) zgQ_7e#v&A2A42eX95Pd-R0tS5mGiyRRR5g~^@HzC3T7;xo%{2cGO%2QevT1ui;dAu&2gb2AR1$V1G1X6^}ej)p~+3sc* z>hDa{3b#0YAm0{(5`Q*G85Jeym;PyjmbQauf+Yw$Z4+yt(}-G(34V3Z;T_aE-6Vsn zyM7pA~3GZ2;*6nQOCV;}%uE@XrC4q4UN&#(GMYZrWvr1dhi zCh&zwpT!+%4BVWYO685b-4#|vhWuhKhFod?|6ZO71zvIBD=6Et=H(PQZ5pI0#hFQq zNEUXq>{wgL@Hw_i$juhx)!gQAdTf}*>jIKq%hX<<)V^|9rxRyL1e5N~8vg2Wp|RQu zZv&G`tf@&N$ip#5XEA{4YO7mrr5z08w|ISKXqGcA9b!k&#_mVj5^{@eZCmqV&w<)L zyT3pR4gtYL{y~$xD`!@yvfUaM(##Uv5WXJ@5h%WAVQtZ~D;fz1UBWGrxDT=D?2@#k zc72UF$unAumEyqM(ntQn*gdIZ%ZpY}1ij3Zj-*Wzr%oN$VqY32AZTAf8)GMjN;|NM@}1QgrCGgjE0}=A?l`CQo`u?MK1@ij{3gO z_)~sPu*!i?q$!zR_~7$v0WU4qom{}72{7oi8f_qObazOyY7*HPk9P*V=nE&fy{w*{ z4XzZ^QC+4R!ErNKpX|X$c1Hoo7X=;>xsNn#(cMgAaY%kS>$-Xyzo!~;YJJb-Xm#3f zlm8v=giJ+aYjT}*n<|3%LRMq(Smhv)J@ARJOc@ER-tE`+18^deOcX3pF#@NO(wf=f zEQc|xdLWj^WR3?>z>S&dV-R8Y@b*b_yW#ebnjG~{lDnTAOsVQ*ikix?F{08pw^r50 z4{gz}Owzn+fm{05uEB}01i{zWR`NXt2wmNtk%@f3e{|Gmj|unfl;!?uUBvd6%oR=N zoA^g*Qpo>kWg?*o_$p4}pyw$PcWwPs^jvfGA@`wTTKLP2wwTy0FPI~f*&aMA33)70 z0)!pb@axq%wy6; zYu#g*y(0~7vI|TW|GG;Vu%G`tgjJrzDkLd9J~`>#Ur6G+&m(3ii0GVqs3Q2g-^Yn8 zXal4KoSg~NB|JOeWLA+k?vVuf1T*03a8uFv!{3^-vbBD%h)|BMs7Mm=g1WzqxtHFO zXXmKR<5DO@2?1oT)N0{+`}Nk;Lz;+=PL`KjN31QW8A3E>b#$k48DR zz79^{vZX3&-2&Jpv0<>YBE=?(;b{|GwGr4z`PinT)Jfs|P$~^WgGCb#V?uSVWUIlL zsh5y$7E*jX&D=s@tmD((x|{5N0T*`pUAwSDkgvQjn5wn!lAX1uI(#bE^_w)maG3md zm}xaz!Qm$FipGpeu9PVKKgYh+^{W6ya%-bi3WeV3HUJ#3As?2XRu*QOk=ceuS z+J0B_c@hwGKY+IZrPu=s-6B)VLP%oBU)89`<1!x#7oqz^OPwadEUOp{!ovv%b3V_% z+30KkSi61%8CZg@@Ihr^E;{q@Zc?YYco0XfVQdBPhIE@HVKGzL{DRpt{)84x>FB!4 z7yC&dD5^{HbIGO;h!A0pt2r06wXF^n^eub$8-`%k_dEzrF5rUGThDpAK0nZ4*dIs6 z-i$(A{RPSR8pgg2o?rCO7UdpAm2t?_F^ z)M&Nau^{w(@yZt~#BF>?Zrl1t_igx?&DC%kJn8qyu4(aEV@3ewHgTQH&iSY@CeE=i z`IYP7Pxo~mdfQ1A#ib}9@^yAu{`%?(x6Ks_R_qw=J-&V&Hk->0a$7s_q62Q+58C4W zN!v!RKX5EiJ>=lRrtSZnU#sE422{!ikkKp|ZFYDJ@z0b99z)a@d9=(&RCC`MN3P$v zKP|%fTs*F)E2m+n`jW#aB{rA-D(cS=at+2VFB399qCQ{lgt%K>Ly{!*0SjP;q;`W% zTcD!C8pE?M0{Y9>&)XtMLc2uF9EFG_H#1m?ePn4>iqNhX1PJlP6O+77fE8-9A?WUC z(4*yKpo5NX*dL$GRy@kHe#Ed(6#)l}5zK;!cmk<*-xClyJpO`qh1NX}SH|K$TwT7p zdg`$+k*S6^r;QqvHnsLEQu$~aHO{S<7CItYhx2{Ku-b+)4$UwwjGuL;r+N*}R4H`& zF{a}w1(iVOpEdT$LW8fnN~Ui9oVHaSZ%11UaYlv6QAXo`1j8wnI>DmSDdhpCJ4W$_ zqs%0!Ge+^o@yHuS5wuBu@pPdnq8Bu(m#&g)ZSGXa|JX((^iKX*uI)q_O>tCmvc4F< znXu+8u&A`w*Er~9KJs#eQ(p27Qo_5Q3M^*hpnDq#M~Ll7kRp#1DZlnMcIB)c zt~<*LGP=ZN`oE_8fodhSy0m<|{5xU7Xu4&vJv;Q5tsz8CZ$YlKcl2e<#*1e`G#g0_=T4S?=Vl!1l3+sg$X^r zN1O=`Gj%SkRWpegzbXVq97c0L8eF7g1KFu$`t-P#kkIK-W=K*$%J+d)C&xLx)al&$ z>>}f=<^yaC@lr7|t9g>(j)sP1Ok2JAUNTZA3t1mf*Yovo*K}nXn&NEI7(T*(mgMaSm&k6mbL?VR zHVak9G)RYrhX9BFxB9nby*FA*m^*!#vRN2ebBviWE3bvsJ4XgCE~fk~(=h3+zo}iS zimHWoga=E7g*LAO4)|E~mi{NKkE{oLdz;zXEyTv3LyhGUvC&d#t=;bSO|ULZBe9H^ z8LL_iqim-Aj~hS;XYq~bv6`9bfs=tDTR2WV?25agJ7f~;zx%Wt5}{zHuq!a=tM~!4 zPo(5bN7d#rko>19Sxs7>V1z9%?QW3jY9VP2Qfj8UL)flRK@5so(w`}nLqpjRHCNl? z773y#7}zSzEu!F8s~~FnP3hvV=>qv3a4IbFW!htQ0JFvj_ zpr>qsZ0Gb>6G*ZWCkr{+Q*jS|O8g;H+d3|CLXLU+f7C=kC}Z$pJTjNX*K0E3 zTCCh6jQn*u)A%tmh%rxP#bX*O-1C#>5cx<^Kv6?+-IDyV%d6SpWZg3B?U0mw*p!G5 z;7tR5P$G*ut$|o?cA>OC5%jc8YX2uRQK8cbpKZ1Hr`7S{6-0~ZlV)+|-m-W|H&RZv z8Qp5h2JsCDG+hY*iUx3S@c4`j<`wFJ0%8p=3r|KIN z&sar@C!t5J2C0e0B+|1g)bNj7carQ5{<0ZW#q%|*C0i7d^kbf;))qvt%&WtgAx4-8 z-nd7J4^U^RSFTZhl)$MV)X6hW5XD)8>oA!Mj~d+Mshr=*T!m1e0sb|Xw(N!w5(k@?)9`7Fd22xwj@tTR&Qyo|+c6lJG?f zBFsm1%_$fN7V~BKVPv8NV&g!HielvyPO`>HG!@D2@MF`M2%=rz@p~NQ>`!1O6n1cT zv4lcJm$Ux6j@aeuqu&tT<1m z?s4LB?xE@4{Z2xZQM5$%?s85No-NYtgDm#uyGq7u`8Cep1L&84JgeVtwlnrTy+dF| zHy@Zt3pp)6027jY>-EYAyk>Y-$dB2`^yDopLR0hLe-YNv1am44bb6>X|LnCaV2xyb< z`-f#Kl6NLsXmg%`2oYbnJFCLU<75V6i4EeKDyMo? znREIW^tvIu5PCgLcG4Km4^%*!=+_@oD#t)WB?<#SI4Sln zfvbH#8rGBd9#Qt8xX9$P8qaT+|BbW;w%m9&@tndC<&ioZawR{Fba&9=%Fq{jsxJQ0Gz&mTz0`p0`6)GlxJ6~B|d z*bt9WQux@qTOf8mUFKIeFWoa;P|4W2|KP$h$|>R*8%L2K-~F3MjS?a8NxI7GfeRs7 zz)s!>sR3pyu9R>0-P=&ApE`BYh#zsK&PU_c98UcwMGm#qK0~&YAz(m>tx_o75H@Tb z*lqJlY+po1`{$`f=hksoVWQMfpf-{oGoUNUpCS0AC2943R|{=YcrYT0GV&5~1A@GUY2#S8P7cT~y9cD(bd zd#mp|ot~|0h2t>(^9{2+xIVhiwt?hE3Z-%FSH1uEEJ1YEBNxOS9q8!+Np0C>l8J}= zz$kTkHO<*6(t+l`O}c2DX?zSxz%-SJ9*afYGOikxr6WEhc29f6;rk)|{$BkBZTI=8 z&iVMD-r`gbvsWlQGKwp3K(v?Q&}^G?DiyN_fs#By>Kl+CZUUSok@FNWJCj@Q*k3za zAAZ+cUuS+je+u>UyN}rC5=q8#@8o09b_cS+g30Pl)~0o&E%U{H{A+yhbY2)!J)4OtcA!+T9T~CEOrS;FwNsk#OfjwpFSPzE6z)>#o;o2CCuWYwQHp0$%v_;tVCJhoA)Acrx2x3id$(z=y^V{ zRjl=JFlZH@zlQ{frIs{`J{H1S+l~) zFjv;N<_e!ahc}wR)Zg{;p5yr9BtF?uEAf<^@54|F^l(^C-tp*xD@k>sz(J7075ANJ z(PlN|@Q|EEfV8y)B~;Q*kJq^oyjA%!6S}DCl1-5!>!y`Q zP4u`*VM}cH<EC`ab?S&(m}+R26{pHgYJ}7)`+<$_KiUWn zqSZF)%q_kvY!5thiiLze9E1Lon1WKWyWvbgL!+#&5TlJp4Oy?mOr(w?5>Kp_p^GA-_(#mILajV17(p5zn}Kkj48_p(*ShB?LSNJOx2OrzlB*gxr#6<@VZG}# zw9A5hTRv)aNu->59712(>L`M5`{MOFSd<*5$n%JM3W7MoD)V77s}L<#O0YuXhLWel z9+}Kq?M$dSog&Ng{tST-o{&t^=tO;Wq9_)6HLx_z7ve`vK4q3Rp}sweg>^@(BCgih zIYZM3ccbXTJt@2lPC?X&2U>}EcthEj<(#g^P90B&b~i%|Uuu&mq5Q**k>>WLXVl=A z8-33T1al}PBXUkWIAe)QC_=kA*z?z;JH9}X$P%k=>h#_-Fb^mM+NA+AFWIKY-qQ1J zVyykm1Xk4jBLbodl&ZfR zW&@sn(*}k!k&Z=NOVig>pPoEp>Fo)nxIBZhTJ!kSGYMNGR9$uYz2zO?4BEFk!Fej0 zmKj|?($9^s>Q~eMF7I*@Jol5XfjY9s`89vJ6yD5iv?>3w1DP3Bpzt+*qJi{7ILxW0 z>qb~Uoud4gRjucR7SIx}9m^h}a?>AUyNSkAh8H2QvYbHbqaXe<#?xQO_IkNBxPl^X z|2lGX+~tj)E{VUBG{=6Vszd=6sA zO$O}(EKXn8tL``UO|P>j&ifMz zPPfw^m%yKQD|-zS?_BuTFBuc0)-jQix+v$Ps7FzHYgPFQGDd5vvK%m}!NN3Jf;TdZ zK9vd@OB4SXI4kwISo(CVwN;xJwu!?+cMYsuxP}cn#lA9?p8JI&>P+#Fka&5?J%t9Y z2#iPy1wBK)Z{ni#=6Lw2g{0BhNPLz=8H4+quGbP9G87MJ;V@(>NPngDRF5S;BsBLl~03CEZbb>AP66a{J>4N%tL=9^NZEK=J9r*_6@^RScUjHEFr)e>gJ zjM}06jhDZY4E}dcjJP@M)|>3|LTfo@ar>d_0e=tKX*X*?x%EGp4jC>)gwW*pFx7WX zSD9+W;&4aST1@qJ^#jGu{z`U-*;Xm(}~_kze81jy%7+dX*r--o$93 zXUY5IS*rb&8pfrz(wog{`z*#aA7OrrhD*e|!?VSvrgLQVbY|suvjE=7&4?p~tPSBhKPh|UACq}1f??e_-^g~}2~a8i z*9oz^<9<3Gj!1-$_vqTOU6ln-R8CuH6vXif%*C)Y@6G3xUk!U0_&y}u0v^`8pcHNf zxWBf`lki($?^2CY+8xAq%PcMXGorQax09C?*C-=x+clWDQ=(pFH(s@!VQd3_#1tOo zQ+l-PVUi8>_ei1MmdoPSZJQ{Y*LxJ*hkXNm#F#fPYl%Fzl_-5LWEORcQ}P-YEr0%N zq}pHUD7U^ztQQt0X;04l@9om8CMsga+1|hFZ^xIj!WW#6RVHn2F+k29%af zf4z3^Tz#H0+^pq($)L$^;qnG)FEJ3YF%`9wj@Kzmh}4zId_!{x(i?krLFKF zcP5^S{d8C|#|2<(qPI3h`$Xqb@{0x5p15eQvK70>~b zq)N8S#}q{2fpJ&*kIJcmk1RlLbm*^C@n3-3-|CX)-(Q~V62R72Ro(veSbNa;ViAIC z=UtPO5ob8ij5y?9>wB-q6+3M@@p)?g1=szIli&R*jWzv+){XoI9A6&a74zQ@?LOh{ z-fzvZzwEx&{QC4iO8sKH-x0px{T_0^)V-e{agKj_A-8_wXOpn$?kLk8Eb0)Rqy4p*BTC7* zkn{7w(EEK8(2Ts|`0Qdaj1$pA-LKmZ)!ljqD~1X8ZD75_GP{DZv8|^C5xmkGvY?d7 z3~3bw?mf(%$azQ=$8eP0}U-Un>0epU%I*$Z)955y(v%Y?}RHylfTn=naG zFgak8wYj360PI(#KP1`8N5FdzMlJ>sFE2mNnZ9V>iRB^Ci?4D>5lW*xL;IKsRgJ(4 z*&FhIQ5L|REOOn&CK6_crh||M21a*E#^~zVZt5tbrnO=%H9gbrRF0GDcbmWd3?LaB zx+C&8eS{Zq{z0C_-Anp!J(Dj5~rNa~YCteU|++cB3WiWw2K9jPOfhBmf)-Vd;sqkpX zB@3e~*YBR5&-<*|J(C;H?~~*CV(Wvgi|dsP{Bmk`q(bMFNZ{neqliobeNgfBjwC~cJ(eUphxs8*ULva{jfv@xdx~d6gtBn4 zfF6175l94)F;DLFf4ac{4@ltb4iO4@n(UYnDb1Lou5$F>(_cwoY#mCWe>pQiPqMaG z4u(riyPbV64gUr9+E0lMnM^BF$44b(Gz&Ps_Vf-ObkhW9d~Y7t-=kt;5TBYJpaR1v zsEzs-O!Xd>gPX#yNE;7BJtBweO|PM<>c6=7vRq?Xo>Q;A!7AUk9BY1?PGeS5h(KT+ z7vMr^Z0U%)2l_PQRSvVnkTtZj7kcw>M6grXywwwG_a%2ik`QI{>ht=k&H26(%IR}Y zqr>L}(p;rGP*gN64~rwp;&CXMkorjUeV7tX+9^OS?fu#?gM?3lI?(~35QuqF-FcfX zR-;v|7X8IruD$K}vZM$0+S*(5y1G>-S{LetxFr0|_KN`XCpC#R(l=LA-YAezI?qI-gwQSy=-<#mixvz;` z$9>j2VuI%^ydlSo-wv5?J@zl!0&)@p$ujWQBtMAXO`J|xefG;-B!$LoM*uF22+I- zrA=)0Nx%q~9u)MT*Tkfe=W)wi+CsUyG3WX-_NnfTeVJZHPeug(O3t96h;Mc|m?>0$75?CYJUTpJd#bhJOeK1LrAZ%DAaz}PD{5k3TvS=0}4=hm8(mVS! zseyx5SZ#A<&5{FMQba$Sd z%cd&Vh88S!xXTZ>v~`83qGyHBGm4qSrlF>6cSw5hH{&O*b}KaZ)A?`&+nEB<5+9#C zGlp(c=)gZYUE;!(Jg1h4?72^G&e7&9;I%mjSOKF3z8h!M-y)a1+OUqr|0gBFyt$2M;|? zr72+JOStWQy_ZSfd8e^Yc@!O1xbmvvA5~@lpm#zYAOSLH4jh zyj{xK<7D_mVlKH(87m6zad%-!e|P?Ab6{thuTSMlSHhe%euYET#$cbA7ja^|%BMAL z@=jGpnRvhG3#bz{Y?0K+r4)zZnwR9QqAOe z1+HW)TsK1}Jl>&JvDJX4?MBdZxB*e?JN(^x{f?OZ(gzCYF1_;697)rDjMwWufQt?p$Lf+CwCMlXKK0`liz5Jv}n7Tzn5qEDfC-PK$Tr`|94FlDp&^= zJ!+N}w1jV&!miwsg~%aZ<@h&ctnT+?Z9M{Ftb%L;bP`3$<8%CQea#f}J2QnL4}sX3 zZEu4^6zGAD$w0`_aZ`+mN5h$xKG7piN0eP8rAZr&dP{Cs0(Yc43|ge>A{}IuFf!z@ zq4S4WO(j&O6K_vMTQz!L2}Z~^@7!G-g5vG^-W%BKChLz5UB01(zs6yls$UxD{~%KE zB2$d^7V$Ld9cca@@PU{@h4*}l4YKTIvO+VHBMEv@Nfh5r`11YU4vqJ+b={dMCD=P3 z-E;iv_sHeWcA7K46}z!cM4FhIl+X(suSVsCvi4LLNo>A)++p^7ht&=DZUJEwp)Ygf zS10#r>1e~ZVz*9qU5OqX=O)6_>O05H+o$hB@E1FZ-KY6#I5i62bN&TO!rOeaB7U`Z zyu&c-RNlT_h7xe2tIO$0$trK`RLLt&{fuW__R{U;ny4BD-rIf%As# zxU%y7n78XaO?xBDmoz%^`p=D`4v!l+LFW_ve=3umBYDM5>uHxKK{ga`Dm$53)eua9 zZ$n|L57VN}rhlsMwK2flptC(hhuzZZKpTD@!6vtVyQjP_ifl)r0Fc)N5Qe5Th#BYHZ~8jcx# zj5(v70)33nx*CS+vYtLs7~mf53Yh=daJ?@=-FN;i)#^`xE_&|(m89LvPhIaBK_3#k z?-~;XM*S&x7B*)B%vejWlXo3rC-Ox)j_jNSzd;-GM-~+zWVF8>No|?; z0qn(~YhthkMce@zrfl%I-e4F1p&xZi2}nupLhh0*?q(UGCHV0P_GscCQXMTY4~S;B z&TZvJOvaq97;?Cy+c%cTm|uPz;eAin@YRz|5mh9=BX;Y%?bs^uxOlA*N8@F$B3IV7 zv}k}3b^oTLq?|(Bj2bnj--O2>psuVQdw7V>8|ZFtk7!KNuOy-$e&*>9`of92mfTHp zW;GRnk*OA~3JGJu9Ap+J^}@w$*e6WEqP$eR8;>8M6rV(QM5$GPEbf?8tJH4K_1O7L z{n^X^F23C06555=hhXN2+p;;h%8dMSU7uF30%rdwO_(pc?*QgVCH&{=7R8ciPTSd1 zssCMVmo?;(ndY$?(Vz_J!K-fU1-Dy4XD4X#yL-_9(=ZI+L2qEwyd(7wioAlI(`Vp6 zE9!kVn*BtN25hC^(y8>r+i^PcZxHcVcwoB@;XT+U-HFdC+g6&#gz@R7$4pJG!7QWX zkqh^vLt?{##VP9V7&R+9dwzbcW-RQYra?{?8eGE1;-TGlj{{(M5V#lJn1x}*H|s(wsi zixr`q!*(zyu(}MSxx^vo@;0H}E_w%s*$wp&eOEB8(Q~CJW?*OKpH1Jv7G=&K>xk6C zHbZ?fH!dhT~)X13t-EvHMl^h)#`?eT(ZM>LT_-f6*-$zEwi!} z^$2cgWt=dr8NqWhjZ2Tcx);w?+} zw^o@9s$)}3&tN&VABcVM?Fc`8K7cfg2yt<6g-?u7GVh^aUYreA0z>lCnNs(+=I)+q zzZ*CAqm3u~oiUen9LzzDHrN#txYO0tdND;5Sc-dDd!YEbK*DLrI@pKVUG)H}zmSzVEhlGTWAel2iHZGZfz&rC#ycT3A^J<_ zNcDo+KS(YQ4`GA5e~Vb9t)yd>+$a0UATtC#Ws(qc8I|h%Fx_Wmeuw`4M``v0%NJ4( z%}_*uz42%BfJ*_y&p>>%T^C#NEs%)1QsQh8`%vS8HhjP(ax6T6_Xb~JGYVZlJ}dMf zZUnBOG2aT^A30i%K zY`xK{PQXd0-}xP_5iX3JS`l3~EnU2Tibh**ay~;I$IPvshy&b*0Mwihy5bnRG|8Fq zGg#+D$uT_ZgwPg6+&4Ja>s*=q zI7S+O1PJ=Sn;qSK({l>g;Y*Yj8KWWf;US1W(_jtP5T!e0(204-Y&IOu>9o*p`BqlO zI;(q7M#Ntn{MgHmd~L|e_HH^C<6ZARta)?(sI9wXfBKAs%XLo{^7=OM5GFY?Z}vd= zh!A4R2pT&c{~jbow&ZVDMN9vDbMU_giJx(LV9}oR?tcPCU8UBl5t{1%{Uc9(Iaf@ zjaun$)~)r`5XYNHkwS7)hdIP)gtk+TaeTL&k`t^)_0^#l`{*JoFUxrzw_~xr?a=C$ zeyWtPvrB!py^w?hNz$=FhAH*kU^n_eW@=!{$H=!F>BUjKbGnkqdGl}h`Fw-pdgsc| zznae*Woar~z|06!QPTuGyuEKChkAYuH#rFMd>_6qxj!x`g;Zz4maa4)f)FFVi^eA> zbSP>}>uIW!50}>!m!Rv5e)Hp_`sPNvyI1|H+rN;YGdxk>C*TZNANk5742g-W&ZbSK z>GtqME{vRv%M!KpTVC2zu|2Q^mgB^TPl3_)KR;92ZgmB3cD?;Nf@dsMp!@MrblHM4 zNrWz}Y7DBSrKO;(%|fC(qZ+Z7mFMzeEs%a6W&TSx(y3Oj7lMVn>#xajV9{q0fx^iI z1Xe6;rvK;b;}vXC-s-|!_jviQ8qW{0kKfBp+3mB;-EdIpTPyKd`@P7|WV0DGkT3xU zhq-!%NfVT}8!V%|DV~T-Ipa?3?S)2|;nMzSMq2uA>nZ95ZKn85wp+ovZ}0~HUS$Ds zsTjGuX|~RjiFF!Q@9=p?E@~Ak0*zr$w+2py@$V8QNUdZM`>S^&ZbFb*d_29)A6A1? z)9Wt`OBp7n(bOExSF54HY=g3e#qZbSZwrzzs9oezxD&Sms=nGb(@KvWrrlP6@}}>OlwH1*Up1P2WW5K2g^hiPG050jlLb;uu zY8A8SgPuqNdfep-7TW!a+u6zcb6AXXTEctyQqpkWx$^K>v6r<8g<3e{dk&Zn&;MR* zyC+07*Z>EN)w4PN(=qQK$>t0+XSb+Vrr(( zCF7{fC@-t3y%?17W#P-21-ZM}UB?UFvez~kK-MDI;6=v84RSU^b7=~BuQBol((R7) zu2`%V7tp=|ZU#TDOM~KDQtbFfa}|A$!#)PO$Q}S|O~cyQNvGNK7@g}bp@_pK_{WlA zr`H-*sP7&11i&%xmv#Va@Nrx1@VT6d+3AIshAYC#ZHhLjDb2Mk3w61TrPmrT8;>O8km{UKjdt{at5un*qNNWtCGjz_49vXFyTL5bIK#4U&E}|J;ox@X zieZjVS_36>wk9IdzNc!)JVKqt47}7c+yDgb)v!dT*-*%*LSdx?37z>h_RwOH`WsIVuh9W zK!OiU?dGc)r>VVgM}{2X+U&+x!Zc3uoF!ya6~4Lq{*853?(~KbZ@*kWA|yfX9a7bL z0qdVxp+$%hYGA!~Vh9lbw312JahjV4luuiMdg*UN;-RLWIdxJ;N(O$c>1liy zi8S#Ui)$}jnUOZzYXOT8LT9T;MC5Bd%kPNe@)xmC{gDUB*pV5b)81?TI8d&aE1`62 zO~yL~gJ!8ty}^SEQRU{`t!N3tHPEb4l?-t}K28xZR`(j{SL;YC|9zUeai{M-A;2L= zAj!4l(l0TP#D`5CD#l1?V%+F|`F{&t9-RMB7Sr$@)s2fr*XZi0iO59m?c>jitx$(F zg{3h*(Le|UN8j%S%hPr%E_vfe4+7H-s7w(^nzm!1#4K4x++Psh-5VIX%8O;UZNf#n z^?=8iU;sTxI7Xg2F2b_^UN3gt!S)3)2%{J#;F8YQqhF7xRCh^;$qR`=Lc_1AnWmU8 zGpIF{(?5Y%L%LdjVi^?;yVFIx++L;E7hlcS5A>*#`97w8LH&2V!OOQ-F26ba@2-@Q z_vi1ri5~@NVmhxRPhU4{Nip}vvZSNjl!@+W{`u$n!9KInCm4%q(B{xd`7Ne-Y1x0| z{HY7Y(U+(t)P_XpgBO+w!7rWn##)tM!9F;A?_l1~t3S)<+U-8zDPr;avT>H;(y@hu zNy$W=um*|xq#heSdS?-i zyQXU+!r09`z}ZyEiyWO_(uDsIJy}*!g;ZTO8an2$*#J6tOC{yWN7S%wYW5+|sf<{& znvllsXd}w6E_I>1Yv;O^IAP1=x6ckSRk@{;>isX%)7ZH0)2cQlc7#cGq!H__Dq(AJzxA1-kiI|C!~0TGM&7 zqNSyTFE*}P&gpl8(LWaUHRMcftZuTrpuV=q5Qr2D^5NG`zHDm_`L#Cm#^`$0SWWBE zYSt?8$5{Gx*qiZmTc9}&cam>X4#3M_oUQ^>E9rV8}n@Q zg8Ni>6@bG3HvG?_$rUhhiOM;g`Pw}o{I3Jfy)A9c2k0`9hi*-0i)4MdI~RIKx<2Hk zN1c>4-hNcg`aA{ozIkMDc#nLtznkOeksx^f=lUUm)2ILz7o1B^YpN+Ww}M*uDM^UW*cS^M7wgVO+raf00YfeaWAgIin(1@1C?b&KW0?)L*O&fTW zMBHqy9d|iHmv(*r$nAd8_I_^f?uY1p!Qy*<*xK&Ye@E+j*#(7l))lb!{Bh8Virfn8 z9$^&>D@2_~1=n4jl$Z7>YjWByJ0%ZaO&@GnqX(t_t9>YyC>Kr2*u4h9t-a0uZ4AwF z9!bK`h7@$mOdtozhG)?YWYh#sOADi*DjzL8!t>8#OVJLWi#|v;{4)xnlS(X+il*(V3wXHBu6sha){)Gw;ZplD8@yO&w5Pk z%HeML=Y!|d`2;(^8wHIB%j&AusK|=LqVRwaEOs!hOimMn?5AP~d>nAy8{m`6trqQu z{!<#?3GlwRjW`PA#)-pM64NPVa~x%G4N_%T|A;%FZwWh~))Ou;LXJ%@dN~D^0!xZP zEb?l9a#sI#6O1xQLrJ=m^dL*PJ2YO}^jY=;wy(<#Sd+VlH;V7e1!Bq0KPy+Af6X)$ z;mhN7z{HILG1vK}c59s!mbynC8$%BSLZ2;M<|J{Yz5>lIh`zUP+U%e17lWnUT1LX-uC5{k>-yY2q{#l2=>)|3lSVaK!;F+qy{zl3)RXTX1)G zcXtTVxVt;SAwc8q?hxEv8g1O&-Q92Rea^e%zV#c{s8y?K&iOecj5r+`9itZ2)!oiu z(I*6QVEI4d(DD}OQfBWDNvpPD()`~}ue4`XHw5k~vS$VGmdN9}oVfcwfBJQ6ynPkx zponRDBhU%d)eGwS;K6&|Y-)Dc`Z^8eR#Drc*i*0>px{PXM>A7!Ehs6FAR1gpOOL8n zVr$X&Ovh96QK(TPk3raQ7nK$wEk`0pG%H~T_W3??cFHeXuqm9&*!}}&(0l`i)XA>q z{-*`~q`BCg*=uA(N8jtzIYycDqHf8wo=NQ_5N=9U%!)i8BmxPWyxox|@!>mcbAocK z(iMIPuH$suw!(Yf^=W^A$gP|F9u^+QC*FD1pT;My24L;Vgzuk&Rj@kz(3Y-WFpxvY@Ki zPEEa)Kkgoh1;!@L-=_#g){m2n`cA8ovMTxmKTEF5Th*jHe@PVbc4XEYd|{e*!snPE z1hw=L?nJox1vdG;Z(K%vyk1;_H{LbyJ|5{-TQ3oxZS|75+d^j_!?G;KkmD_nzs6xk1u08}CpYqp z#p`*ec|k7jU!mThuntcK6fb-b9`51RSc-1F$ZC-9*3oaO(xCX79NJEBfZlh|^ceyq zHa>vGngeNZ@)fPk-CEMO*+`dn##fY_qbz3Z#!fLwLhDhetL-pTGx&*<2^SWG?CB+fsyV@%Q~Dn_XH zU;_RrxV*&(B)R}i$zuw>&N7@zcrMtpL1ev;*tE(sc;^K-?8LLU5W8UW8q!n^-id8& z1w>#2mxk7$Tu>C5tA#8$*OUNpFrH8X+MYnxVBL`tv#XgjOo<(bbF zzDSlKN&%Agq9;guvxW6W5J590^Pw@gBTly>{ND#$I_$mN?*-G(;0!_`Q+woCF|2Xb z6)mIUXsVK*XrYQah4Jeoz4)G!QWRJ)niyHvpO z3((<((Z-VM?{c%QgArJ>%#G)MWYSJq?=Z?J=aAuzmlvzM9*3b2xY{gX z5jpCs&bSE_aIt3FH)&DZYf+8`^w^BNwPS z5h=%9h7`&fQz4qyigd$`vDF<>y$LJuOx0+;5!?tJQR6uG+j_YcvSq6JS6vTcV&@9B z=!_nB;&;K#NLkG!+!5B&{JVmm-o00JHb+1iK?3z{j!AHGp{&nEDOJqW5^o1W#>2+x zg^XGMqs7eNaYJgdg(!BhPKblsBbf-Kgoz`(;U z`obckZ+9ty-cQ(_ua8i-&H#xln~Sq`L&HS*HGURgS;cK`Giy|RM15apAcN6XEd-Wj zGbz@DEAXr@A{EC)9sI>_hJF1o{+8F((69u8k@ODdS<_(R;y3M!-17I(GQTkoqTEhY zTV!BvWcdBp@kqv_^hHy47flN!A#VRVM5Gh@?(=p{<_th@bzMr)VAu&+vw zJmRI#6d-ZNfqWDO%^)7(|7hAFe94i2sR?B}U`1Gph?LJQyq84cwEk=-90rw&A~)Vg zsN2O()!`Exs8rc>f0><`DJ?RkSHiqsv1r}6*&$Rv7vHvXQGDF=ZbpF;E+(R>$Za6u z%eHsEwAo5gqY0miz!wnS-xDbo1XQJ;5(Z?>O47a1zgdRF+rMWxPe$9hNn-anmF-AD zTH^1p0AF;!`-6`!5NooCh*6y^mlO~twaM^VJO;L=R+SqsQo(>+)IS}#4d(8joI*e81+g`Dd&PUouI< zd{1;yfh>x8s(y^L=xWccQ|Q_+h*tsXVh=BDn~OY%b=2c7$}-)1(vqd}o?(n?9ih_7;D~fB11;7WMqk z(sP@ONR>0x-E`6m=VE`5)^BXQ{uN$nYYe%jkV4$P>4h1|=aqo}W0OvY+ex}>sEWs~ znLQy0TP-M7;YU)eI5RvmTg!DGsshFa+s(>9hZ~I7%}{~qH99%E%CNAmtgfNv1R8tT zqOQT;IR5`2%vN;iY)DcxT)%_5Kxus>ZKHdJSO~nH*4LXpUzJ)xJltcD{)H|iB|>TM z8j>03a6CkW_x@^x_kL=GC-4d_@9hJ(fhX|y#!No{WW;2(%?WoW5Nb%dhLw-*jhMtZ zv28imdYn(x7Smd-c^?k*OrYQ^v04LU#Mtu+EpypBT5a$EnUx#PajRL2Z=<*Nv6I7} z7tKRbH)`=Bj187+%&F2=Fmo!(aHzDx%v!K8ZOibLw$F9qMHG3*0bveO^|+F>3radI zVZ;o;^7`4c+1>iiET8-~nM3X>oz_32nBZIpZSHYSQ*KCqXU91q@T z#12KF`1P+O{w{9`<%j+UEc{T#ZRVmZ&fq3|V~*qnP$L&uXh} zUhp&V#L@h+aQDdnQ!^A*h~C@+$MUT>Y=vw@(1=&@X`^-*8P&oQCNTUFbl>??1us&_ za%&~=YK*y#k8!6a7lSlufm6d$`0!k*b|pV|mH4Ioj~&$0Aeq*=E@B&o%!*w7N29Em z%x|TtSbnqhlNlMIWB5$ey6M0FdA!hP2D;l;W|8UWRgLV2^-GzU*zR2kOfPT_!i|(T z$;S9GlH_&ENjLOA zrKX^}+#PB*BCNPwh(+k!#4GDDPm|yWg&!3gTBc(QgzBpUUkQt10hl@ONT$9u>Lhhz z8ZA0Fdx=u28fq5rkQBz0gcAk!KBL(0%34iCu!t_$jz}0H=-_F;6I|`x=PnG0u~X2= zDzx6C@Z<8&R8(cRY8!mKC*u=CPZI@%e`PN$V#*z)QFj`nCEU3SX9SyrlU{N%Gy&;oyDozMZMsD z@3dxuACXsE`(;K&B_-w_3lAq@MU;y0i0GG{1}i~n(Spv2lDb|ga;n=I59PwWiKneI z5czXKjyy(@o9Z7yERr_+Ga1X+mw{M=)#Es;`mrq|s0W)r{wO^T_Pd*;jgy;{I0sEu z=@o1Bi0EuC+n`R9_3!qj5&tb1`?deSf&u*J##P%o=|!NGQaBho<@1CmkN5l);C<<( z!{>%70_9U{yF*WjmdOG3JkfFfsCad+t8i1)5uKK2=3y`Uz4Fg>4d#Df@8{xHxR~bX zy&>?nO%-O`*STxN`kDS*;{Q*nkfRpR!MjeJ?OZ2VZCQ$Xe{pjtKEbhtSj)>XC$?8h z(Kx-1Ddn>{|JDhY>G1fVYA|HlCpPenLzlr2o>=%n>0)t+!KKLa$-sw9-qaDJ0fCf99!v8kcCLG&33G%}RB(BmC;< z%T;!guDGxmFqrh@nPt2ZAZBiED^yu;Vq%g=9ZHFce#YCB;?ZWrvN)*j8U3o4&op4q z^v$X)`!_B22QRwS5`s7cQ$zc9`M$Q&T4-qY@^WE^5T2rh{D=)m`I* z@Re+OgE+}jI?KC{h=b1`%{#^Z(P?cjQBJ`!;}_OOA!2Wtn&J#A^5{YpXdP2eSk5TE zUaVK9V4x;kt;M*aQ0b?+DT;P>Zx{#|iF~&;yPzPkHJ0fpN}ZVG>jMRux*)aEXZF3} zE-*P?V1zuM!>y^|{CvqtbAEtZQ^7gEn2Ragsa9sDqlz=gniS+3Oam)=y3z&T1XJ6xEDK!wZ$%k>CT;OdN|K+9 zuWHek`MvbqQPP{v`}4?Tl!)HKM@*U`n9_HY(2Dp~)wMN@cZ@aMF(SS+4YJRJK279J zm{Lq_Y>+s~Bezz$Nx?GYE;YF1g=4*q4csr^6;1j?As3(PyPGTS>$?qjh>D_7R+sgpx!~Rrp%eZ~8i*?*gfUibp$)j_ z+WP!$QLhO2^eO#KQ1q|3lA2cO7H^ihv-8({$LJUtxzY`t&AG31V*;pCJ2e>9hy7qa z*vaJ@I3`>3n0sc}#7Dzv=ld^{Dv#(v;eE!jBA%A0ZnkTaO>r=u=YQ?45C#%x>9(2^ z%vn682rU7%2yMuC30?_mVH%g342|Ec{&w`{EFxTmLS=sG3qkzvpJoE(zbLKH_0trw z_wF|W@24k<$HTQI`{%_42y}B!|6FqTw+)P4j3I9_Q^{9{fAG@T{d5uIq9SPX!@brI zoo~;3kBz|Kuw;!xppdVpj2j2Mk?x;q1ZE`7h+HArysGKR;L>Xs*E{tjnrN`qdv2a{2g`sPowK>eT~Jz!d>=B5Uv|9(0GdA3rUC5+vF>C!ABPB*rc{=Gs!g4nOV+JrUULPmrcqsn}v zi2U}0Y}}p8knPS~yZ$FGyB!Eg%ib}02BJ=d3`*lyO^7hVQ#;AuQb+vFWij$hm~<27 z+1T@ZdW0eT=dWjH_$8&4A|fJC+u=bKHzqA3VmU*J$?rmiUu4i|(O;_0y;X$hJWTWv zdLMRb5IiG;lGp;=Wp~5G6RukjipYx@xwwP8_#P(b)`F`}7N(r4VIjE=eCq{eje3c2 z9&2poTYC@Ym+@R%ky|;^uCY|vS%bTZgzJ7c3(fY|lrXoi2K0OIXbBi1R#KQt_@nBF zH2vC;moGq?^ZbxmMNnva+WW8KkLA zxYdrZH+Mc~oyz9uv9{&+ek-L$tRN>ZX^MShfDk>zfF3ptQpJ`aqmi-YZORPA8fLH`DZ-SmW#KPr3iGPqoeOB)A3GZ+fDD@w(eZmn;PD`@qp`n@l;@OwR%^z*5@Z@2`aKZSbDFO zm|x$rj7eZ}=B)Fr=F80Gh=1z^8_PjK#C9RNFUW=)5!L$nV`Afw6k1vi5ZyoIBU>3T z#VO&dJ=MXN(V1E{IXQveI?bQWY>hSiFe4+i%wh^ge$}W*I(_;cuW$VrN?&cRbp_8geqnS}Nn&JZ$A^^5r% zuo*cnmCjm?wvO}sGwoAX9eVBV+>1dwZwxZPb8V`K?iq%PR+xY4i<_Q)li;<|hRaLvSPBekXD+P!l zR&SP#J%VGRG6CAHpH|QX<#@hylTJjR;}GJ1bzov8c;+m6nSWN_@e2(_e85s$-cBV z20ud@V_NbPPU;M~59Vns{P6pxuv-=CT$8PI%4%U0%ZveB1#aYJAd)!WL+F3VAc<%D?IFx&pBeo6{VXV~+{!gRZUw^%<+^{60S(trWQ|X`NLaEct7`bLj;ZROP*M`xNtZ9X?X&XT z%q(F{n^%rziP+*PpIc8;;Pa0;74B#=(Sgdw= zDY$($D=Hpq87reS6)pYP&IQ*p#z^zM9p=k|l-C<@Ikq-wstq8V71DA`=l40?qV|26 z?>;JjplM6IpboyreUS9~RpOo8Q^E}ocur03$F*-WyN-;~n5;`1nA^j>@wu_lk~>}* z1d0{5-YD-CcG6lhi`hui<+0NpxA1nESlm(At zg5wosX=3?;(S(2Utxfhd4gnpRk3wGESORDQu$m@-|9rD(zelbq{$RG7kQUo+_^rkD zZw2keo7V#)FZ179Rp}Rk(F3Z#4XZ(snD;#7uD;KcTmj}jX!Ev`WMG>*HSXDl2@`K!^kq!@We5AR{Ell zVSz5|9RC=?mm00fT+i2{Aqy+v+S>U@5)yw2|5@n!AAVT&KL5K;ao2-G2NPup+?s|q z-9I~4)3U!X&H4cZfN^^#QI2TixYlcl6b?4dP-#H(A;bpy)sfwh-xxb{a^so}u28<0 z`Puq2^Z3suzUSLvL%q>F%FUl#q_N35Mw?z~CnSQ~4w__8bX8N^T7@SMlps+@NI-ma z@Omsxbh&-jz>8EaGdS4o7qD)cH9}v@+pG?YfIxU+t<6*3$+Lp+Ns2nH1)e@olAof# zu+l;-O=lMS`YllOX9UJr8)->$tZ&K=n8Nlp;I`(kitEKfU0T!mV*UZM z#sV7=Vfe{8Rg)I=B89mbjnzkt{hbO=B0yDE^$>PEtq{3s+)l&`^aY}rnfC z*W89*8_Wt@s}S^_M@St^397NDHKm1DbG`4^rfrmpY$uI0)lx2ibn;f26dr6T!-dvlL3{=FzfscW%+NbZ zR6osW7JQG3y7o+RM^wJi$f)NC@23<22M%?bzCl8;`oKO6$Kbc%QT3cE3j)-{Iq{_m zX$EYu1T8rpn%Yx(0Q|vq>$fdfTt)4poPrt!N}fBV%toi?^`y zF|(iIy>}6I%EhmrGWMlZDCEB76IT|=SKX}CSZ#c+SZUVEh*Excq;lNssqJ4NtuJ2% zA_Va3g*`wDh)uSZe&B19>7z`ZBYV}2r$?<$Q68M_T4#P+23J!Y1t_{y3vGjCFDnEY zjpbA!u1b2@=WYLNvEzcQBEd?*Lyp9~w+pw*7wA8aIAqjo%`3GtKm_$3G3=Sg%tcju zjrg5_!$G^MrzLV|gmoDd)lO^IgB3;GOUO_N?1@H)c4@DrFB41 ziXA;62;}nR+DA*&?DWkCFYuO?wwI~r;S};z_f`<9$D(H5l4SHfqYW6OML~1u_ZKjb zZYx37kxb0okxESCeXjoL**b<)@u@07k-vzoP#bPm#K4#}Ru{f+?hdJugd75lz@qs` z3zkb8qIbp35S#y{g0}yc3d+*_f|Gq}Q@?t3_(f25Ete`nzRK$v7KVvB0*nXPG5*q) zmN)l0_EjyxJ1PTESZ!quu@{`wd;}-gczwW|CkAu5r7H_5lSgROEzXPb3ozZmoJyhW z=H92u9`!-zDsciHeuA|K@b%SUTnh~_qy|kfqY`vW@*1VwINe6_>N<0U-ZFc&Fz29` zU?A+337Fr}PQ%4PnyfBMBILD0MZ}3b)*iM_mfl|_72F-@XoFX3d)JaUA#FCfI|WNA<0>^1gr zd3-MvS?dvpy{l+qhwT_AZE}(q`DO)E8lV?;yzI%!+Bg)@38N)7wl=}7eoGQo6+{Ye zy7`srGiE$rq%pzAzfebiIujs;iJWdeXd2?Ef`-VUhkm!|pszXgo@z}X{jCs}pNQjk zI>zGvIMlseZw2a5tNpqW5!#bdgNB6OM4ovem&DO41b57SJ5k`t2(07=-TAMwP4-{z zVB<~@5)z(+!bt#IjgeOgO?_OG^g(jw2$=g9_C>u*XZEI~>~@}pKYbo-x0VZ?AmKI? zsSa7r7MY}lH&opS0tZa+(dNq0)|(lv#vT;Ys2Pb|$;{AB42g41-)R*8IRjU9M96*t zY7|IE?uJs5=Gn)RYX%)Ov^RqO9{;uo#o0AcO!$ml>KhKpnMwgJV%x zZngjCAlLEOkYDumk_aK1(I^!J8f0W+D_p={&%F%vV9z5OpPl6h4wu%Z*Xl&ob~~S| z>px)7p>_HGN76GrjWRCKAF)V{>4#HVa(ZaK(#y9))gnCyAyIZ02_M^aNOZOjAZRvLGL zF#+>lyN)eYC*HZzF5&sYFvHzV!T#I_mjjT%5giu28QBFD5YV5rW-o6sr2um}6i+32MpLO;D^m$=ftdHN<`O z_7joLCM;27IFGK(jJ-_+vmF`-4Xu8n_a*kn|JDn#x~9ITeuqfJ+mV2P>Ot+`x<75+ zE;W{xqof5f!ig?&npI|;Ji#m-!*dDIDJ|WNaGKfB^#liT65nEVro(R0&bg(Bda3Cm z9DPY`3z}e;hMA%c44+NzM$a~bxr*v~f+sK(UYoniOG+hp+^jn;aeQBAAX}Q7^rnmc zSLoW5q+ncuTMAtbjPzPf1$&M3DO6pHn;r@UHXux@9p$3!9!gJdNdgH zdLdxQ6s^{YjT?i0HghuH$OvM?NMh>mBthWYgC?>aUtA8neASEw7fkASJI0PfTj5=m z;ncg(_QErC1SFO}q4b;X_5%Rp+3@>6#^Va%nf{wQM)wr1= z3)vcBNr;WQgfWg@^t@5h-Okm>Y^9kK$hd2#K{`AZ4O;7XUj0xlUj8gQ*X_GZYMg|% z-_2I+BC!9il#rw_48NB3K8aChBojmKLB2FA*r8?iE5r%ruyy-wwaZO|S;ngTX`Bf9 z+j1f;ub=U9sR>GZl9vq0B#U$%by?Nd?GQwn&$5cywrO3K&D&j)TWw7~e$ zVaYuD__GO?@rE}Nr8Vq~k`iGPxy;C#0q%8oISZSMPj1*ZC5U_2!$?d>mNUc0W$|Le2U*4P zKj{DHIf`n8qIspHisj8XZ`x{Ti>}$;{_^sP)jh&`hJ?UKZE0x|SYZ?pw@V_2f<%6~ z5|qXcn>4ik#z|My(9KtZd46GH9jtq7nMoaC4gYmjFjyd65|rpsT8pC=HQrkO0xR%j zWWCXW2|*r+x>UaX`bT<2ie6-z!8Lh4^y_dZ*j+&Q)o&=n%;KpZ}$2yaMq(&gy$->saf-mV!ua&u_Zq9*g@<1V> z^sGMD$H(cLS&WWE68U#uY+{!$LqYR#Uw%=3LY);0NTao^b=GimanXqIV7V~`&97%S zG&HO?=&qPq-S3}`fi)jwyND$ll zYlfSk@*Plg#EHY34szFiYYOF`XF@%rTtB4HnX!!XH2tA{+w?(usMa>k6*sH*lMM(`q1HyY;uU!C}6?kqRBQ-b-WW?e|37 zoXIHcdJ{jwD{jluzO>OVGPn#~{!TuL5WkaBmgw~6qT4y%-0GWV=(s0ERMyCyb}n2s-tbyRFVzcDYg6(H8-2+Qf$6;br{;`b zjm!Y!$aN}U|H;EAhsyKX*B@kRJTS+PlGj!9E#8D)yK~!<_j0pOv-XzSCnhQRxdyEC zCi%PQhNr*t4+FfjYzPn$4stl7;b0E_IKfo;oOTvn1GOjAehNSUvEJdp)mz8V>jEkj zG96L31F4K@d~epR7VGP+S{m!vgt!KI5^i$20ku($P4LS(==#L2HzBo7X=A!b0{L?9 zfi>oeKu5}n!dS^x`7)K5O5`mtm|0x4WN~YC4*}eow}k_`!fq){rYwOM$}PIW*R)?k zZ>>v$CsY3$VbDe3NJp15AtRkb&6$LC7G+)A(UD9abzW#Fb;iPLr{#8)!TGmig(LrB z)?r7lG5YRyq2$HaE1dH-#GeRF;K59FJr1D^*}|>1yOy~o`qZ?yEKHZ^HB;BE58TMTD~wvfgE8bTD3Q69QWV( zjY5sfjAsJ;n`34|cl{j`5VmHog-Vipzj_8gyH{y*oYGLJtr8w6t}0fo z{^T2MQe~1kJiR8#y^VtxI zE>U9WyD=X=K>*VZ9Jr#=OU_O!*`#KX1|Pg0pT9YaBTBXpdNe-wOT{}pZIfv_ydi3~ z?|vUk0f2gwwFF7G5rop&%l zN(lp6%oJQ4=6QElgK$P4TC<^AKLt+{Fk^aKpxt8%e_lu4w7 z@6Szn`7ut2Wl_GGc7s*e>5029B-+^nyHfFtUiY%Hsk~DA`Rb|J#z^RyCj|n^%%&>S z0%%2YpbW9(t>Y8BevxSYqOSKX6qQn1koj*v#GdfK3)s13sT#T*!QA+9rDlIb)$cqV zgqQhWV*>sT5PyF)iOJEc+6hq$DE1^j z$S3fpayem`g44*J8xENOdm-cnd!Ac940m_P##OEN+}?ZliOpyCJobBPqr2}00kQ&G zsT9X|{6aE~J=&k>0wCo7*oCU_JcIUrogZE7vZ6VL;HCDt(p-1&g=~{p#w%Ol@;~2`6FB_a zhFMD;th;SSqo#=X#Ik75B(LG*=^~4L^_c!X6^LzQE@}LzsVzuGjCUJ#SsTMs>&L+F z`NH=4O87x@Z>JkAoON)uq`;LrS1vMVL%|7&CKbfNufyD0m*@-$?YhSw%jDR=;EEf( z-%?)ryGuc(b@X+}D$?lh)cTO+RPTXWSZ%^7v}>yK_W|M0p-A}s2ZWsw07z9tiW#}4y%p!^l<=Rr7MoO`vUXAKLd>r2 zdAaC_df4#QJ+8y0Kspo2y(uUdyxTf|w>0_@-LMHQ;BoK0>U_ZWc)SDXTNO(#{melJ ze-ohkXOJ78Y5MaNZ=o$OP&JciGhS7L>{xXglLvpX1O4N%=>vtZ{RO6V@ArYsH1(FW zVuu(itpD?j`FTpf$KJ=YALu&$LUd)8i}G(39xV5V3n3`{ZRM)zW6N)#tZ75Avsi|d zOU}EvS!mzvOW*^=%(gRuQ~}#&YK|?xkkWpB2*y|z4*;NgA0_ZiU@cTU?^ciA77Xv`#w#P=+?f^IcX(#N2oIx;!Qoo@9~n;uTrql`en<7zd>^RTGKMs|GUSESb6X&EN3 zdD_T}6!Hz0ablv%2iEt`6bu^oTwbDHV%I8!Gg8kn;l~jMOhNtE*>~s$V-_vJpf$H) zj`aGEZ+KkI$X@rSgSNRU#oR8TbXNT&Q-h=KXNQN~#z&Z)mq{1+5L|9gOGH=DKTP%& zJn^GfdXg!^2DMv!^b>n=do3#UJ&o{b_UY0zM9NAkl=g$615cOyzD67Ee|{Sf->v7@ zOy!9T9Z);_qhK-v)*jS`meW3jgdSl++el2aKoxDj#c=10ckEU|C`BUDqJvAiB7BD;!#sEZS_NZ|`%iJ2!Y+HQ5>B`x%qrHm&4v^Ur^eQ$*{6>kS6!ugzPg=_q(i zw4|}%XwTKC${QJoHlikhCw8x>_2$vQ`tgyk!uJij{pI;$a>E6+&|mLoOJI;UJ;Q{3 z2Cvs=dM!`7DjkQ2_ll%8eu(o|t)z+~h)&ObxYpknhD^w4xSP_53sLkpB`f46R?M-X zZ0W-sFe6=T1V*oWAPT&IKK?>!FXRv1gq!#uU;=b%C(BQW=fyM zQx=yKIR?E>Sc}s^X>Lm3;4{Qz!9k8RDk4ouWsUy8p%fQj3%5JxhTSz8a?Fpmpw(3-Lh!lMhO|G0GyvV>p zQ1XcMbz#i(M={XoqAFAKVc_6#JHlnL*#HXZY&GcmDlqT#PmRphD%Vh_ssHJYFn_f8 zQ4_RAWq1C@JAYDDGqy^R+!Ur*={sxHVMG#dd)~L;avCk@>@hrXR2BL|sMtQQrk(8f zce|SXK({$X6^bk0UH3!t20u1bl+|yXRX)t`YaiEsD4BKx&81GW?%nruusA-&il_X4 zKOVc@1uh3^xk%}PG?CZ`&h)+gLgh6aQO zFweKpdQa^-Ud8gcO?B`-Z(PnU5BbF$ka#hI7V z<`vZvXntx_>%c|_o9FA^{dtTjlEOCE7PQ#59F^&HPo1Fr??y#|AMcl*X!{(ZgM8t# z`((%x3cTWUYA#iqh0(j5REN$#YSML-SzQmMGY<)|4i^ATw|93VtMk?3KEN5z7GDqA z;H;L)uE&^00|GWy6)dv0Mps9gtrgnX?a_zbedB=kVb^Z!xA zr$3;rpWm6~JzFP5jvGRM?(RBZ@M>!U*eMf|-WeR^t9IyZ@4Loe^{`RK%1$0Ar&?+9*!1Lx&z*4-u0b!-h?$Gy|6YZ`yF;!}cMsla(PQLiNRD&Fi#C0yf=8NymGq#|qzR$1j zP;I`BHQ^3R`+c20UvqQo*$Y8E8c%W#K=&~JR9r?@S@}@1JBMXZnPA8t26Xqgx#Q#i zEl0un_DGyYk44UZ#$S0aN zTq5f=iQu9evwe=0QzZppQzm+W$v9jGB$7W6Z&bf(eVv+1q#8=zaVA&}TgXLBtpo5rLNH5S3p zr4t2aHNPa|qk8Afgt4SgnW4gVs@-5(+UP2zx$^SU5dg<;@>!Rln%ws ztkIpHQgis1$YnFyB&(|h-roU+ul=P%tc}vBQQ32M4YX`bs@~9fX`GUN!;5=i zVCgoe2Q4=@WQgrK=t1D|2d;o8>!d(%h(HSgg}21 zV)oAC6bUl|Y<(2*aGX|@Rpcg?eXQ72X(8mET~@!-?bCJQRHB*XnCOT{jeCQY7dC=J zlnEh7je`%w>h?$8Rv>WmIvQPT0OC!$yOs~|9?DYZuBt_PQAa3P`LBH(fKGNL>skPnJo8Dgmht6A_ zs2a`Wu#n1cHefu@hHmpwBd{RIA!xo_tfAEY{G_NP3s#!W;n{ zG?8Bwf3(6ia)XLCILiLM`De905qW_-pY!R*Kz_6djS$$m^6YdlicskTEuqU;x4 z;t@ueOUak`QDyp>JE07qSa>pAWs5EBe!F5^4Yh@F0;LrhHdFf&sv=Bu=|9I5aU#4G zQYo_pnX9lj2u8AafH^Q2jHTD?l>ck*yV#CA)OGbi)s4S_e3yVb;jmNFC~F0#v2B9C zcwSmXgkH6>cj&x>^b?zns45>KTM^#fIZ4l)%G=Ik}%9Kjgl|h4nwUc5P@8Rn0K*rek70Ms{ z^D-TtN)&fM3?ce*dYxvOun4)PK9ALkr{<4Xip!z+jahtfAR-v3iUnQDysv>OIo;BH ztnlAzk*4-DB8m+l1sbeN)0kAMKoh7HJMU-rk@2)+u>sdqQ4S*%| z>CNm*jrE+`9J|u|rm@z8Mcw(OlN{`V@wu^E^_*le{BNo;99U(OUl-@LbB zg_dt>{BwZ%H=CHN!6%DvKcBs7?&FaiPA5P6EG0=tW23XXJ~CM33Fy9m%{*{s&~`u@ zR7mxAzWHi=EH@EQk_mpuE2NM1gCv23VP?M|y4tM&qO#7{tZyyLu+T)w{*!HmRju+B zy53t+(;f zKBk=NoK4=08)3E^4HC*{c_46KX7tKC4~ll9nPDR>fJMI zE6tVVmA;nfBYaBTM~r{&7U%n>1y%z-ir|+A+p%N|{X#(yBfa*a_EFUBd z*bVb#W(gnlnA!H&jmPO-5ssp9Ni{2@ywyQxI2K_tj>f?#y7f(+{pLuH?kF%&|lRduX z*AbJ$6mGPoefE|c`4i#9&8Wr)iY>ou%|iKLqsO7)0z3 zFZf&gg7Tmr(BcH;Dx!zXdIddW>4;UR$ANms%GyNc9z_k;jP(xr{j>66 z|Jn3mYIgZTvD++%W%9UfFZPJ6uG2kpjASrEKdgOxQeS^yq;I+YZJfS*nj0BePE6ON zJkbMV=Ks^O(5v~o=z>BdDWQr7G{!a85j+mm2!vKec@1@+C*s#wF(Hy{6m*7>IZWrh zDkQN6Xzs^HvK7zDFv zY}QLj*cJ@;g1$!}5+APHmPrJY%sxgZWv$JZ2_qZv@SE}kaS;|ouw_n3K$24aDFb}H zjZ|kIYj5IXP7I7$_?Ax0_7tY=`ecoaN-^8ttnvyN@hp&K{^aur=WH`otxKnY6f3K^ z5rga9@9IA?#=cthR!&kv)!*0bw@~M$JE>wenag<8>zexnZA6# z1Ff06uC>A?l>5Ven7Tp3%}s70D3xc{KV_bl!0kD>M4t0~?cF5&zSQx_c(JjB$kS5^)PdSjq}oD?QRkWASin#u$OcW%e^`18xDIE>iDeg=5X zw$gw3?*Wqq^l)uPIuvox^GB@Trg2=yyNlybu+r~&{`1*6(7f9(cR!ocm|U9)G#O3a z3DLgjP8_xC4;r3{sXCAuo0c5Tiz3nTlh)kb_HSAw9>@H}34k#Zp-s3V9V{?rv%j7E zT=BGt|9VaF5%k8xo-YfPo3$m|(E^ua0CN3t6=}+L-rP*ZV!BoJLeLF`%=dT6Y2RY4 z!J4X@VR?3sx-_IFpg@DyB2uXi-)ex%9X*cr_5~kY;LH@QB5}WSmJH};nc$6zN@s`I z8h$zS%uY|AA`H zZxt0+)2)rZxI=J<;1Jy1wQ<+R-Q6v?yIXK~2=2k%-Q9x+C#RG5+yCBYkN@gipLMZ% zF$SYoSIt?oo_eP7v2)!~Vjl`GBtk9<={_fYZK@nZ=jf)+NApv{F=j#uDI=hY zzO`=F2k++f?JgQ8r+CiGj~bdD3iaYm6I#dj{hD?JG)K*o zHCxWj>`1d@m-59sh#Yy$7STI%y514CS!qSR>b^r3`2B|9JBzO0?Dl+^w*LV`6z^$7 zK`ED8EGeu=>CU+xL|qP3TMqf%r8y^*4+vFoPA!qBpt2}5WUV<=B{nlT=Fzy1+Iq4) zi+zi}>?GIpT?lgmcrQi`8^CQ=XwFP**+)u9l@6^TWBvZ10PEMXL$! zad&b%Aj_p&KDJ4VQ;|}mh!{QuYp>z zlfE6kIg88Mxx+`9ObVXXhdPH?V$doRMv8P_KW|*>BOC@f`j4yKPUM(jh@76HCVVv7udp?RS&bxhPSbW3fm<5H>ws-5wugZRIWSy(ROKb~3E zq4dqx5!mRfFx;IO7hEJKbp9D%@K-mxK9DN+rom5T@M6!KF^b&<1IotPM&vlIz8i~Q zm}SX`!)ctl)gVoYWh>LD?jHtaDS36gI(Tf``E;JqvzIuf0U=^!3OFYXeUv`OsJ5@G zAFPNh%Ys$!Q|-)+rx}cWebRjhQA-NjNp)l52(0xWjw$I7)?!^ASdn#PC(^{|rVBZU#TU-PgjWg6 zs>95T{g80eCy$GPFKy6E9+tz(Bvfp9&?hx2RQF{um+Kt+chdrcB{Apq-qQk>=LB}0 zwiHCZd)BQVLs<#c_R2wxm+S17i(gQRuM`(+#FX*gRe_SO1c$)Xq=fI^KOueh$=5VD zr$Q#=iPr6KGu(ecT4}cBt!FWaJs%p7%uC>uc!sV%6e;C@Xne`^TNw=5{n!e$qUwREfjz+TR)V^4iZP|1mdx-hYG) z()PJzw%Z>)#r0J`)uA=+O+yyd#r_Y3g#Qa6xhnC~2Fmtfzvp@0>uCpbn%QdT>mM_N z61`OIGlvx{B#o^*y15jQ0FX%4nBXB+C$0jBQ_R3%au!|BCz1-RJE87cPiJUo>bA`dvnyFHV#$HaqYok%^b~S=NFrRPC&6Fj`O_w7xOY+NRrz za2uQZ-D*J&KH=7A#~l2a2YJjh5j;3t3uW0^c(YN0So5`LL`75Mv~ZiPM}F8qD@X7i zn_QcI*OkUOxl-!CnQZpgx)ZMW;MO$4?Ql}9U({oAA}bl=0%)IbgDN-( zIW4V z=)WYUpwwSxV!z4`SYa3Vj>IqcUbFRrI5UDy7U_8a?P14we-flz0R};_i%Fzg){#>| zwkyKSHGhbpKj%ZJ)Am_=k!0U(?@VD?oP>emO`$5IuL!V0gMXP#4u@_$T75|k>IsKy z{l*-vpEQgEfJh6IK#Gmc1F*Z)(s`d1`lOf z*%|7&0Ie(dS%E+>cGLTp!PQn*dXE8E$#i-|^UZ#Sjl^%d9{13&LQ+wG zpeZkyA0ks_a~%tJnxTGtD}$w`hZ{ug-N`@D*!wPd*78L`V{vbLR#|O&_mNC%Ms%OU zD<`o~%AmFxMoE+-o~$BDkcHX(S!~Hwae6S6;Oa$04PmjmO2|o8=g;t!$j6Dq+W@e< z&a0B(q{fPi@-WGjEMaKM-UO^si#CI;qbbV2zWD79WTe)iDj8bx@RQmRdw zViL*IB^F|sT_eMHRus88X=8)T8E}<7(#a@zacE|U$B8l@D_F|$hcQkRpFJ}U#N$Xh zm1rYoqZ9HIt92%4WLLeQS-11aZ$3&pM@e;)ODy$b*cTLSrN|U8E^o!OGCrB&kv1AQ z@Gekie?ncuRx2x}Rk9AIIv@3!$ix_}8%nBG{Y2vPuCFzeO`nl5q}%)KvxWFlo=j9J zgv${bEKE;-Jic?WyC*Io?n|ynpUQI#eY=LWY9lc{MUk|mlTsO<*Jp)0W(WZJii(Oy zB`LU86M5*wzy$f;aAqv1GzP_<-@^iCBMcyi^=7Bn7_A(zB9Hio+P7&5J4utX$NAe)n zG+5GPX{xaYCG#i}>_S!ggpyDwr4+_2X+W1$g_f@Lx+u~V+s_E)CGrxw^*}E?#`hou z^3vu)45PMiD*-A_GaS~1IY1$_WE^rqVKYE!4WR!-B}ZjDELVwTZ=+OyfK3Ij4S^?$ zL}-QU$z}!XyKmvNI8s&jfvYTqM*5>NT`a~-bpdY|^O-{5RXw!n?n89E;L!D>2FYTwEg2_ax+*pL{Dk>TR|P_oaK9$mV0v68<1a$?T1 ztg6}dbJsw)b$oa9CsI-I%%1KQw4p+l;u)!CYm68-Qi95Y_HEypj#zr9%K1t5!bV{u z&2EGYeE%Vdqc8gn1w1y_rl?KaA9a1d0I?Y+-kwhf>D5?iMa!`@5r0IhG$!Q~YLE}< zZK#)B(QPRHO#-xZJC5#G`Nf9vDsqsiTeQuPRI&T$Z2WTRa?e_CmXma($Edd)up@ol6G1O5Bf`^O3mH4#dsQxgZC+9o9(SqVZMqi?NIw z_)%$P&^4v*CcYD$ANm4Dnb~*+$+>By+jPY)v;8#y4ryIvkvbJz~nIL%4`UsiPq(;W%pmYtPV+BG@Qkc*0RS~%HpNP z#6R*2Drh9Qe(9i-URDM4HaCnd@ z2%QqBbhlpQ`xCBa6uLzf=k^WpPq-~C4#Y}m%h#_6h@HfH5;Cu-{yy$v{SiY5&zfBU zq;K$!Ts-&-iD^Y7pH69#O<0|s*--@~={4~@X_-O{yo8Xgm@hLT zMgF8NA)wWd0F$~XQzA(FnJVzJ2OBez zo_|WS?lnsF5f%H90eO^4O^KO+u0$i%VQn`AacD9mU(W=apahGBc!{WJS3qLX>|99f z?!$MC@&=)|F<{m@eoo9IkZegIF(M8Dc=DMg6!*loqsAq>8O_^i1WhltWeyhI|N6`S1)Pw7rX&Q$egTJG zR|sdc4!t-|;tKU#sxYsuu<$FZNCR=AOTg}gm&X&ZJM#lRY{p0>WyRvc;CEz>SO1=n2Rtu&1i*N zAz|E!S8*gD0BG8kOKLYorbZTtf61y=jcfmph?TFKCzh519IU z?Oc39oC3WJszy;#2J;%>X2(S(mw{DoxjsQ$)`=hSfykYG17D&EF%0L&Em5EBgL->@cLVu#$edc z6}A#ber@gy|5~5FCg{&CTM#taLcLG{!F`N2weVapQg|8sYy^bEB0b#yJthA>nMeMa zm?z(U9dLdq$ZXLC0xQD{sQ>d-e;=YzLB!~Pjq!he8p!?~@BjYJKl2^<=WG8j7Y_QL z-}ZmGdec9H_O<`k*#CYSf&{_TPyd&TiSqAs{0}wzuSaHKkRkqm58~gyqT&Akp@59A z%)(-xRdguT{}d+Zd52W&-+7D1B<*)>3p_&$ZXaVK6K3N1Uz6zr_aDI}%>H5+V#1Lz41{g$eP zzLiL)N;Fk)0f{(__P<2$07mw&rcA+_5y<0ZE@hJ+gkribN=&*fb~b`9I%+yvE{-k@(X~9 z{Yn5D4uv_$3^s9SpzO{l&LPifmsQ1yVd8!<{u)Sm_0M86+hDdT0X$mziP@V zma_)kl`(^#G)Rvk=jxI(n=!;XN$V6CaYOpg>!^EjD*)XhF*FdjOxFMhk!l|WWi*wZ z;_ZJeF6=LV6xaY(tXbGA@qpw*RhMv%hU7&_LYrERN=$=#t3{e6h%I}!?Z?VQoHmAo z-KQo;PgtkZKqsvqfhO)u^6iR1=!wO;#)y}TYy*G*uo6}o4KMZH3UScC-st|p&{(Q} zsooI)2G%1<4r7-%gw_NK+5T@~ecl28E3JipV*1!zGOQK%9gOM~{C&F=IYM4!@iJ7U zX{seGaNy$b@dqu^7?7y3B1Jrt2k29z_Zag& z8xEz&EVW#`x~x&}4+Z`zZ&aSoHOf|;qrS|Su$2^0kj3Uqd?3J8*4I8+TzNYz^Y0yu zyJJT4#Rb6s4;#~pqxiUH*JJ_-3Ea5GsydqmjyJF`ge#0(cO*VEPEAa0!P@ZZq`=|+ zv}3?dw(+i%aW+*HK|{nXCillH=2=IGNoM8tB7}`BpCDpVpK<%urG(H;cJ`$`c!%rr z$|eOq;!l!*n>CC4{B!^Ty6apQjT}{^IIFVtwzSWe6p5UYN@_BeFG0eG4TxiM$tmi*uWc^Hr?}v!S;=9Wyn7vMd$dt~9`Coi=gveOSui0zBw z7Mi%48qM@EzdF06(MtNbX${RCC`0FFF`Y`(!q)=8rD(4HweIrJ*uKQz7VL%MdWjrZw}^FUyuYAH>dU|uNCajcuD$7wWox?^iuNh)$Dg%Z zFZ3VFpKbpKaSS50Io?8OUgakit`>WWX5%J6HA(o0i*WB12Yd~MW(SAIDa}fNYVU7~ z7j0+zD$898EsRb=9INlnJAarPHLqKJ>a}2cHkd1}^Js0A=l?*;`r|cZ^snfc|%7Vz5jp`4QH2^K{20ttW1wtJuNLL zIl7xCKTn0fBn?8K2n1(1ALWC>#pWKg5Dyjx@UR*4(oEvWjeKEnYso!c`iq;D$P#^C zz$Kv=1+^gbliQuZZsY6-BSoMhlHEdqtfp;d*?n4fC@KMsYCWlb#sO0HH^4F{$r^70 z{2K|S(G6_uvNj@r@|2rJC5`pu`fj_eCLE+iyE1shb~|ffO{=Ix%_b`gSX=dkQ4;Js^whhe1-L;_h6+^mBZz09W%dOEg4aMHV&5-91Ee=|WB&k}` zSO#BvsHL#G9J5@OKhiW+bPLjm8O%KB%uVenl&~fsWA-JPH}$*`mp`qergfbt++jBQNUPN7DE*P(zv$H1Io0{$N#QiOwBxHRL6l$#xaP;r63gw;~|B9~;Q*Befy1fN9c-XD9% z<$L1pY9#+JFyvbPv%N%NJIxn8%HQ_s4i9!hK8Xm3&<~mNHi)3TPv^IJspQ6b*^}4F z^g2?rb+oeGIUd&=r#1P(SpqKj{20nSF8*SL2)ZaEGI(qREAc!urxgZwLJ$eBU)Y zjzp`T9WX&LR5UN`@?$IKqBP639a)~y5+ql#3nLNRU5a&zJE#P6;~NZ&$yWGrVMN|& zkAnBGHLXWH3!E+D(B`pF^FmV4u~ww}mKG2py{gqBYRHG>CMLL|B+`|-7q~%ADHR7S zWkY84TpV1b2kr8uWuEFU1@a7{G_KC@9F6KE4PsLIoyY$_@K7iBmHgFtdCb)ReY7AJSwuvW5#0|TZ> z0wuyNMvU5?OmRv9Yhp$id7%Kymonk$PPV*HsZ-RfT+R`-ZghCrN&^YL>-A=fIv%^L z+XlZsAWn!!n6rM6hvVbw?op7(M9^37Guh7;d)#Ji_nB${V;nEhmE_I8#9k^cf=>}) z#&Bm!#CTRMPvilJ-8oCi+tTrSsfcTa@M}B2x^Ma54x?N`z(cScII+BW+y^tA{jwv8JQRU3R_yT3SP%rb8406!hv)IQ2ZG(es5`2k0==6V9iOiUw=z zJ>M@k4UoHY>v%@+fp`6+sNrdzV^>T}*#(AK2mpGUd=9>R(L($({t~H(uoyS{ncv76d_9bYBX(1*#E&QQ$Ii&7C8ZnBvcA=GsfLEYzGs4b3Fnv8xEiwI z-n>oA>j_Udgdp>qI+*Z@b4fW0$?CuOvHq)HPRJ?6AF#B;_lKop5Ez+6gQ@PZ--Bhq z{_3Kuw6y1m5pqvq*YHtN-==8}ZQdxq4$gE4{E^!zYw0J6Cb(!OP8I~&+S$UDpfj=G z8yf?PI+5`>(&*{^soN2-C16$=ytRrNAtMV}JS5j!FsQMkmDjT?c@0K z{b9KAzIZ35N);z1EFf1Qn+ILN=RD3~Iw;O?=uKvJGdC?DTfC%OxXsd}NjEJq$ap0` zRhX2;kKBNQw_n4xU1j|H4G*4*vT*^awJWG$+ZYC#)|d5BRpUl7JvssZu;PF^I8s|?k5pVh6Os-}$-z|?b9s2GmW2Pw}%5;{E=G8+LWsY7<1P}#D z!*_6K&WJi}0vkX>H|~O$9Y(;D(^gl|fD>|Bxsfm-Y=h~zB(W5Wm3t6(w`{l;-KN>P z<0PBC5D>ukd_FS+d*C$ZJSvL~XQNTUdeDG6@Zj3?YoF2d0#8gstRKVv1!kZ$%eTBk2Ep}BpoIS;4JZ;+@ylWS=ylZroAN`9 z2+~U+he(XS)9|2R$7$pQWb+d(s7-eCT=2?{tO`Uq5T|#m`uygnb0~0ZcZ$*)WAA z-4i5)mLFfZ^tO$N@DkZ<`CUU!;BVZCI5#|~h`dg+G`$v`)Ix7qT$GZL@10i%Aq9$} z*&nM79~y|*jGdu^0g0G^<=dqp2TRn>jo`PHeMLf|lpTbB5|LgIw1KOe+HKF z_)d0z_a%Pa*#q{?J)?i9Z-*OL7r#jjc=0C;u|x-5JfutXdW)Nsr(cgB1TwWj+YSdhqT)*V%X4CTjDNM$U|;;q^k>NteSOw4DP~D}s%Ok$3Onwuk*+ z6@G)kG~0qhzbI*pkQH9?wo*(Cw{zvTW0g#gRkCoQ<7wcYyT{zlr{&d%i5VWZWH0ez zI`9l}^D!Rk`2A4M&>=m@HB=rr2ZoT>RpMx%GS1YEpO}71@vYqAn(c>cJmH#k%aK_T z)dDdIp_TizpU$D8Es6&W?~$kHO0si)VMUdygCHG?-TdZmH~D={}J^$K`&UL zHq>0f3?F`NqklvhG3)77a=}D7P8m?65iw&NaNy5oyOVDuPt~t!fWf2vdjr zSkPq>KXk16h2BmAyn#tw6jj5=)yjq`7ni_N_CmlF@zwpRH&qVb;cS6M$OI`+2RJ<7 z0RJE-caqMAD^sf%Iy!HbSKlVS=Xn8>5&eJyx5Q^-f8~C8@otl*449T=0QjeP$~ysG zVmiVX=?h}tH4pF~Pt+4`nH09#L=$9=*Qsb^-pP}UB}*fbpTQ34F=1x5*D3Zvjc>m3 z7#e?t;h%3s!xe=Q-3N*QhLp9+07JdmZFe&Z3(<(%Uq{<5R~JIeF)$QkUB(M#(+n3^ zLwtP_f$g`{xwR^KaiK~rJMZceT4&k}5g!F)aW^~i+ITTi@I$;;tG(khhF4Ni4sfQY zEn7e33D#O*u6pjUyyA!*+hvHQvR3uAkaE7^6#6Np4!96q2^H8})ygq5jvhqlOGyYF zoXHTPlmFgp@4QWrZG8IDwv`(%zWi1rdlR+%B!!0i9J1FA@ExorhnpY{0cb*F0?2R~z!fK@)UZEoUUuF; zp+eRMBroU?e+GCL6>YYTe`Ab4H2(Z97r2l+e7WKZ3eESMlH(yJe_M-i@m(2Bo%3)) zITmo$qFhAvXGc}i6d?7-d>24P0mIeE792G7ecDsY*h0Rjuo{$`DwM|f z;`l}u%Deng_1P#Xv6>CL)c9*p1GTguAa}eoQv~dk1@Mw_SAO5)uUY2$i9e;t2#pO@ zp1N{p{1ye5?+*nPP2no#OeY5Tx*!MTd+_#0B<;dLcK_2;qa-)(k+!ABW>KlWcAR$Yx*8AO#McJmt9@6#BrbGlG`S>>UYP&GI!$X>j}!2$+(XKw9PH1b6b~G*dF;ev^Su0nTPf@hLjbPMVxWZ9l37i zNr*ffS2xK>i@#6NU^`o>PDm%2D6{d6rzf}NCAYMR9V0u+gk(>VkRKUq0)C98O`nRA z;sNKCv1n+aZoET7wHAdJZ|SWhuE|liV)(J)i(HHCd^`r)O^Wogw=K$QY43JZzZY9$ ze>jzqFSoq&48$1t>9_OTj3lx7r;uB|d=7Se$@m8W7vYIzGC&{>iAU+*TG>jOZG|mk2Vd zU%xhnOc@#){pFcKWqTy8Ab}XykCI1DBWr=lQ41==aYmbKaW{9w?_}MYcVO^2rQ}^j zyyEj2Uir`q#jIuHBcuXZA|>^x`@EEezH=C|8Qj-KZgfmz|`J zSK9Rq6h%i^3-h;%)CN}^-*(?fzxka}t@LyVcIy&ASz-jeo z2?vI6kfhw*ES{pN7n)LZ<_Dq0C_4pBb%o8{9P+FWYK@%Z?j9;5>*fsC8*U!2H2Km- z>QV*gI$2_{aBqb(VSF!gAzb4rG5T3BnC?D$XkkalSeOP8Q+($r33&G_7J?|l)1c=7 z@3#`I3cPKrFLrP(vNKySC%DVBA-ZC5@1tmai>!1UJ(LLs?1@3)>B^>l4BO@=^J^m} z43c|2LlN+I66g9p5q*3J{=NbwhqK0CVN>EcC1$J5_&uB=D`oE!FDRnb;2s0x@aUMW zlF#=m3a$GduF85}#@|%Y=_*B{Atg2?<+tG-=n|=ipG~8I?vK7tzli;bY3(|-0=3wS zZu)SQaT9u1S%y5>xpF}$gWdIcA>kLH$yC~}qaYl-2$+{w(Dp-S$JpM%Gdn*Y^8spv zP-tmGRC(y{B%xz&`I9Hjl(uK6Kg`%#zUMVHA=%p6dcCQ5d-LK2 zmr`TrUh1a4B`-wbS`~} z>{Ff~3$|s$CmX!w8t7x4t4?hFwmSj3Ru^XFRZ1`I3Ep=LKaZ70m`_xGNGl&Kvcj){ZW`w3I+U^FK5>Y@Zxnq{Vbd0|wYp#_eoSMNN==Wz?YDA|Uj#`^GQ>rR)v5X4|tt;gr z_2b4~%Epc;GoTz_XFr)RQz(U!<(kXrd-v08dQQK$9yX`o9jW#Iyw1v|xwJu=($moB z>=Un`RD(W#U+2u|Yg1L+j5zbcC9hU@QNzV_aO|E&oXDf34^dF&q!GMjEfx{7RkO&;gu>2rmt+k^b`TG6c0Xdb{v6VI2q22PpV3MjM!O-E+5zHbzjH~c zi@C>ADT88G>Lp|Wdar0Dj;cs6KKI7U(%n5MVJL(H-TWP(tPqm6BZY!Wm9k27Uw(cZ zoE_jyR6w`i0}A2+c^YjB>1m`LUwgzAs)dDxVi4;#l_KNEP>I?1@0qi0<>hcH=CYt- zOY=;Qb0)HAdyEdsme1dI#O3Q^%UR<7c;JwXJN&B(Vrq|Gq%K*k}h_ zLBtXY6!9)U(;*c zU@y&4JgBq}w@3_obMjaV4o+E>eCy9~)Rh}Pu_lx}MlC5+<~xh*KmEyP3HJ!uRl+kK zxhJ|un75{L1tMgrcnvJAM^oN6*Gb#Gz9<5L1x1cFERq1#eCxKNTyh7>Au+5CPGW0850u}-{?8~YExt*34-e+QOt8490@IF7QC)mJoAOMhjcl&VA@>W5 zg5RV{qEu$CG74qUat;!nDh%k-0!#`dl~bLQ9Q*SFtF?c9Vu3D?KS&aTuI+hL;=AeU z8FJ;^ERj(C`GXyTdN{u46XNmIj?J=!a{J}N!n@$)65GUos9>ALrPl!4 zxQgbsWH+bLmp&!TJQP0cnQ*cVRB;x${%H$R=N%njOegp$})MNytsDrP9^o z6;?JjsG1(b?&F@!>1L-WrM?FFOw(j@eaFrc_zgMD_rOZ9LA$@Zg4#yR9U{@@IP!2j zb2TQz8PlJ*GXF#d674}tUWt4})q zhgm|~MFfTMV1EorjV#5RAoM96{x8WAIx|d1-BzlftHJ+`p@-W zV||+xbF5wv=f)r_TR5y1`)^dRy~4)*@R*dAmeyLN{WS7%^Ss-6>TS;{ZMN#bd^Z47 z90?yV`cs4Zm=^yq%riQAZHTZxd$g++h2}#d?Irl2UFp9R9}4Y>F@CEbyVG&48fneT z89)g*!@AeSVb5ZkiO}AYYnKi$)^)TwD)JAByZqO<@(gY>r%x@qhFf>-Q>_2 zbi~A*!e6)wc=Qd3wVDM)1EG#XB+jb!7;XVXhtgwiNRhhE6|(|`|YKx zmcadkWdED-q}#&$Au^D&=V~L=HMhFYy2l%J`r}9gMExr4<}B+EHc#R^T=eR>5c5U` zY}xUm^KaK4v&`3x8GjRUVmyzIaE|yi{VN9O?g!exrmU_me+VtZ-RJVf?o-7YF4qt~ zUCb+hRQ<~M?nn-FkPANnCRTYan6p|~+05{WP0|Lftrf0a2@>q%JW4_Vnd!7@nP->J zxW1Cj+1Yo!u=w3AOkWR{66cpDZRc=X)(8O7IOd(WDY;^VTcQr)s9>Ea__odw_#o7 zb*{$u`&@sg5k;f${6zQw+Uo*n_TF9hLOa?e{CJbJ;=A+t*X4RC3dWlD`iy`d0SoCo zw%X}!BhMeMedi+2StnijuTOl6?5&;u^G;xJ4=3rW9gWVABaBvg`tWGdaGm#~o6TlB z9K@z>;sI9Gm}y-Ic?=vJhK$983A6E;DqSWg3i@!Ir25Z+vq*6hF^SB#y)$_oh7*b? z`fqY!BSO-mx+YclNZ%mIJi7l3ji8$pGqD|T_R)-mEF^n4WKT;c3W z5;1bqh!Zzjp9{^TOmu?m4foVPO$|$EYD!wqJFCa1$y_BSk;@?-g(g?W#AHL@a9y&^ zgrP}^p_Q~L@qp6B^o%`6q#ugo;Zl+J7|KsV7zyEtC<@Ut0suu8hAHyjF7Ku?X#=e4 zZz?c9T6`P2D*KV6rOyhC#i?=C6L%Gb1-6osQi|Xgq^n}lD^gPkLfpjb&GCX+<{&M1 z(=e2h8TBb5#*Q)E_&eHGpOf$?6QW~YRKcOT%VJR&6_amLmJ79=HmMwKe%n=Py>oo? zJS%;=`TZn#U77mWm)6ZUvH^wnoO*}EgeUkFd)2twcdp@*2I_*n`eX8=)N;)s8A)9dd%VEY9<>UpDf zwAg)mKj;>9Z7%4Ek>j2fd@%0$Gae2E2BV^6qzxS3NQ{LnsxN7?E zV82$JU3Cx?!e;6ePS9iM-Y{y=966oNMj==U+88Zt5P0A%N_PFkwbFQ`7Hw_WcTc0j zSF6CRS4FPMKu+EO;?X$buh~42fgNB~C)>Jc zDXPS7FPmceX(7I!o`tKU)ykstyCpm7M6G85N}{wY8yht#fPEK~aS&04G&mg@kyWuD zH98<_9R5O)X)=0LYEHMSniqEVwF9a+cb-lPuZ6DYk`5@VzCPg~CJEf`Mje%uOJwWD zp(72|{U*#pFc^>MHA5>IAB0bx$O0Q=!iDmn*n=@bLPTOD`!z7>K#5R4N*=++o`^;D zDtzb&`t;lPu9=z<=b@0OATdRm#rn|64)XI19zv!?lO0zH27lkRR!m}lxTNX)*8@j_ zjV=|WjLIz^C`N%hnaWBn_fww}nCi?`*I7s(NZ?%xYvW(Vd ziO3K)*Vw2pm9PK>gxsHHOU!nLx9VSSTM;t1t-JV7cs>4k<)|4RuG|^~vGCE`{J-h^ zUN7c7?jAH;seXa7qVKT<#qk`XxRs)yfwd?P{QeHrg|0Kk5}=~S>y7yORk}ej=K_+C z<><pqO~1gng${`ltt@1I~EFPC7T-{coQFdBGx zjMix=UaTPZo)*)dZZg$8qYtz7#Y$G%-h=J6zJ7~df6lb(l@g(IW zrPYYLEhD|nBs$_`Ndkcw^aqyx>;p#=!-!hy+Dsskt8oKQ;uPi{%a^fV511P6@#=~^ zw~{YW!DZ9aUnPPvpGg(yrT7;<)4+Sluo6n9#(?cAA=1(X9^(+YgDXL&p2}X@NTyD^ zsi#*?%Fo3Mzb6Xfx=T2)@S$4qVytBJx{jFO7ctILmoama{g$IH4jG`IBUU0Ci(Sa& z5FC(8yq%Ft9On#IC@bQ7*fSeUu@)d(me77lIzGQf)V*C^#4pBE6>QS32bA9`#*pv# z#yNIvWeB50no7vj%5aWsEPO5yw^JWe-g|C#8@j9`e-0%-MD4;CTP9yj%0yoveXEwp zP%m#pZI~=@hKBm4L05!AA!hk)a9jYydc%Yw!sDg*Mj@#M7pqqopfC>5k5y4FeAb;O z-^M%@LFNZ>W6LEmPbP~U9;a>Q*9&nUP}A=(X)E1sNKT2N9|EIv;AIdoWAJcP2smU< z6-%L&kTI!k0xp-^QF6r9Ls8Rj@I4>Tao6kS{vmPdJt0Bf?s<0uhWC$dXUxPtisltV zmwW3L!QjJ?8@m%}Rc>zIet@d-)cc;R-@CaM&^d~77Az-U(r;_dX?R7C2oZb55)HgC zE*ZTx(~lg(K~ z^LQS_uCpDdv^?Hd?v8<*$_^$b2|c?lE;2#|RW9!hcz>;Pzaly<)nm_Yl)MMa-ETzw z$^JjADi^9A9*)DV$g+O(wX$bDE77&g+tNTw zA8#agLEs&so6Uh&`u!&tivH7QMSKPs){$npfgcphJL}uOW$3zontfNusJhic-d)aF z$j8ehzlk-~WP1IKnm9YW_=$M5xYCO}n0y|i2{N0qb;j+;1TJIy>dP{h<@_eE`%W8Z z)3f(`kZ~d0U__#LpJ-nCRpXQ*R{teOGHUjkDzgYa0xL2ahN!eKq7p*pX4MLt3o(7x zT)utlDlgSU0k=znOQN>>oq>;hc}RoUPc=}BS9YLMoLrS`N{s)geCl`@!r!zv4f_j@cfs#EX-n=}}ANf-d%Orabn~+HN z(86eT{*Vy~;0vbA$fN82L0=cz4$3)&viqPm14J?Wso1{Mj|U_q3qnrh{b4!9)rlWm zg4wiUOg%@g!f6#g(KRMDV6@ImKHkc)#pgk2Iq#YZXM^1J$jeo&VD19fYIJ&D6q%V> z?DYEaxNJPb+(Q|;ceZ1i*04p)+3GLlH7Z>4%>1hY0xd`AM$+nmYIm5yA0k#)NE7FzS%#VJagNp_WM!MR!<&O z@e{L9LZp1kiAWAh@$qJP@(EQ+6^7r$(~JgVIE_KY0*uclxTS8uL^4rCF2E|9qiDaj zmkEesdzghs&0s&?cER(u*bF%Lyx?y6JbPxZ^vEc46~YGx$%)9kq$Oi4}K`;KiL-7{t-GxAUxi@w`}%_FVs&)Hn9 zU%CBQx$TXu(_$l`?_RnAgD6Exyn8!cRx8RlEY)iC2-#`fYLLUD&KZ(cfG`ae(_6llEjBV-H1(PIo;5$l!h={j20 zw?3(A``6WGM5+IS3g6v%Zoc!Coo@7*RW+qpx{k*@DXZZS!G`niAdh?e?Y;@mD8(s` z%H43muwuv_u_Aq>slD6d86V3}%cI^cb_-A^tUXVt$QP@zPPueK59WPhO~_TS5ePGE zbG9J=_H%8W%b*;nD7g~S6!|nj%r1p1hPWbAO_769YNzr4A?qxo+KSq3-If-L7bxyl zDDE!B-CcsayGvW#-QC^Yo#5{7!6CSF)9;)!#<}7K|0(SeHBMTI4(E9Z3OstSYL#gRG+ z7f2DIPvqT*W$8a(C$Az%C4_r#H@-@A=KLC-TUScxROykl(}SR{bX6kX@nGFtW&m=P>~>@02^gOQ9KPAXvz#GoRivyq-KD$T+>i5dpiND=?00A) zzezNN7Jr;n9j|Px{G96)0vaz)q$X@lG|7#g+*v1904#mgD|0h2v7MXc$Vio3s`F&m z@w`QEznKZ+aN7EPXv{AVS+YkU9^7T*(_6G!3&>9lJ-oOO(zPXogJPjk={sS-I+Dg& zw&JZtj4-pXLHVz&<&3Dp6hM7%6|2?6h= zOJWn4zEiHwAcTFj^@9RqvgS{##LxMS`&F3Z}M>c;9#kHUG)*axz=O+?M zgf<0tzFm9oGdTVo`@uyF@u@!JH4MF$l&{%BxE4cxxg~vaCR%_WBUgc7DS1i zq8RDJs{*y17%@U1ocVL3{jN$OAHS3aHu@Bs>#htjAH9xar2p~DC(LS-{p4zDNZ}4& z@RVxwjWk;sceOk3T*e}AlwzOeZLL#TU4E>9vt7QQ>H&04CuC#t zc=+IQu@tCc+ff37y;yI7fYmF z_+o4{gXq-ZD_$)pTzRl71*ZXhJI0n>V~vNQ?ZAnl+khuk*@6_7q~jO)bC#?`!)@){ zak$F8fQSIT$1-HbNv*0d{R>&!Viq*$Z6eO?I$?9Csq66z-}@nNJiIq0CXD~E@9Gcv zvKKqefU7h0H5}|D_ihbl~17DrVskiHRuHC&7{=8h&eV8 zU&C%R_ac$|d{8KgHzeWS3!OZ3lLlVg_J-WdYT~Pc|K_$dt`ev2T-Gz;QVVw3rW-6h z&nx`ta_5&<0L9R7xt|`q2pwL_@9*fTD>Zh*Di6C|4~xwf1GJD0>dP02P{avsgBfvy zL0D#n=lw!2RV_ztNmdrEUKNJ6YYztLorvN$oJ{=^xWyT1y+@BYE>!;uCsVYtvPt2^ zUJQ!LuRKnNAJ}Zxej}bNY;OtRq__0(lAqki=a&u3JydiQH#ek_!kP|IpQRCEbyot~ zsvUtYcyI~x}{XR!l&Kb06g&%M^?QzREjb!CYu{QANpHxk+{D1wbs z^_7F)G03am@|VRVMrbjwmf9>~T!!6tD!Fjw*b3{B58*h?H47uZL>?7lu+&HP)oVa@ z*}?VU;uB)0X+(c>jpz2ep0P~awcLDQ zv*|cvt9O--Ek=N=-;&g9=t)Uk8WQhKKxyggQDdpJlc00UOdCJR6jfcPl|;oq@%Q4* zqvDvV(tpH~8O{?ePxZt0f)Sz47h&nCueX%kF`J`7-&+~ce@={Wd+%tvY{Se1o@cBw z*u~OU#$6zqYh9Hh(Dqp9^Nw>oI_^%eT;hF79BxJ0lsp{8reo67@oRouVsdOx(@}ATy#L9=mAd=_& z2_3mm6n=O|MP@jCVbL9rp8p*|$LBmr{T^%)57Qb@6jVmRNwEFSoepm@CAbomrU zzqNIaf5_>BAkuj#e?gj`QJe&es%9!qEa?>B-qo0MIqE77uuPldk1}cLtb){Uy`9p( z!ChnOO9g7+KthR2Ca``ySW&rO^v+kO=h zMIO#9Xlx)9*JiLUiuX@QToLK~RIVr}H=LSR^G|_-Z^QDGg_xSA8g78Y{w9uk$Wvk% zQ*C~Qlp=6q7kK$J+ST`b(H_E^wg`_L!9*hVV6~TQW>JJAnPT!%9YiT*+xmrlvr*A? zg0(4f)-AEn&bqLmO?+PP<^k%TK@sID`P_vInq@I^weEj7~P9^xqy2GJL_!>YV@ zwVL-AR;T%<5hmOhq@H4SsbOgW`|8UfpT<V?D$1fU_jU%adn z>Eg9DYTpYs^h5bb$wt4Eg^`;#PXI1v7|e-v-V6Ta2W0hE4-nOFCvYF^ZdaE`-bkJU zfEn@SgD>>sFyw85_?CO6^hg|bR$NtnNdR|kx$Z`syf5)zWB-x3>W=j_|BdYRoG zmv!~mDas&ldu*%v+%g>E)urIHb8qFSx#X^7XpjktO5#zvvqTs_BOyw;U!t)Z13;HH z?VV%f?8~1LMS|D$qH0edM*HK+D3?wncql=s$f@1Tr$sf-a2%K`~sVUP#||9eLJKYtXn|AeaUzbZ9A3Mt zoAX~dCT$5Q3!-5nxUgBdm<<~t<{rBP2bPNbgCqx(0d0Pyi*-nMmSzCR=NcZ5tC~>6 z`%iREtGchRm`47=0xYD>Op)i|VbT5(a_ZN=`u^RxXA;vsr35$;Ge=&8R>)KuF6_6B zIR||W^xDu9R6ZFJp^I=slo@|Qb8q!}R7*+mPkCv*ye(GYc`W@B^*Lded4MjjqG3Ua<`(Qd>spznp_jYYkEdmxd(!$XtG)U%dX=Ksp~kBv)@@lAp+uC z>e$B_`otOL2k7tAr!>D6YJtTzpP9#Wol*z}dhOA0)0KLuxZ-l#1!Jr{#tX(;6|o^r zL>eWNzigY%ZQl0fe8cB2+W!b~KYSa&PXDP=v9tGZEj~{Cc2wn;`RWhsJS}# zv>!-VB#N_U===JJ7wgklMySPD|HUxLn;uby?fgnD>VQ!WZy-h!N@p!a&|ftycqGRH zRnN0nBAy=A*wefqSwTES%(4)?7+Hmm(q`|Ax+5AP=0hCGY=3vU5pWODr}10PLN?b3yZ;YEVa>jD>lTYO?^PG9SS~UzWDNinm2Oh!xKBi;NoOd7tx!vpvxl9cJak3uz=+N)D`e=>OS$Et03tAJ8aT{ zofHmTIS3)PILk#Z|E|}`cU`=dmoL#5Xgd7i12S%9J(%wejS+pX$h?0?6KUo#srE-| zr)B|T=Bxy@OW~007P?NZfWpkfwG~dHx!pOB%eS^B>)uk=jep@ggKzPfw{VQ#g{@shz6ju(wmBTTnL{yPn%VtKe)IDRmFFIa5gt(0E6a#cU@Q6Lh zY=1p~YBHV?hFu3T*x555T3|mU$y6alX5BW>Vl9C@Oy$wjq%%_5wlv=%`hYuK`@m$D zH|9DD{E?GpF_KqJ5uV0J3`vxB=BJumg2z`RHUiN_hdR!=7oF(W+ z^h{cROpdZLu|!$|W6Kh^aW@|gwY|>}vH0D&LXSL-xN!+txRiq8DQ&su06y07`P7lQ z;SPU*esek34+>ro)j9L&D5~1$40y=xA|7k5*|>ggAsFL3a<92ETI2six*rl)3#jrw ziK^Zy)MBuHva+iqMC_3;t633$vD@G%&SpP`jujT>;hTUM7OcSn-uxKwxVq3N!%5=n z`*hAU5?M3VLm45bUsj8MdRKVs1w;+X8#aJ#wD}!rtr!-i=Au7yyt$PFH`d##k1N!` zeZCL291eQyBb+!r5t~v|gUajv#nm{uGwSU(7Ccu=X#e)EDMs^HGUFIfa#4*M?rh)W zxA-G+u^IG4N##M{CWxaV^#-I0vflx`g^K3(P7vq7Sijl;Q9;o$OKcL9J4Fwzu?}y#hPYoG`sQ86Yy4F)K226 zs=?X=Qp%@Vrtm#nsoL7`2c+&}y?2a%@DC29@Bwd)|FAx~kN(j;=xCJJzdrVqK=-|T zxF+6gFHJP!O_pW4x#zywbOEZBI zkT8URcITyx>(I8d;Jo_63kkqwcp>Im(@^-_ajSvUwYK&P7z zoL41Po2)PvsjiPN!x}Q5TJkZk6C2HBtcRBRq8}=EvEU`d{e&aFnOeoc!;F?JOrqvP z+A4y}P7X&{gK`*?+h~faP^FMHZcAi7@u1P>YU_si2oq38RZ zIAqmrH75QH9+zZH)j1>uBul41^(i>%66RxC|Kw+PcAI(pi8ykq3hs1k7^>C9kph#` z_t+sYcX~yzdeMqKtUOGBEuoH~gEyrozT&dS9D4&C>nIP=+!PJf)I<3g9I&*QG6g~& z=Cu@e*Quu$UDegbt-Dgdn*xljO}`wJb@f>~$n49eY=4WkOvf z8G1u6J7tWKu6u+JwpDe}?C!gtF0~6>u)Bqe)~Npu_ezj7ti$C(!u#c7J&0}qs~H;T zM07}m&i7bpo5{KA!tQ&PmdtGX5oe!kHVG1DNin(>1wFu-=)7rh{1fS=bCf*(Z;}3Q z8_Jaw8+k}w(nG?O;}zC|&n1%2U0)Y)AtLMFgd6Z(buU}UtqD$>fNg{%p)J(Sz#+vn z-yth*Eo8b~4E+Jk`#hc$OU^Lfd&HnRS*(O18|WDyD#BX*@XTH$@C5?ff|cBv=&{P9 zi61Dak@XcUbN$Og9`YIG_*&Rq#jc@V*u0?}`|pT)*CiV^pR&=bNK)JRbLo^{v&le& znHe?(Ld>J`<9DI8n$r9gDuh6zDw6{B%Hh$|FF4Dec^rBtunVAP9D4K5C~O)S{pat+ zR1ZhV8`uN1wM-P9nUtZceJ=>Ss-JjY9>m`N0<_pZy?UFt@1#teIx>|hB-D!I5XTQT z56@Ox4aht^xpsz)R%r$fg3ns1Gk1eUP4P){gXx*irEs~afC2NmRJlcM@R0pGJnLnY z-|!V=Iqmrp9AR#2x6u0VViI1h5G(N7>@wE%0>|@kh~^A~nn}8yUVDQ*=V_{d^qg56z=r--l4xzjiI2+d)N+AYt+zAErK*%lcME$yl>U6DMCspCV zJhR|za@K{bly;M~BI1#3iS1K|4z2XgE`lPetT3WorU7xRtW@r<IpqR!mJ{6alL?J_{pUr1E46g_~9)} z$4Z0=cGU|zjDj${c9st(eU0iIz8y;OYzKalE?=HoD%F4ag@-8D5b|bFRJ(#)UK?hL zASw1nnG?I?2ZjCZK1r9fBooIf7(?$}RHqWCuDl^J{t(V%_t}s2_1mc@mB5VqwV(vo zwF-Lpu{ri3j=csOXwzfUd%Q836dj*`Qvb3**F|sq|5i6J_C$w}#ow8AQSaYb#N8$v zE7V_)uOG&v-neB6mc!0BbmGI-LZp{aX;I}3jh;Pefj^@QayI@v2IR>lD4NeJisQN8 zD1rq$EIDI?l@R!Nk5b9#s5B~xTH&P=6`)f0$Wc&HG-d*a)&3Z1d^R>Jh{3ggensBi z2qOG9c@{G~anpE6C8je_0$xQm)@x>eWQ0v95FIDEdi<#2S*QE^&mSLFhr)+hQ;ql& zMV%CxAW24+Ee=A&hPm`g26IG75q#<*Sv=rfMcU;x#GaMq-3t9GhMdL$hv7pCcO{&h zW`h-Uzl) zDPn72oyNG^v6P`~;Li~8#x8!`HI9hYv~FeBM&ea}{Ss3lA;0sXJR0U`aUV?w|Mnas z4zuZoWHMsxGZiDeu>;@%fjB=Z+CE;{@b|k0N0xQr>e#ZXBS+Y(zkFe+EF(86W9atBhs38FwFI_ZS6bz- zTfCN@OxouviPr+*iXV>Xp{pvEw$2H6R{+Z&zB*dq=cuF98Q9~{6 zE4;4WvFn`@>}xkJT5;&AgBAu3(^&3wOx+NZ78?#qL%%xtPfy=Os1g$yyG^-i*r~S% z4d^{0&-x;1(=L0CUBTO>t~IV8Hr8L5H^y0oBn4Npzbh%Alz2JC2BkaP)DbQu;WD{b z!xzkFtN%^@X4O=8S|OSjc@lsQmPvNclePdkV~@(oaH8^N>7Tow0b|Qm=YPzb6#tnx z|6Tj~_^~968`d!;Gv-&v1E2Rhp#8143Vd7#DK1~MN7!pYo1?!87)Caw&xdYKR$az% zaMks|6y;De_GsaYz@l+`P!>vX3OMS7N8#KI?jMNp&tk;wpj}Bdcy^{P!*D_dm!e0{}bCsxC4Mk3QlT^5CCzax2LXPy!!N(p$jLs zB%3Y&NR8_I z>Rzl%<4FQ1jV`Sj1pfe=)I;%D`!mko>q7xDaz5h&>X3sk;hoK9Amn=F8-&cS9&rx! zobpR{G@XX@$h1}TLA=%EQsK%^JZ4YgDUMEnziD;F@6)PBnt0LT{ABm96m4|LrTAr1vX0=EYRC-JPJ z6Wlzi!*4Fx(^`O69{x*Xu(Xe&DCOp2)cDE1rpGIJ`{NA!KdyiWx16}tzKCsVa7Cho zyrZ=ZysCkG044df+6@1O{19g4il1Ce|E~BRmldSt(S~yPr9f;_oO?CWWIDjQ(tA&O zCN|6QBVnk9@3+`Wt|76xExyQL9>3`FsQb88keQ`r->Fnpe@B!L)TnI>Jo5p7M7J8z zLj86zBi4(|7*WXxVR&nKVr5G^uU!Dz)Hgp6Cw<>j8gU{dToE>KX{~+kp}SOK@AZnMbN1IlFKPOiZ_=D3*`^GxN2|jEz^!Vi5QeG=Ky$$ z%{;cV8Jr12&_BOe*&V(NiCM3OYRf*YO@0)dW6aE=UjMIPqz@qI=l=$e&%fsIR~ z@vJu{dpzXwb^e(5rS6)dBSo~l{T*fP`4Y{-&c-T(2>yVJ)lO6su8RJ#p6C;5s%W?bbQq;j+W^@~!P+YY$B7;RG8|5g^E~=v?dM+Lk$PwtMB6lldDFhIyx&1;=-M zi{^F+QyDsf8*+!^a5<%v&EWa-mT9A3!6ss#B6p2?t(3V(A4W&T{4X&)&1Vd!x$2%D zh@Ec!&Dc9Ut#UXRfrBoiR;812bXO2k9`PqnEGqlt!QRk-e6E+6P;g`KV%T5_1DmC> z9?}*mk<4WX&4hSMS?5EQB-WwMDGJ>{q56AYBY!cey8TAI~aWFyq!Cm zlr7(wCp`C6%n;U5DZTm5)}bt?rbaU1QiF_lo3$l;itXny7#$0%`>cx}3~7Km zo4XMY0>-cPA)#9JS!YUbY*63u1C_7@&1}LbjNF=iMk%nIT*`hGaKD`c%BKT=GUeKvJ4X_A{6*ozGiI)U%@YRIHQGLc@txH_|fZUye|sD_WpDM_HR+sRu%y}5WP@|G<3-m&2g>9_W~3Rde&e#?GVYa{a1{W z24)d+y9va-IV^%6Ey(E2#3wb0mc3xATMDf{wa@+L?_sn}u^1%8la;?608P!ky$C9@ zWcZn&r@ji!(8M&f7AUSK^;kILegG#`K63S z%>S}@8rTQ)By;}~v*@W#5aKCJPS=A&ToTxbIGQ(Fn<14utpOwrh#msD4d-6!6SK?a z_ESb)p4;hZRPuCUMUz>x2|YdCc@lKz$@$=;6^)nc+x_r5#1n+Ong@^f6LlQLYInVM z9P;>lzi0<@ZFt?1d(}Sy;#=k5pnTVfZezg?h0vhp$hn?~D5p5-1ew+_PHJnWoID}d zSGg=sv^tYXQBR<7eI#yCKjXkjcVz(6mHTu-za`q?@o{gBA<$0mo$qv|1qv96=Yre= z`E|M)m+C?3?_ZEvzb)Q7e>a`-NOo0!z&kLBNnyZlTC=A=_t-*#aCCT?vcPU|6IiOI z^8ojZ7f6{ead_sLHdgv8_Cy2X1U9&Cd|;X`sYU7K<#@2n0s!agwDGi%nk(hLl7%$gclECCI4gtt%g&3tk)9Vo#3rvVXK{r@ zfK4L9p^f!lyBtwuwY5~nPnVosoe)*~O)uNg@PAHQq%)h(_rBNc6NKOFWVbIIV_Ck2 zh!b#j#~COM;5~6gZO z9F@DASo<}z>5z%0-3r!ZEG4R(CcS0pwgTsRuXw#EQ~bZZd}Yn5wZ1iJ%S(lP zO+qCV%CV%h&v;}bIYE00P>G?vYESbK3-w!MjtCG)~~iRX0jES|{UOh>wq`8-+Z7e83InZto{hO=H1WkX&J zKCV;9>Yb&^Roh@^E1JkO%MTFE(=^$ojOiapx-5MGE=ANA3#C-v}Tw)gsUKUa&* zOxnj=(Z|{fL8Hf?KsliqyDN6Yc}z(RsvL2Uaq``fH~EEzFAOVH>undP*WOS;P#HON zan7lOT#TmWyI6hxT5+Q=5{TK#N|Y*8Idq#<^vi3V=J={z*FP4#8=-lF?j`A%U#>0Y z+jZ2@>-kvcC|qN$!e^6H1k&o^C+)L*kBnPq-$Tn1cS}!fy01=bd#}*h4ZtdkhZ-Fa z7{Wk3b{&KBleBaSn~+&+E3@h3z)L`q-o#5lGOH_r$wX?Nd0e41u=y^;%qFMC7Y#Ny{nYq(P+B?o8`*l@& zJ=j75lPtI8nTLNW=uC@E|M>us!{OIcAP`dmc0^T5xb~9@k*DO~c6mUO{!s&aF5rnI zuEE~i5oMCsl{*zX-jbF2?Ww+h*voroh}deq8Hup{8d|mEkqMGv%r&jNCPu!lsbtd$ z{42>y59rW=j5sA$k46n~aTtAOzT*?Ru0MZJU9)308Fr;|Ww~zmZ8d-FEI{Ce($%kQ zkT%x-cllTU1-fRa_-~(|9Xi@Ky9vg**Kv8UcIVM@$68L}NlyvsbB*&Wh@;&VLM&M$ zCJ*DnA&gJMGD*N;D4b#g0nNYJLTH7t93Qd4Fei7viJ^{Mi3yhU+B_?4Z%<7$(OJax z$0UBj3V-2LO^_Hz|d=^~uFUXzCNu_}krv5X&%el)kUqnmus zXQUygA%n*SpXxV+N4Nh%E@YgDoBazNELp1_V9m+8gT#w!e0{$nc@sy*OQQcHAz!AM zm77E&4@^oDC~-xcFM21aFlVGbQ{a7zqfB2lAgo@S0bh-9E`M*#82EaqHBfF4IY*yx z#huykS9AC?N@miY8}u+SO2~tFW*jzlet?>;Kx^y&xEGwyshZkIbta17JRw4EmkngJ_-b$O4?$t2h(j1BMK0}X7zLowDT@`c( z36_4eJ0)p=Q610oCb+0TzC{NI7y*14r2~$%T@2i^Z~iTTtk(kCBNowXE!ogvkTG3C z%W^6+v06_e@9M&Tb?5zqgg(6fb)EY75%k4I0%O`PJAyP#A}^k>yTmZ4+VvR&Z>0{3 zmm(@hd&u0!n={Qpjdql7L}f*smg#%xRffsBW!-ZD-8xlzNh+)xN)09TWTa1a%<|B) z`L8QT$d?1Vf{YM75CxT(4*n+p@+gx+lxaZokBO}>M*yt6LhmoF0DMHnqvNo_$os(PrN9l5qV@g)s1S-jm6>q+$8fe zf9xB~ns1DJCgTve&jwC}>_=K)y5MKlax^IxiD;b*YR@&TCrqZ?PrtJH+`;mB-P7W6 z*CSIRFa$*}P7!=ZEGWa_LDSQ4h!Nh3;WV=nUXA|=Y2+=tyxf)B+NQ|r=k+o_tZ34I zO8;VJofU3%&9QAQEHOwv$x82V-{t8whzZ0tmap7JQX}vdS`3a_yejz46j71P=9o#K z=6HgCzqJkQ46K5%2r66dpjn)y6Y2Y*r^hoCv;&$O6T}DAim)XqZ=H9hHZmSg^X8Wt zteK%b+NRZYkqPd1fw=%(pF76I7bGioe6l>TFP_%>7Jc9!b%!)W8AaS_17*mF!mrTS zqyt|3NT=&zkaWF&lddPMCB#k*03zpcOu?UbFQjCMZ9i}-3!HI$TUv0!uAEZufk|{H z@FoekG9x9ppXRYgOr?kUnz%Fp<3nho(MAqwY2I>1GEMBr7@G%23p0!0H$0)+{Qm=zshL|8+jBgSjBb zz|zpktFPdPBSpw%rH}}2ID%o+eu*4c4=(yn{1U!W@RS4oqyUCwg1j=-UtgElLIDVn zI1!l@DOtfo_$u(TGkyxuBLr}bqMjO&up}>U&JwIu3@OMQOkN&+_R=7YS&S3E6D_DA zkp%}HSa3E3w=-&JkTqfhU}`OvB=7buSiC)mTf5!=o;OE~grA@;_Uxoz!7`lw96kxT zw5e4@#nkx0OJCB8Z~zt#E^GZU82UMm6Ponr=B%BbhjWHp66)j4$~V+SmQIFllRbF; z667d}E%aYPn;RLcHE(rt{p+D`nX>stvRjp^iz}&%#~498UhB$*d7Bx?$rn(_j;YEe-vnEFK(Pvt?0@su~2AxDiJqqIQr!{-YamFuY6(+@%T8i zuTlw3s@BRBqdS$!L}n0mrB0-l+D6E8=hHWvPHXbQN!_pdADGtmPvOI2%B^QA2D9DF z>nhR2YTWxkOAiB@5T6e6z^AC?p-|b}vNXb7%duW)``eYv?V12vR^*GO883RR%~EQF zn_1P&(f#So#W26;`|Ub8J_r%^1<8{C?N`J}!5;$skusjrNxmry3mfFZ+KhxSl!R!( z2b~Wxabqw0BC8MJ=7ZLg>YYTbYNur;2x19M#=2s~lt;49r%K3MhVC_yUn8)E@B4qq z9{;}VY78z*$%(e^5jEQFLEqH=yz&A#s!b`_yxx8y5ia@tdE+w%k9L#AN;MwK;}O7L zW%(&k`z$rX$?tXrYK^cKjk42L2l6>9c543RddiAAAO zTSn&Yk?l=CP`wlYvCd^G{BrX=1U?AMU!xvrdu}ZF0{mwG)rJBPlYP%E2 zO#Cf~pa&7M>9oLO7Xkvp)@6^M`uhOL4OGE?d9GDuI2lPhbekUg zmYAs|`k2(XNUZyDQ!TO{zf>Q)r7nfu7N6e-kFMj?0h_{gH}%A}yPnh0IGu%LcFDih zs>7>km_q?@_S|>x%j!CYo$5%p2CbZVJ?7O^B={uBpM6s0IE;Rmq9_8(ssv7p#b_mmowCG# zmJ^07ep*fNmhE!1jJcY*0HN^1b1J&$8%1OgbeaXJ<8G_G<);%<4x^zs-#>Zs?{nhk zt{-;xH}7Ey4J--@-aY;<7KWm9Wx%|K;&9SKhPWMq0d0+z5%4ojj}8J$%_l4x$a4M- ze-_v7aDZ(QQi7*Vfd_13nO$F9*Y8!l?&aPQT=_4FOeVClfhKdtIME|>VN9JDyKKeA zPL%~A6ucxqG6YpSFJ?$Wp=Y&qisc0>)ln1nJnddSYx~a1xLx6H_8ZFagtS~^X17?U zBXmq-X9Rs3mHSK2zg}Za-Dss5_3G(Dw73doZf1_1@zXyx6&@TW@G3mx>rp&y)JH-U zaCW|`qdiZr_N&9m7s~f_W;4JVx2v1mwmp1N$LAx=-Fg2nxgu#aFCzV5ggFd6=soc< z+W6>LMtNJ11ACKP5BlOpc$M${bMyXP8>4TJv6;DL(zXKqu88GNJ4qPasxyx_gONtyDk{Q9+^0f{5gAcrc4VG2kMF`jXVkj?F5d+j%RbYb8d z->Zf-lUl;(ZFUkbO{xr0!&SF@TpVNK)WKhwOzMI2g4dMHyLiwV%og#bG<cT?8_;yK`FtPGJqJ~VpI2lW49z#*Wl zM{-&GrM}HEDD$6T{8}b_wC$;}m%U}IQdcUVlE3VFl>LMaoPb!W-md~PZYeag&vEW@ zFuhe8v5x^}2ufW^a*HR?bL6l|O`nEeB-mlIf}lA})h*M02S`=+cD-f2PpaF`%FM89 z;NyCTh;ttmSI}8d&QaCE>3rAN&7mhwA#@A0UH^rAXS3?>`_T3t9;Mddw+nM8neWgx z25U^>#|+5UspQ7F`XQZO4o#dod*khN>Z_)nzIruvs}}EyEtJ>cAQg`fHRnefg!F+E zyUWWw!_&@?>szF5$A)f^qd?ji>={1((86lE$~X5CC()(wO(}T}_ZsCV1AN+o@QqBH zbRHi(NTo58={|WVmqeid=q+&z=V6=aIvm8>w3A&KU^tNA?j#qL3IMO z_@%!vGAR1{lI$HQ9PdN&+>VR*`?ctK{j5*;|M+rd2Q7~Ex5?*M&M7=Cjg65_*c*$F zipSmvIWiyUdcam{)O>2H)DEGpY!#i{p1)2U-D}Y0Dz;BG6uGMI-MS6>@ZtSNLRdiA zlai0h;QQ^>RJ-7qAQa^$xCB5=cq-L7M@PEp4b_qHZ+60`@rtC{^%{77%I9OZ`PEni z2N5|FF{4zh)j56c`Nx|3g_`}nx2}kxR9SdXIRF!BZiJvPS+_5$&zKR3~C9a2~& zp%Oix?QSl8yuiyi?Kf?pn)A9S`-d%^c!v%bUbvgiKUe+x^Ae#wtqR=x-yHBf@VWB~ z#-yR9rpRV@glXE&J=Q#)GnyY8SErde0jaeDPs#_PcR8)GfUv^$d}?rw>o?I^wtvxt zya3t#zOn!Ay)uk|5cjc^5Oiece;M?PywF8%E4zR2=B23dd^UM`D#_aFXwm`J0JK^> zR0z7h&l#c{Ar7ruk4@aBE0!V^C_@d(q=!T9UxrWREw#Z_N~8_^af(U9=%kx4R3y$h zXPEOZ`3Uhw;7xBhib%Zv4FESpK#xGB{eqN$s+}=bCbcNdRRHpx&~f|uLpn3iD(>06 zF}{F%nB;Ygq4&k~(|q3%A!%jNprm|R{}&gkuzhNqZk5r>0Z7m|x3i`o_f03V^-32o ziK0LXwJLHymI%L8=g7PPnTD-LxEw#|zq<2`r_}dW%b4xy+m_kSR?IjPSMl|F&Bgn0 zpRmi4*R#@E%Ji=pImEIk_U;@j&|{#IxxR7=?@zO0L)&*W!G)|P3IYH0G&N|Di_aLu z3XJY^goLM%>*tWU+65sg2YT@#J|KfUNDd`iCZ=|-O9WEduKTUcu!A0xv?Fa_rwI*@ z<`>1)7&6;gikq3z^L9!ZwO8z-y%aFObHnO6J=mPKc5m;Te%A!M3iICj{zjoI5_l5F z$s8!x^nh^V#ZCXG12$}f%F3A7glhG&il+?0b`!{`Xgo#|LfS&}bg>!;%9VQ`He6$q z3<%gX4({d=jLH1zB%SuB078_LqSFnx-=#2nKDhp3Z+4jk2X9GM;IPFl-_*mcfPA_d z0bwf*Kuix)tLx-k!#pE*QcII0)mS)KVk{g{DA4mcsHrqxj*qyQ#A-L6xuWz}2PeVE z@3;IAi)Puh_vwcgQRvlFGH-xdVG1X0uDRU-X%!QpDT&Iazxnk6M3rdTh72TnARfZ( ziVi635RkLH1GMSuf<(AGC~S>bK}C1-wKOrmMZqE$pB@CP4|hi;>?K%kL%Zk%!)9zE@YP#SxyH5`ad@5wQU!80Mg+g}siWinJIPOcld=5w$U#I0SO@{1;Q;GM zXK-~d_n83JvkPZR(woD_h=0TTnU&|dOjmEWbyEH~NyMT=*Nr-<30r?s+$S`ja|L0- zJibmw-RV)0rt9s8w(IWr5ay`3gx3$lQSD>B(S0&6j>yFUR#!?1^Ov!q-bS*p!#tQf zy*wI=c`Tp3>NmXQ2bjJSDZA~pwV6d&L1Yi*nf?H6j#AF^^&8lUL_|(3+ zU*kAEPt7<%T4^hry72;O)6BruYk|r_CV*salX;xEDw9sk7fzRZsg6pEo6&cj!cpdh zhzQ<3kw~3H;iR)elyx~spxn^H?uU>v@kd8EkqpY{2MtHicH!zd1X}s*4Pm_}TGG?r z)?{^1OZ{E{tl{5~He3{S3z{E!7<{6+J6n!`Bvb=+UkO+Y|6YA? zodv!U2mmqqR5Z=M@0KIdgn11)N1rA88;@2E+`sQsRbS4Kn_+JfKQ*`f)@~OyN>^Ws zVxtfPP{`WRAx!X~JqETB4lep$+S(1zl+7=V!Mk{IMQlJotl-yqx83o@%N5J2?6&9c zS2H@s=G^0_Iq1_?D*JH~!Q7qbKhmPGmp+N`Ib|QD{BRme_9I^`?}mcNlkSjLsy$i} zQQCN}&cR3P6*6u21_oiLf1-4<5UB9@@xN->w($N{jSS+Eu8-QqfG*r~*V|*d{NFav zmRgVCU#|IIUCSR2p`7sfh{~8W7!q5$hG==o{UB*qKjs{0(-8VX+-PfpAd0SA0K|zL z1aV~)Cvuo&-Yu4iY*jkR_7Q`)GEkBJd4U<6t3B9hka{cI6(2=obfZF4oq zZW`UkLa0cKo@a?zfIYJ?^O3%3yK2Q{v|n*T_-@Qdy`TIzLL*?I9ZrM1!Hch+DY=^> zWKduos6mQ@GMhrfRBI=DG@+_bT9&juci9soUuOmLBPHc;g|;B$Cd4G6bjaoWX~2Ns zNIBzJkTiD7@YX%t#%XLPjcvQJ?Z!4IX`D2+-PpEm+h{nkZN1Zb z@3a2zxA`(_&02GQ2m9=^x3NebzJ%V2CMoqF4+*Hl3z~piJ>&1HjP22UsbbU6Sgu3< zkWXV9NZZz1&si7Bve!0xzRtg~a_?EPdr|ZBu=EJrQDvoeO-`g&ngP)2-S^+JUS#)i=bvc-N zG~6{O+R+evHLvhFWXIo+Lw)wy$HCOI#FZ)RfBMdtA7`01Uw=eyd~(hyHaKWF3x?q>VI#FB6TG#JBmLX;)L@|I1&2S`-W<%@*Tpy z`{SFQ$8|H8`yCZiESjC*f$q2(?Mbgmr??H2`W2YD=D~;MEf!GwADi&K%9Gjl0H1Tp zR(^)y9Rtez;IU3p>DbuB;lRaAhmIWN({+03gS_?D+uaMat`ZB-A%cAFqIz@&-ac;j zwljA9Rx97^?+tiWqQNNGdb7{gkwO=?uiGw}%`CUwRSHS;RGc(cJE=oR}W|dZ)!->&7~|Oi(K_p&Il56CvSRFDl{61?PwikkX26 zFO{9=qSNsr@4Bb-{SQEQ;CN0or#PDVXZ`&QQni;cJHY@xWr)woKbQd>u57rAAiefw zGUa-`+9w($@<6)vw{*R6TgLd@q%r&emLS!06xB=QuH9;I@+eh6L|uiuG+Eww4zSl*o#Xv600uw##V`3&Q{&zvx}^P!!c~ z+GdI!C0kc1>?TU^a55^vewvq^e{0fo#Gzz3O^L+A%mYssUtPEaAbvHh7!=wysaxOq z;Tgma5xVor3^MGXQ=xe`QQ|mI6PI$tp=)0ZGGH^cBBYN{o{LXfhDNZ_OD2UrSAb36 zt%_nk(&WZMuI(c85I1$8IMIX)XeuR}-KJCdYR1rl&bj4I)b)^gX?#-wIl{&^`ex`t z*+4;K<&f$86jpA#_coD4jZy1+$l-PMK>M^R_|A`bu?_}*Cn=3kA}l3sc!ALj45R$S zcip^4rjR|`R_#T2r{e15*UTy=^IC}kkkBs=Jv3ed8_j(Rpt_AEqE|$v+=>dmPYHD# zguA2`@@5eA8S8&?P{`)?wvN_~e6OpxIX2B8bz6K=WF~$0xw-o4^|Wd2b~5}KdY-QJ_DakuQSY zT41Q_{dKP?R{>#m&5>s{4IM*EiHcMc8V&)h`?da_3X9BFgp^`3H7eb%6Jc4;7Yn6`2QcRfT_uWlcVjoe2a6- zmpx@cwZoLRx>$z&S@#<%foB7ZO^zK@`4U|Ez!%(R`B$t zYP3(-#M^aUj=S)=NJr)1#B4h&6avbfaMR^uU}J6}!oI9H=3So%|3IVQ1y_;+uH=Ay zcE8HKKFd@?=qENs+EZ+`r@*#+0j8a5hC+ZB!Z!uu%!nOmJRq#u^+?b1gUSv& zZ$jD^ze(Lg>*Ey zw7YY;%~b%a&7<)z0K_hs>I{ocWHlpe=ydAnza-@fNv)I$4yWq9_u)-Lz-!~Xt46*= zJ#hsdve!o;oo)U*?2YQGN}#&^x)`fSExr%GRy;8P9F$?U-_&7iWE;6sAWgqtHq=Ru zKe3V=l4u)a?=!}Js%za1c`$k{LRg`@J^rE5_azH`d*|?b+SQO;T2VL1k#RI>c6@i` zVGPq!6B`UAw3BC^C zJqmOq@Mv(b9%NxdP`pKM16KsF5oJ$~2`4Gj z#~Y3z8XlF$`E9Y$$f&6c@>41Ngr_Fr4*I<@0(@|zUh(rBdO-QLN^iAOGPC2>zP;%j3q zLA%A{mV>p^>!iPz1M#%gy@{5rcSqDyL?-29T3>COAlxzjy{9Rxyw?AkG;i|}pE)3M zxyGjB3br^CQy6X@&bS!}q9g|aGF$dZ#s)j+WIeA}DT#Iq53@ib3vY-Zet&{&ok4+% zm@DP%r7mRy)eTw6O;8>EF0<<_>f1gjH-JVt4-hyNEUb(B?olAl@nTs4eY+Bp`yvo2 z^)rvm!LqD1f*ho|igMZYK$7)57~^QL%#rwNaYkZJ?^YVms~a-}i^hC7NB(s1_yHzU z-Ht<`A~uZf8jDlR;MW*s0?YW#ZCAO^hl4J066-j2;^f`RE1$MNj&6Wzh&BdJ0?q`Q zh!d9#!I(7QeT<`Fqb=|pSeP5b_*^DZs|a#)A(BA6=v|UKtp)rw+k5d)(nw?`GY$+^ ze!mUkSsuTILj7Q!8b(5(-SQ;;M4nNlYzJEloe~7oLC_iLi5(L4w{5P&{kRjHHKUUr zGhX>c!qfeM6Y$~aWm=EDwdrS_tRKM*z{<%jRjWcFG>l&&)w5w^sXj()EbsXx&im9i z4Ox&X+2PibpUInX>Kt+l_13@jVeZxO!uE>`?t0|6_C*WQ*2kv4(M`p(hXA85WN%-? zpw&Xi^8$wD5@Cl~rS1G2j(Zxog^gbQiQL=OtVp%Yd?-S^Ai~Nqyo+YaxcrvJ&S;J`Y&~)2-xvyr)w(!eJw5Lvi?ctj zh-zOdmmN-e1frTRWe%dN{b0H(8(5+{1aT+}eGaQXFfM$ziFN8sN_||D?lJ(J*(Il= zLp34G?eYhwn<~RsCvejvk1ve19|>wypevF;(H21(#i$bm{V^`@A9BTxd>FG$nRHJ4oNlv%l=i5XnpBcU#4yB{&3)F z=-0y|3Ep5=wRzyIQOYmXcQ$^^VSemD){~LL!x}1gDKY=Y^Oir4THv435Xi`p7&Ki? z;TVBOJs-13BTUt8?;&=u>8EHgjP$j_g*;vk0=l0u)VrT4e%Y-3j;B+XX){R9u=?s$ z^|B%S6Q6&aJ2Pp}fuBMi#Am2(hxPqf{)C!8q!TTwh2*A}OKx7T)7lju*Z3J^3_a2d5(u?C=JVLGtr&q_y)vPdZCX>9aJ+-|q;DQ@&spVe} zPc1uch$odln>w|w)F|Q4v}`orBKmXBV-b6YgumML4vO9Hr=v*ksZK(sWf%k=DJpeZ zYJpZEL5mCnJtRmYjb=~j=(0ZKe6x4dcvulAgEzkJ&45rel*}_b8(5B? zL@zIVU2@Sc#4>A%$M8Md$|ksz{GAE(%B7N;A+o>N+6fr)E=(e`hAj)WE6 zJZr|eBmyg!cDg2<10R<@yqW98YA>y+{~VuLaWk5I*PTCZhDP^&{Lu=LLhGWO5}Y2T zxr2H>pbf{CK;>#?R{{9&+8sV#rB$?r^+ql`dj533`+LZ$y4A+A z^VceH?w03^G!J{-Aky5Ro}WXoeu+l%~m%@U^RLyn>xzYt?yyv*J( z>iVGipOXOh!;O}`c$rxaAOG{0WXC+)99tnSPOUvfWT<_dIA+lEF|a|FyZqm1^$!zt znA%=;=jqAFe&qIX1+-;IXkmsHdJ!R>Zv`N2dg3v5Ug7_;Sr7e4VB5ZtsBKzVQ0v~L z;_epK!8MU8h5tFMFaVMpFy03xfXxs>5fyFda2FhOOTO3%9~6a><*;jw-wF>h68;fV zxapS5+eR8#9fM#GwgBFYY#`#{Io17bq2J~UGdA0G={19Hj2UhQ7X483#~pNSuhv~N z!4w;t%xmbkg%ELb8hJt2f@p|EomC(Yvg3#enF^^diE?LO*}B>wO9^LX{*MJU|8P3g z=^DlmgZmZ#u0MY$GDQLa(%%Z6>vcv*x3)qMtOY^M(S~}3wD#Gy@VDk^+hTEXw)2d43U&96CWZ>E4$t^ z$cU>w&aNOstt*_jrEkoBiABD^84QSt@=;<;IrDSFPP z_yINW`q5}?GZDtGuDgRE`n@$Hf5dsVFBzcpDt1!;LSS6+isxAVSJrlhxc9ufoi=7$H1-186GUev!DUds@Ro=|aIY%TKhRi_h#hgDV7N-J-uptJkY1kO zmK|L<(ZS0=n8;_oaa>&-cRa6bHa^ViT4o4F zBqQD$jvV7)&-Y%#r_=LE0Of&-7D56v%G~ewdH95nqMQsQvockwG^5O9Li52U|44e+ z+M@Gb|5ZqE7iQvu&cJJdOjT~cu7Aa6&mHNDb3WIX7#E)Fuo%a z4687s%h%Kp4+|#s4cN2AC%d^46X4rZMLp2>A-C&36L zbF8~3>;$jJ z(!Kb_wN)TtHM2cI3h&Iw;Tj9uy*dtBMu`C=Kayl(VQ1&p;K-t~uUIKF<_w!Fq}8b)=0$ zQCwXjX zplgix_xGb?zM%d*nbPb-^5rZvS!RXcmjg_YP{2SSEE-5&i|jo%j-lz{G58akjl;_L z?Q`{Y`uli19Y6AGmJeftJW6S!dSSh)dWw~n+QvNp{6>C`83Kf#R-cU}+42)O*`y?^ zQ!<=E?H5cP_+El9{Hz=Etn@P0N#rc$%GQ}UC^#r-xq}hKZe6<~hQ$U}z z!&V-jw-&FR!qb*tACwYD^V zeS0wS1RpxpOfTD+8q7}nU|10O^(tX7FSI+yWH`?p;sZ*{b78MU-omFXj)(lAi=3p4 z_u)5IgyWZWvo4ONu`NGmIiqNDZ7>9t%V}&y18#eQSlvDs^>-U2o2{84~Sp6}|A*^}&>b}bjJDr|j7g&6bWj#wE z3<}9WrPwM95s7FhGO_Ub*FZ)Dct=m~&Nl#LV z^dxwO5AzRys{UJdYM#i*U*cWrY5(_-P zuu@_#1`CR3D!`$Cl3=wFRYh{o>Nk|!Ua~1@VsaEl@MVh|_piHTs1~-i{Ri~g zwMHNUWphK?DTKw5s!Vu-$-x&v5UgdViax?~^HsEfDPZ;|Bf{RAkg1ws73rO|e^f+H z>bS9om#}`*(v~lVhG*6GNz!;S!_JB6oY?MiOT32d0%u$>NKl-GwDo1II&Z>03CkTDP}z!=xh1v$VV9*}D^Se?PU?^rST^P zif|aGi%oHe(zg)kGzle`bQ*R03hp9&!ZRcIz0SSz+vx~ff*yrNzL%B&cSyj<;df2J z&FsykMwq{s?q8;TPI*^+w(Qu(y|#O{w@^ELLKqn%zg6R)3&A3yYS8lh3w$4uRF~Fo zDF1l`c4#f9-%x-}`Ab`zeB}eYRE&CUfoR3@MrKCBB&H$Q5#u9~q>RU6S<-t&am6r; zJwqAmBe0VW`DqYya5WB#>J@s;7;u=?KjJAd6QsxjEex{Ka&yxLI%s-?->h;lwD=GY zY=@%sFXz-)X2*baD`x`O`L%#P+pOcVZnEq|k>y|ne>)}t7`)=>Z?&Qj?-(V(=D(gk zZe(k**n;|r5p<->F48x>BFA^-lc7E`LLWIY;xD5L##AUt!TCFRJ)W6>Rx9tcUbd=_ zd27z6IyQP8E-7@)*ejcX6u>d8M{b=!&K3%EGU>Q+ePSGqLi}$DSu{>bT>EhZMX9^o z-VM^7B=kv@0(~$tpF}dj(GHynid4~qnyQBE0Y^j{=9r?@T8rT?)vR%!KUtfa4^+Ck z5tx3acR5mOgL@A$_lAfG(P+{f1e!#_wgvH#oS3)Qd6S<#u~%OmiF`qgh-Hx^%n;~p zG3drlET}ND!!7hu54GbK0+I&ds%k-B-x{WFl26uNVvz2irq&1vrJ3CbHOkSZG3V_5 z_)Oyp($K)+1wIa&ApAk1%Wf5rl)+5%N=@vanfYE+JVZX>vej3Xn_37@I_giTJF=gi zpNq0Fo?>_!eSV}_)8nJBsaFiGh0snM=6c#q3i*5}WQVJ+OuzXZ^4b5b=q)sB#a@4g ze9P}tae3wo?#U#qn<+Av?{@$WN^i~aeC;d>yl!_eiX&hS`dL^hxXZnyScW$DtA~y# zvV2y6%1G-X(>jBKyAOht`bYd=HsF`Qn6Cm2PQZ?|q%ae`rZiievhnRZl3=t%)*H=| z-CA(lkeR44>?r!YXJ&rK-!uhs82wIAA`WaR&mB+FzB&*Aeg2oE<@!Db@ks{Gp*h{` z5)M}{OpJB(r?camiRahAMvAhF8{ekWNs8x5YwSzMlo zlV!!r8R|&hh|1Jq6*4PxjBX;P8A%7*XyzJGFGCQpwfVywCX2mfY2^-~Ya?xW?E+;- zsLbYcIMcVnCi`4XpQv3x+uKs!NsPsPZlIF<1G#<@e~j}&hssU^%RN;5e_Q_E17 zM9zX`dkD!nwp(!y#ZQpgYTOXV~W)G)1v1C%}R@dvij@bnc z^jtSR?WJxkSJhO7b?yxbm*hySqn(`*4j|E16qR}` z-GtZt>f=qHswu@8(P{!QRy#if?n#v-pD)%Wg2kX0Sad)ky32xUk?0a$e)E+$>-SH? zXnodbcYikJaR`Mm($=g zjOb4s{E5vi49rnkeoPm}!GIXPXlNpDFg(}wh=-t!Q1W?-?D)OiQL|eJ&tD7bWdBKY zfLL;=?yUo%|Akd$55k8LA_@@G-?xX0#H1c8g0j|Z18Q}fKlr@;LS(s4O_HN=Y>JT_ zUP>gc<$~U&rR{BH|qP7ye&_ei9tx!r_PV}UiaVvh3WZHao z`c=c--bn}u4~x{#5ktI_Bv;g~zp|fieesJU#UM44sT8-UjUv;7N=i?Gl6G1(%4ask zRJ+^LFFhHDtT;cI-kwQLr^};P1O_l{#@bf7V)eH|GHy<~%U+$@hsV!W#F!YX6?Bmp|L;#%)v@=|l84hD6fAGv8WKZEm^n;Pr!vK?bQ(osv&yo_l?|o@9&P0c;E|z zlrha;p0SCv_J|K-6a>PujZ)UR4FhOYLiTAjcKsv>2bZ&azeZ?Oi1H;Qzmp==Ixj0|$s(IC`av_>f)^LXRUAk5)L8zTIe~|8YsKb1FFJnj z&I!uo24~l;=SX)*!ieX&f^QmT^36H3luk0fHQplQuCJRLf?d%!42q9Ibuk#Nk${R! z>;sxRwSW?cZLr}6$n6f)jv*J zet0DmhTrkTsZrWd{D5C(&c5PoY{)OH1g|_N0NT&Dn)ncGSFK#(j)aJ}y4jNdjb)g! z?|1s#f?AkKvCUB^4{YGaemEV+H?sv!)EHjlEf2}~a3T_@^^Gz!qOsLawH(MSjj~W- zDT-taanl5-R6v=9J?xqrx4`u>02@r-0j+!#7I*l#eFINiq;v_6UC5~+%Z#G=pg+BT z&U8FhlFX#iz}|6FvsU?GV@<~_11E(i-pp);0;OT(Pc6vAXJK*l=QeI=^!-%y7yDSP zH7hS?^mlI!cI*Tf)l2#hgr0et73Ro>y`r{Z4cN&;^KEL=&f=_b5i-A}D!cX15i}5< z;QMu%OZaYo-FVSVN86|> zYTA(5+1fk&gV%fe3$R#}CAXN*-6HJO{(@BZ*?F`=%{DVqpF^Zi810LVs3u6=k#WK- zag*WWNLaPJ1Anutof{2NnN;C%$YmhA8RwSEmCbxo?AxuDoQ`^1wD*$DQaEyg@Mtz8 zdTe@DUn#if_1e}O2(miH!X}8TB@R=j@)6F6dEeV=(DC(a%aZ3Hiz1`CJOJCG zSd;o!?4SFdAy^uJ)F!W9Ng+iWa(r{szi!Lm7NM4Q>&!(SlQ0KGTR~A%_5GEGc4sOq zJ5orPXtDb@X~*C5r7-hN(|-ZO%)7%5yI)1vhs5Gt;h4IHVg<=|8Ie)n$?7189TFN;o!G}r2~^F_U#t&a=iFYOmmeA>)~BdxY!kN# zaKJImo$7$p(e-w@RGj?UXB^pRo&MAA4{p8Zef`~|u1+dh1xegx%f&ID7YD=LHGQiR zw$f0}o_$|aalbU8x0*1ZT0Toa?`XdtVUi%aNoK?{r_u3ElH1kJ@ZIJ?)Za^?x?C+^ z>ZC&v>rrc8w!C;LtE*xetw4ykG=uFw#!D{BE9?^PP5)`_Xt(J*|F5n4&c+qeVtd7@ zv*=rYw2@PX6MYP&%ux-ZI6JCL9L8m)#zx($;lJ7Zb83p5r;Og63j(C#bKj;p6S88Hv+*18E1guTk8g69I}V(V zxLxsyy6(Sy958-@pg9?>SsB-dJ@}s@RKt=7Qq}{?78Vyh@r!s@@7*E+w;~q0H86!- z)pt~k+5n|>FQw#OI{-iF?*OUg>~|Sdh2Aosxu-RZuTMpVPB`@+C^XN9?SCNZr_+MK zDtpr)v2GwIOeh^+03adbb=(XI)$I%@^C9V*G5Wt(NyXW{w~SuP>*F|bk~{!aT*XXv z4s`+9vVr#Cxh8~z+Sa}Ny2-@pumv(Ge3T{qxXBUb0v~G!4plbBK(xHx=N|LdtBb$( zz<|fC!J`?MOv)}VKRmcKKj(elwy!eD)kDqQkKlZDht$sV+xT+Q4AN{~2lHKuieTa@ zL%98OwjuN?#96BdQz`TbJyg11M|ETjd7IeepdH8);9l(%`QF7LUW09wg}W?%#u&B< zl~Oe00DS0{BfqB-;QG?e!;+gwH zy4#MYpr}kSGuK}wDk`lgZ`O1iy{e($aiI_$cU8Gqkc{>Q69F#aP#P)G?)2xKKJdw$ z$iT~Cglq!5m!z{$k?(p4)9XHcdbip4^3rHA*p_OD^@bijh5d;FeoDSey2j6-3s*^0 ztLZ1q9-I#+lWg7&2gn8EaSlQp>h%gZ?c=|!_eL&H$Pd#sGq;uj4hgwK0v>jPG0Mi3 z0=(I1!)?!g!~Hml`NUgrrJG^%cFd>hUrg@CH=>xo4AjD6Yns@8Q^DW(MEUlHSk1x( zJ%;s^FRgq>4b#g-To=9zc)D`=4j&?@9bieKG9=W{1uLT={Z8l&h9vkwrf$CyIrP9V zf&R>uL0ci2Xd?t0U81H~KPChm(tfr=`CTsZfA4{5>+<}+mBxsnr8`9=uw~!Dx7;DN zRG&lLPGLw6JL>29FQ@$Mm;q+e^mk#tAXyc>GBSJj( zFCTAcVi(4nLN&2jA>k|+(Q;Fc;u|G-hG?6GILt4%s4OmGg!?z}RjA`BZ5H_Ny$#aJ zdNL$`V@un!lnU{a1~CsGv~-FAQcd@7?yW@|S}TUzt+zot#ZAIlb6tsb9&WRHNlWPA z!)PV;7Q%;lcAeSv`JO?_o{!Rw8fvj&*3E`(=Q8RM)|RmS9GknWmLTJDDLrz==#L*Q zbWu05D=9>DfWo0hdcClNpz+z6*{GrDK}q(e@gLi8RX}C?=PJA9o*s9=v?mbP+>XFB#h)L@5_>?k6u%+irR}{&%A9vvy zmn9^WI&afi#C~0+njyG(lu0bnUe231?jhf8VRC_-A@{zeW@U&oPe(*|kx@-AMJ-#f zEiC8P)=K#&vA5$uBxXTYH8B1>(RuUQG1M8dr%4hw2EehnxOlt=1ss%@DkFGzhTuEP zyo`gs!;Bv86-(kx%%Fvz{*nX`pgLp|XwHMsNH&lQh$r8K;^v_JObReW)0Tn~13_~J z8^LmJdtt>jPVW>8jn3bPyCt5YEDyg$%#&nFj4W=EexNB#T1WoB_9pO&5qh8aXmP!{}~F z7%F4!&@S_wg=dIAPb&o!%bGsD;dZj5Q+ZRi6E^cA!DJ40UX`WXWp=TIIHbPi4O`VN z$0f9%`I2+7uI&6djfA^oDHtk#kEo1m9FCeo3sGt?8YF|^gN4}EXwhYvMZ=rp8q`g7symtE*$*`B`1J0pHE~!j%YsR0);FaRs;8SUF58FhC#)rI@!k(fnO# zy?k0KJ~!rqS1Y`Zfj2nqfMbiYb}}z6Qa;da)wvhfu`#ZZXWVPlIj%h(*R|uuN}kf3 zK~#jIDLG`4*9Ds?lU%-Iz1SwF+2q0Brcu!wuXZ}qY1P>l-KG()ov-XC)pt$jdFo7+mpV5;~Y@sMaID#a(d)=;mM*p~bpnf`hwpe(O|!ns(5FQ`$w zX(x;_ySKUPR@>_L?l}3m1)6J9xKc-gG*?Q=)NUlYfKD5LJ^(6ULP*fN@B98AY!0hQ+r7@p|9GBlOIo4Q0cla0u!8Dyw+5 z)2VU-4fGS{KnCS%<4!CSZ_Gbq?RXpb;7-VPb6=#R9?z0+_wHJ(d$3*8dE08NCV6aD zyTB(a39M=uuW}>Mi`dIhiCrp{)K2=;XW%5mA>sAAgKy0hb`xSAjEuZgmmmcq>uy(l z%II_}&%EYqF@z)@QEj$b(Z)5Zgmt~aNoq?XU1ufl*n>rhC{(Ko9)jp!~m zGPpb-Bx3M~*s57aZv8z^_WLaiki!PWZ1qZO2|TmjG4-A{k?y1s_#G>q!u~oJ2A>OX zh7_D&6XN!cf)i~|f1LY<03-wlQv>Z`lF6R~#FPt2aK*f}DYIUuT(AFjKRy<2Xyjp+ z&!4i5RV{qi!YNyh$_a{#1Br45ZSq(!gHit3;mQuiti$g1!2o%W!*$$5WCKSIv;Vxt z7v{gM(mH^ZDN<_;Z-6Hb6uG{Z)ZFtT!ngm7OdSu$; z2Lz|{T=g%<@Agg_Ahh9d2Dt&+EXu?U?z3VwJ-E^O$>dpLH^Pseq1ExEq-m+59 z)elB_BEd*+BHz&KS`?HscrN*HBzE&PNgmLlh2F8lbO4g^=oov6wcU_vS4q07c@K+n zNzUxFh4EY0wFn=s1Io}M4|BN}mE&!NJ3^uIoS8CKa)aHwxHF@+pIO%L0z(MVvX~nb z&GYwSW<)I2Q&~J=uA6QI)m=BJ!PQ8@ z6tO0mgWDA+1E$;&2G0lQE4LHPR~?ZEk8?jdUv&)+Q(a)|Rcm$mED0O_>?^VF6s4w% zbYK{TLLE*E_GG`O3--3=zfOP`;rW?LeHg@{mxhYZ&d3Mcx?Xi|y+eE0%BA(Ln&nL` zga|F3iqCkNkXcs!$Zh_r&L;z`Hi#|mZAAi!6U%hG-F7Pn0OBq&W2-2#({aS7pMMOI zBTVToZNF`O=*L-J#;M0WkjS2}Ke_}(Y&jZdebXIkBYd>Ae2n2z0$ z2|65evop+5cxgw`7M2@Ab{Vq^zrwUri~I-bchnF{+0;s|{$D%X1%og}Y==klDL?B+ z5og!K9l*+ICXGtgnyoNQ7W+L+ke4TNS^tfD(_?>`%l(PTDIp;>KFYd+Axu<6oJ$lv zqz*U3G-CLj31JF#UzWtmp$Tu;z+Fgg;~~YMVwFxBRI##R5hw!0vg$H>_MU38elaAu z5dnIxP-7(&DUAKa;WppbR@S05X)5s^G73r^rQG@FfByjBR#Tmmy?P{rly(M9)~}900KvcL|JDwQeshO|oLK+cm$@G5 zj2#(p-v`nTVq;;1sd({D60sc&pUURIMsgejlIrx(;kb%&2^s5j+-eXLo8{{=TTaLg z4>YaT)NsvgD@&GxBSUu!?x2IB88S!A7@&x6jB~d@aiUaPBV}l0gsF&vGB$oE2J8S(Qjldb-^<;WxHFnlOgb5RLqxuEd&S{+eDAyA}4jV zIA6dExINOp4S!x;&MpIR3Xi3B5}S&hll8^$pu(P9TsIfvF znx+RZBIxMc&;3vzonXT=4ocnnlbG-IF@ac#s#afR?(lI2{ubi<{y7ko|H>r5Q`7|$I(5f(^B)3BAAp!u|POY_uT*pg5)d14Nap^(shaP-{ua^nTa~fUv!x~s+ zw%3fJa6mq(9N;=wEbMtmB1Cl>B^P$qQQAV;!pK6gzsq`#vVdWi3^qo}Z2}+_a1tHC zE3a4Rlf+4Wu`r`1t9#jhr${tZr8ji6Nc;2iYydlau4$^qNFeI6%CBU%F;gwdj;Uhi zi_JrdyK zn4~eJPLHZ9o@nwG#!KN5bswQ`Av@gO@~h+VQ7^f*hnahHl*G1oi8w9K=(jBlZ)frWoMWnH-lL9~q<-gAePu;fkZ> zZAcwCkXf(j91STr^$nT)hk8pVq#_tPRJQS$yutN@&UIzy?f@p2>iU@_{D zDVE{x8!iVF71f{M(x#74DC7uLU}l|CatGvmeHU^%K3PW6KcEk3(4NIx{#r94UG}x! zJsAl_DY40%sq8Tmt={CN&%x<{F(%`7R4xC&bmkKOHFhz`+J83M4uXbkH~vwGwp}gu z{l}ayU5F34N>$X&+;a?yIHd%Dcm?&=GLsSUS7&q>l?&~5y@Ft$c6DbU2%7#qI(vH4 znYsu)F&a2wZpc;$eP3PhZ6Wl3RDgfOA+Vb)5b6-Q8Kd52a15D^18^xZR};(1ldqXL z>5LczB)fU0&aDW%^>F!N=p<}`8bmFHHYNu*DQjeACM@~Z3Ja_7ol$i}K8K6n57pO7 z7FDolcu=9vQCQa11URJlhfqX_iqSp1m3lUeGF^;Q#+haZ2xg@3xneIUWC#$90qB!zmEuajG{Q`*d$WJxIVfyluk{I+;|(EhP7@|Tn8wf8YfUd z98*k2%4aGif`u@QA=(c}tJR|J$%nGM85GT;gXPxZwR9*FMjiHCkMb9Y#Prd*x+|?N zykzP2HCu>Jaf=|%v&64z)5|5{;;iriIUlc0%}KBoc?fsK)>yTO19A7>^uGX-E<`6O z;zc5dbfVjZb90Q3lYj3r5{j_(UK{1<+@q@vKA}vFRQP!4u6Oi;1&DGz9&D5Sv4@?C z04st9336=vcs*UDw>VrR3LrC#X~v}$s1zR1ZF@LbtN#CE!`H<@Jq?-og3GzuOiGTO zLAKjTRTy==r-qw-Fd<+collM(?m+S;hu2i*YYSRdq>E@G00&~8udK{Ki-r{5EUb$= z^gFJ0f&5fKLH5$`y^~*@LgkEBIQ-8jFxnRBQ$=m3-3Cx3BbWE}g-_ zS-#hvX~2&fMrOoT#Cwzyd_4tSR$bvaAZrK3O^jrih zM49n@AHndxvSjg%*qA(7@_U-JdvV6(;|YQ2Byim|NeijGRNY)HkiQkU(}H}`=>$vU z`$Q=4c}LnA!_UjjaGP-nxqXQ*TDQR8QU@XOvuc9TmNe>r6UBcYv5mtxCdq(3yxne* zxVa4HW?342rXRqbIKxfB`Mhr3tUkOGijS}qzm(%3-T@7{wo0%$A7+~(pcrq@6}#4r~*ta32MMdX5fucUyq`x7L~ zJ>=L-)>4y13ww#dpkZ z`6Jwm-N7t0Q{88$VhUvH8-tj+9~KKb7XD%dH=$w^}!F8=UR@gDRd zAx)FctLj2j!pXJ~j;`NgYq-Fl2F!Zp_B|2bni;{TOlS9k@~Xc`_T{jFeoR-f-z5|i zBMb(}9jMYmvkH;IW|W8KKXj}Afo`9|D6jp#FVi1s_aQKjuf0*4UwZi+W1obUadK~0 zVKcbhA&P@uUaRtA58<|2GTRfhc@`(yg#J)k)oxO~(wFJEFq4z9AgnZ)LaSH){rylC zL?t#MGynE;Rj1955sBwB^NU=bl?nP>yU4A(PPYe+c?{7|D=TGe_SCl&sbc1y5;MLv zFL~ePAxbkr%^U;_10>-E^l+U0rCkssuC^M0vBb!hP#hrTFe3+l5nW@qi8B(ES z$`)3ZgTa&9way?GU{gc>fJ#C98GFi86f+0R0Vj(cFW6vf3CDeDBnI7%K$#Q<8r`bzXs%y1B(W+zk2{{G z!#olBv8MAifKyolVJei-z`L;BRCRBfzw}?0?blpU3Qq7q?(rpz^=IejNi2-H)zwIc zj2Xj0a99pfI@#D&1-BqZY=#ShE^4PdfnbrSZ!{x(L2s-o%g_;vB9@+=c6d&yHHvzL zR<$vy?pB~AouP}G_^En7A2L-)B@jVrw9iXLMGGG3Zp2G4w0AQi6`QCzY$&ZhtkSwC zHY#kmrpA+5z2Yb1g|sLdj<-W@k*aBZ@j%jqEP&YMpf75Uc6-HqQk}F{Ee+`lo7PKw z@a$-V*_wl^F9pjw;1E<{G7ks}HAuo_ifZ7I9Y z@AAt-7;qz|#dm{A<_d)UU-Zw?rqddFiZ9jkJ@}+FcPF^+-)KZa?-vu!hL{K^?77Q! z+`@0(No+aNGR1X{B^!Bd2z{abANj_)Kl{CC^} znjyRI=KVYe(XUu*d^_C!K5BiW?g+#OAEch)NU7v&T#r?M;4^;SFgot_817NH$IsZ( z(1z5&ZJp$vCswNd*`LU-_~~N0uA^nIgyAp78<*A;^fdMOiLBtg3t6$zK@emSf5;xR zjIDX6!V2XibD;GJlhmNy`9~2>FV0B*R4jHHizy+qFKzk}*a*6GvF~^S$VNxPP|ojn zN5X!brFp1eC?rf(Q`#&hE_BG7B z#%+)X-PkKEYfUdPDMRW1W9l2Dznp|*1Ntne`d|!x%PGL^B~vu11m-UiAy`#K#Nt4gaLFP=3x9fR8^KhIU&O|QPO@T*YCm1Qou(X}?O!7B1Fmz(gEx)!A5)AbphEIC!>;u3Jg;J@l+E^O| zy$4(*e@SXbchS@dPbRbf5!S!|0up~1>EArye?yM_6dgG$Fn1ts|DNi9Nzw6A-rXNR zg-W3mTo34xP8NS~L$)loDV$}rCpKLyW7sc+30`T^`v%2VuRZdTbSOnBW;l5Xp$4yD=q`VYoHhcR z7N~NnuLaVw4Rgg}4Hr zSjmd>m^5#;Z;8DI!pDg^Gj&|AmnPWhRO}*I7#O8$O%l0y{m)@7j`e^R?6&Dp}X%LN>fw1^CrsJ|5Vy z-!99NJ#HAbdbi#`zay(4XVc1h;}&cMQ)Kh4YcHONQKs<2>?tHkYJW2N1ui%I41O*f z`#p?MK7w(W;{yisn4Ka2yK~2FkUQJ7bI*-)^3M-ebiYWWN$f2KCc#eH`l)wrV&4P4 z{*w&Tim~R9U&fuTL^XT!u&T5k+`-o&GILX{3*cI^93RPvv^^+nC+APv;BKY+`EA1A zGO&HsfbUDcSf2pV@@=EToJPmr)t5cbgC7R3w|dGN38v>)W7347*jbSGgGsN6EF<9F ztgIDTt6jzau3mQH1G5DGiI05f{%&F2e9O_=l_D0rw6`JkX!2e)?sr&^r%aZwXVlgXMYVFNP#Dqh zH|gt7bTfa23zp4ZT&3VT~p{d{d zKcR1WoSAl9FIuMo09ZKgN-QJpNb(zRi-4@C*{MgF8w1{G|NH7UZ!TU`U*+KXAXIW` zh&e}yzVq6MST^d7fu~ZK-n=m8gc17)wAA0scoLt0C`P(4@9D!%GQvn(9osImttOPp zUEYtn=}Fp1la<*~=%uW@nO2L_NPm z&bUOFCWl|@U(p2}>$|W0vUvU~RI%mPU6CH0P#Dp|4R;%t0Y<_m#>qCQgX^CjYow)@ z+~a?|POA$gWC3RcaF1G`U$Y7B(aMU;O9~_4vKFz<)?m8seYxUGPuz^G^gr zXJf!IrO%=*S$|jxNqyNK_{y%=n9Afy{k`=km1DH$7#4D&d)T{>)cfWG-W3@5jgx#< zjrr;>HkP)yC!gfx!b1c?`)$u8ymfK;1#t5VTak}VVB+%`PoFSE*CLznu_hZG zWUy!4xw6ROq(qD#IE>bgKQ86vyCqZ*>Nw^=97dWrJ_dDvNERHGNux=X@fjhdBOoOh z@=4ko1?9vvNH8@LR$Yc#;4cW}U}9o=Y2K}HnBT6V zbg8kC)p@pM`D#!lD;P&UzTQ1z>~BFp$wiMs@CXT2y8EFbBa;oK8UdnC7+E`YG6~70 zsa041=x6Ik$ceBnaQVi~?I<>cOnTm-lVY<+K>G~$yEV?p-porQb+$fo#!l+6RAxck+&M}PQ=x;(ENSYOU zHe>pG?v1N0n~aI3l}q)eiwzWzFB%edp`YOQ!Ngg?6&%qlmH>Jgp{THjH4CoM1xmp0 zgU>JU?U$OP4;YkBC-C-;k9GYjY~;H#%CTR*%Vh7)`Zkmdg=jvhpHU}JcbG;iZ?X#i zMtjhOU097WjE<@J5Sk^)ORcB39` zy1|e75ANh(mI>c&b%2+t1oDhx>Kcl=y0FKR2YKYdom+)YJf)?-?6*z!XxAhR$iD#lZ>khJyOqOPM)1~<)We8I4(6TBDRR59 zNMAiGKPQQ_ml{GmbpO*?Tk&+ zS5;_d0?Q@^iLh%}PLxl(@-X5!zp|q3pvn}k+SGO}UM3WQC%y-;_r4YGe8DtX_LN^3 zWXLL5M||%uyn7!`0U4nH^hEB%<%8Ay;;{5aoCDQJmJqAJ!3g;s3K`ymA?uHhjRS!(KRYZ*!D;G^b?()TM#L+XTlgrH+gCB@+kK4jrum^jJ zO<3>)R?$SVVQ)TprQQ_s|0Kx&@K}csci!-aiM+uxv zLr{qFlZeb}d!zG5Zm@+eoY)hIFLF;P>mUih5kD&8%ZEbUTcp#%J7xnLGNnq@A4Djc zsNSj;D#bTKy^+mqVk1AAFDHJzGDqY1d)X+9&lN(FE2s68$faNXXA<(}PDhYC@B4@L zd%@s8$=1riD-?5Is=Sne&qR&q4o%MIZsPMUOwyH&YMc7{X;M?691qR!eg3gi!d@hx z&Qz*EuY~r5g8*t>@r;zOk7r-afGi-f6q%dt`@B;QL~PxhX2J3sBUZ83E=E+vuoyN1 zk<)@qD&gVtjw(1?2<=n^bjGy?OeMilp89qP1>Wg}V!TYWdNR8Nu!H^)aK;(Wz!QgL#RD|T2Tfq>v&?9n<>*_paC~*bqc26kgANLVjU6q`_GnXE?fmwP) zRKW%U0k_TI#KO zy!8hHCwKdGldZv(X;A3?Jmq}+u-535nRBEgZBov^pg;G+I z!+f~4|HCT=|7~L^4j{A6wjPccU(2uXbC`V(7r{%HJ?+(d^OwfMii+gf@+Z_w%e@vJ ziAwExhn7^m_y}2s8wlNPNY|^-Gx?N(L6jF#5CBY%{0ut@gnXk|7RIr$B2On5JW!u_ z+Q{UQZ+X2fp*}v8_5mfG6b{A4a!8uZZq!pyTblXww1UuBz1X3VYAu@7xv6_W z$?x0&Qvv)^l^`G4mabB0L(jW%kFWP2tu`m@@5;_zS%Q?BCZ@U*2s>at7=DbgZeryv zp8$EXwStYe+sqKaYi9_+iY2=wcWxEUd~X0mkEvQt$M4 zT4i|*wzSY3vQ`IJVP6SzSPThc9wU*M-Q^U_;mY-Eq%Av+T#rdB15lRL^SG zEIjyJC5>>Zpg*B^=d1&@z$EugK!x4ticiD;G%o6v7mgs>r~`KjK^o^1D~rl`J&Q)v>lrz+v4G9ty#~_*q-3?1wqMZt{Ud> z1?sNrj;D_J?Q_TD)mSfSWNph4<0)D6&^SKrs!s`4u19|Q>!cWh3J(zpy5Qx;`OYJ5 zSM)Q9A0gkP-)@xY?T?yCwlxgKSTbFITqUFC$!(j?-tnvncH$+Q)ySb7ADql)yP*VA zhMCp%h~M+H!dv&~;B;>Fj_ZTd7Pm&+mquBBX8w_kv_!=PKXts;gXa_j#}%_(mbpkl z_<}7XV^=>S+|#`9>$Kb@OkrqE`J`4qB>jPkWHB2z3y&?iv>Qz<-;eJHf$wC(-{5 zDlyaBgu8z}@K`OD6A11d<*5U*t~oGy{r|K~!*`0;#!V4`oJMTyqE{4}Y8J_NksMDB z!-vy3DjcMsR+3~*l-;7&<#8o&HX?j$)B3;uUj4wFB^*NmE8KU{XiaNUPkk!*vw6Ll zMGL5p`e$*j5ILG@7*|gSs2tq8E^-?se2u9jwM0xgN6pNl&xI|Wop6k#QK=uhU#PTXW)+UrK)%j9{Gr0IYlyxLx>tBfm?O z$-qdoeV*;qJ8=}71(Z=jfgxwlc`gge+?<5WQ1N{DUbsf`s2DuX(SY2he6WA-V`Ooy z$9_h)B+Ow2Sa3h_elb=14nk#}u|}ShwShe#hjz^+vXL2eH$^XUtBRpEZQ88(dj0jO zMXyYR8%_kYL)8xwG?3uxnm2KF<@Ai+YC?tdLWWi1{aov^hvKuJZhyQChATLWd(x*1 zwAE%!2M#KsMMmJ@z8iTDMX_r-V|v^-;$Dujyvweqe#y$HBjiD2hKtcUsX8T$uBb)& zvJ`T5FH!+>D5T_zT}gyUN%!q{)i?vm_|Q2SO}O!QW?xRu@*eG%Q5my9cvvIMBMq9A zzFLH!3Sd!>W^~b2{MaF@V<)P}`^-D=-r$W6EZd5a7W~+yl~C->1vw=1DF+^|G;bN> z)h4z>EyMWd+tb1Q`v|z<$M79SqiQ1n|1pOC$oDeAWWSc{PYXEdMz8snSn#@XYgYL5 zNGGD9!Zf6KLZ`=qc1l^|ir97^J)cbt)CBt5yH#nyF^a2-l16 z9dtQ3MMQ;ZX~8{6BGgGuU}ezxsZW6UKB4{Ci1J)ldaZj zEor+Mw>c+{cvcv^OcWKyNpW7FCF2-o-j!f=Z)o|?j+kSdK+}n(Z5u{B=u2zkjCF%h z`XBx>nDqr)X!VUjQPqm5Nq7N>+V0%7jXxPH!tZKp!)gqT#X|ME@<}O{(=_EVkWFjB zrqyb#U|hfFXDbH-%C~R7|8VdMv|z|V<6}anhc9k-oP$u=3Td)d?vtg=PYf3E_TwnI zjccfdd347YmO>u44&AaoYQ72Bh3Yy4T~IquBVV!UjqLS}*8`loKV+#{b913{a<5@d zZV)u@$$+soL*&UBlTp>o;@UB}=JH8K`ePSo=*584rKaR~=1N-p2{7)MkpT;<@*!C~VU1nUjEq7C2n z{eRZJo`3W5(W`c+H8C$p&_hfwuVWqLOORAW9wbll(=l0jzrD3M(TR9}ecySH*oYMj zdm6+Umv%*bB9f~ew{CDkrLza08qw0-RJNySOv8cm*H`}#g*7*_^r}P=$X)6F{bw=( zCTn$K5Jexa%Z2mH1Irs>_?<7Xw#Q(E*)|^ypR-D!`v$aB9mvAktwyH2D3@?PswK{` zXtN#!OYA9jFuYXz!yA7V12=Niy^M9MMiDBi-tJ#si0yRY5>v?ku;J8@6(KNSoEqfK z#>GEe#G4{dL6O<^l;SoYuOl$8Fk;55yajA27+A1nQ`;gZ5SP2r{odB{L6WMP#NMQz zR!&+UJ~1KMR;*GQPKi-JRz;pWZM~*lWYp|=Pkt|yB}0NTKE+3-pCg(a1V5t&iQy`> z6_R9h(#tx=b6F+KL%A?_WV@O#LuW)sXBp|0qRUcda$^-+0?26vX(&XOtzI;iUuQ0p zsG@#$?sM{#`mX)yG%x|#--s2&rt;9A@Hi@!QS;Cy)fTTklHm~o0TaveDL#S?aj0KG z0u-SdD2DQg56~Y^m!rrvO~%}_Slh$qoK&w3(b3S`W)4vOJmMjLFB=uPS%l3CYa4aq zrmjjTTS#^PBN5IY?y4>qsVFgt%!6*JE)eYo=g5`@+TsXAs%6vD@KOZnK?lVHWzkhvq8 zTuRJ@^{(6tAM(ZiafqQKQ@EdDr8#rDLm1+PK`$&p-3{q@_`Q$dmkPMWcxN~CIxUBj zrYq{H92u5|?1PkN@39pWAE%aUyv(+Dn4Ehbwfhjajwp9_iTlG#;ss_5Bm@2%`{1RJyx(6Y z;&n&l)%<<@Nj&6Xf~NJe|oR=)X7Q$OrpDd95vW-ho%?Cc>Q--C$j{@^xP8kuC}=SzV!Uq6;+es z5JWt+Vbxyt;`EqRLzfhLS|Wjr>3acf;p08VGTHZ12dAFN1xb-^G4G~Y4u@+BE49+h zS=d+(JTZYg=k{eUo6|8fSM7SKP#SM0SQT;f0YCmA0lB4M_Yji5r)6aIKRO?>a&QD| z6`@RI>s!PUA<_Z!XATi!ESgiVj?qPLpX zJr)_sbegKku_R(61qOWctsd|>K2P{It8Eh%@OpbK%tu*ENV`exJ?BhAm^+;#D|A^x zt`O#?mBiaoLT4;Vg!i~XNj-DpV;c59o4iRRbeG7v_^nB#-{VSP-leval{r)Dx4=N$ zj0kT4`4*gv!)7Ur-*XF_UTNx350pX@9=`JnHvG`|%{2 zRQm)_j6l7aRHW-T@?-5K!sePPUUweKcI}aoIafI5e$xY910VwbJ|6aaQ9@Z~&jo^R&~DH+X-E`aNXcM@`? zs1G=c1@(R51_5oDtcA<74`d75z6+dY(XmK7iLt`{$#S^y*;$`tscA_*U7QefJx7Zh zIeo)QWzOkKSEX^-zoNp*5?!vsFSx6cT<$tGaKz1z={Arqblp7sj{fTr(^F``h8SU> zKxll$@FXs=X@r7#U!UI}rZ|RVpp~Qe%c!Y(1B&E=rrzG|$qy-((d5gGE*mOtn@ylA z0rzo6-xaW2h_qi`*k^AuRov9B7*`31TR7If7+N8mYY&Y_yv;_-yH>AQ#ha#idfxFd&48lPZspl+*` z4pCJNaH{wXX+YD@K>LlZz?8}FAztWVbt!i!M*p5dRWlaqyb5Qf<8D|GNQRG3zd&m) z$C?XMf2_)|8S9LJ2igl``H<{N&TNR}vpsUjGrbgizv+iq-SNOcxO|U}kl4o_6XdRg zn3j%38?!~@gU-^Pa8}lT&I4voPXO_jmIDX20+*<7J0iW`8&8#&<}3Dk(mGnH(aa?H z^&@}utQ2l0FmR2MTBqI&i7WX*ioC$S;}JCd5u;9=aU64-WhgbVrIk(NmsbStt(O`< z9KAMQoaVk_EmhqeA^JBexGFfmn*C@kh(2m#6GPz!X^fQTdptO>#fzyOffokq953)m zZZ+rGy*;BHJT_XmO_#7o{e3Yb3DRUXGmWnthK*u?%-`xB=Z&AcuB1)m|u=({L^7`{H<-EABR} zqv3f7TO2ipCCX?eKWXNc#+zuP=T(Z_7_qbf^4_=d4!`EmYOrGZJ`)14L2&asz9qEE zG8!J{q{iRt-l*w}EaBLOt6O0#$V5+#h^$5bRrf;Yt$a`{f#d9jkhFwiLNnyJ^V`zr zqNm;Ce4`m$S)`rb%~u*Q{~4CUTn{QcDrGw`oOqxLELvDa&b$es`6e@tMS*5HtFbsu z+cEP^^jnCmCndR{YsOseZ1>}doX2Tn>g7sTEE|U;DCO9^nYtE72NOpw7D&LQvwyvO zc>(e`u-^KaQ=HRedMTPpSDn(MjVq&1YfseBTqxfpSBfXeE@N!nS(1JOF5w;)uyLSH zn@k-*xxL@MILzJMdO!7#%t`$GQP^R3OspIWE-ZShbi2~nMV%E=d7@b1_c$*B0@dBj*Cd<ef%xtR8KDZBkIG zHS=NPxPbl@RTb@9WW1;zuQNn-_k*0zRgXZ6$4Lw2l_p!A;`hlSACQ2;3H4xq$}?2e zcc?=I0olQ!Aju7nqr44|r`B_$iAC5rn-lhPeJt+I9f>+!cvITvjFJJgzlWlmZ2jo} zXjar-1}?BI)WLu0Xp6f?#HoK@Se|Zs32MIT=ADm64;<;o~XJM>Sr29YZNC5q&`B{I*HZ=qK0mw{4`S^AAAgS>n|< zPST_=w7=K{9iVZi2>TxEi@_2sWeRIXMPp|*r4(hyrqYoiUVZpT9Zg)3w_m2sy;cMR&|2q%A7vDa%jynE8)51csr~yC zIKTHxP9Rnn{5fb~9Aa<$3M)sOF7|l|!e+e=Sx%!$Lf;tiq1>4Zw)RY-j_l-2Ok&#K zdpq?swa9i9?s40d)kpLjf3}pqZ}u0MQWpe#$2nJgd~Qj-^YbAZZ;}2t-{<+|tjw&W z4k@!Q{@1h0$IW8s(a{Q8Ee>R>0{oI1kh5a0VmIamSx;dwd0r;$e;cERQX80ELqD747D+>`)JaZq3cE1y2YNx~F+)*^ z-m=L<+%m82J13jzd!35A2$lxSJ3ueyG<4heva9^*WdWETZ~V zu2tKtAvXM_OAjR6socJ!M$t}tZRF@tNwqfNvN1H)aJZ?X60D)REI)>Y&&-y20XGWEu%hOzhZ!a7j zm!opLE$^6mXRS!Ts6&+S6<|Q}3UQKB*?=r~obrOGkfYh@pvFvYEq$fArnKW7(CYfTSd!Rc{u@WM!>4O$##4_|)#JXa%&G0F+D zi)$6&W(OKs_KnoCDR4Yef{NL7`#c);J03phrEOIcx<7URlVz}+Ii6}_SeAk28FBIj zE*aqb-(Z? zt2(7KnS~}wPMWR=PBbFYb^qPpJ0SN(bBT0@6B2JPD8-m3|EYAJz}HSXgF-r_64ZuK zV5l$W(r=3FipacTnJ2sQh^>Jacwg_oI&O+W z$tI6-)%)S9PirX_Re)R|#2?CEppc=X6DM5=HhZPu5@E9Aq*iHx(?gq$N3PVRc{q)! zr*!&FW3|i)zaWo_0_D!QE0k`x?qq=A&E_{9Hmb_rB*-A3po~PuQ#3J;a6WL zcx!HUyn1kyk48%Oo9R*d5{58?d9r7`*8*M)&7AnS%ueM-66l0BbkK+m7(Q{ZXHwy$ z3QBS)d4`VuTrl|kdf`iV7y+CRP5$#!11YJbk&T5vG0B23GED0CvMULW^7Q^fRcPaLXOD7WPXuNLG9xj z4Zt4LmSkSc7GJn5f$HbxJyJVHp~wT;1(`T|djGEn-mvFqR+mOtN$dVB7Clc>Qw(-t z1P*Pa*qCoNHu7U&WkCGF0=x_nq9pzYpAVMA>%7vRLesg+k$LjVl{r%6A}EiXDbj1j zm#TKbB|To>-}X?q#8H*F&5I@AV`PoyZ~g6Rnk{Xp`RwSVUI;lHT^O|kv+sp|(7fWZ z=rW7Pq0X0?`!lVx1v`@m7M3p>ohq6;G$~2AR4ij2?Y6-}zAV6#$TkkUL;1tA@o@*e z^@#rJwB~|{<96}#9Fw3DgptEw#zq)6r(qS&7H_L1N-sj;9PUu0+%p>?(@hp!f}G5* z{Q2*wTu*Z`=%xJsyN!NeUAHCWPZ1YhR-)q~tz8#yJiNMfV~%PJWaZ6+Nei!gEirJpohAbc z(>yQH$ADLUI*yGQly(JN?>03+n-Ee?%xl@87ft3v*$`uM0>E{mkH&Yh?g{bnHh7wl zW48)wL9)Sbp1NYCapHDfgq`LndvopvgVk?OEIk4_xGXv$>eh>2&jyh#Z0u5~6Ju2R zbR?91QYF$|W;FfyKA&hD`6@ThjhW6Xv{CHuN#GeKkiUP`7Hc9HG_zyP>wLm1{P;jY zDCD-RSBeIOh=pHkf?>T>+1GToR%`mqYy!{?^iaVI+6Nz?*FXDcD=){q>T1RoNnzqM zUv?ia#H{I$Ip*eC7Pn%Jhhnxb@`8`f&O|xm2m4}00__FgZEZGhN!cs)@zTd5e?a96 zvN5-6TXQv*v5Rg9BHJO_D5VGd)+#{5%xq_-p#3&kdOD z+Dq;3U*7&uR7?{}L-U9*I(Ev_(1Vp=2+M6sJ+r(Sm~6cy*X{!iHfACqrc}*8Y6AzA z;~bOa`;~JejjX;Q#Amg#Z;xO0J&eS@;ezdm6hJ+K4_DgGry;T|;ZoQ07L-*iX!>mO+6=eByPW4G-5p3wmac+|(Y2MtNqz-bH`+1Z#W zq}C3W0c@G*o7^zS{ipn~ACH8($PcG6*re!LnO4hDHMD}vy~1*qjb?{kgi8nX-IQA%xGos>D?0J*`7 zf6FWv+fSA+{1hb`87#NLm!N>gpMwU*8i0rQR-bNlSJ3^Y7tvgwxXMDuxI3LPAaqYh z;0$K_bxMXV*gVJ+J`$sQi@Z*_2vBQ%zxQx*&9V)q9O4>FwNnB^789NAn!Na+kSD`* zrOueTRm5GCmUen*x+Aw9pWk&Ww%SycSP0TQ^J%iE`eCtbFgC%qU#Xa1Mf>efjKUtL z>Msvd@AaFf2Gg#qmOqhh+TD;WiY~Ehl#kmAgrWAUDe_%ymus%k1)pE;FQ+MD15r^I zzOqd0OmKYUqIxM$O_Qd^{O60>;EDLo-#Yt50)VYkFLUj_ zwF&i$Xr}`a5yzckZkqI2-tMW8u=yi)_#nwb=)NjMav3?bcDEP>l5$R5ywPr!pz3FF zW`k?BeD*e&u`?*1V?N8Mpq38wVE431py5#Rb+N<4b*$s=13EA|`kRXnmQbhfFd~bg zQ)7uYT}qV}-B~*n5n}tyVj~`6YQ?Aa7G$O~>4KAKQlDrA1uy=LC0b7S87@l8UG4}u zE8DYAOF@!H`4xB2S}hjvI2US8hY%x65gf&ed-cA#yVE_8R_hYmve1yq@=qxn0@)M! zU0uWsi#GikOzqQMF378r#J8s>24T<}W3>*)2wZNBF3b|;N8>I>7EEAcD$#YdKw9kAa)eYg~uz`l*YRx7U`{wQ`oPQG>g(QI!70 zzw8s5(s!}}=zvPT14!`z<9-;6`I(EeAWRZUM6Sh>l3Gx)aSwoIR4eOnc>8$ zNIdhhoQRn3D4{P%Fi+1l?{l$^N7uf1Evq0J6U%9CmiG#3F}YN3#U&o2+oy?^^PbPO zP7_{~9LR$|X$ng&<++M`zB{LTGFo;x6R`;rpjVWhyBozy7gH+_i}6-jNwU`aa%j@RSP@i?L#>CikaCR0e2 z;5wJd=D&YVE!?$FnC_ zATTzMHJj_z_IZGGoBy2ghmFClgz#kQ@d#bNqy{xOthSp{#d0BPjDC$hpU756y*s!w z#o-@i^Ky_U=hedaUv5pN#DB2G0SRAVjT|$L{~9-L*>y6e$XMUtvhg@%U2>sQD1=lv z3^)edl2F7650i(Lmw*qauGUr4$_6Z|#^@wie1%#TZM@(HO)3!uy(8uB!-bf?7whfE zG&K+HNInT3^!>X(GN@tf4w}>^_)0ET5V@fDjL~1K~U@^ z;t^-|9z9@D7dxk===)V+iBral`pUIGfR2v4V<5w0eiRqOb{1?J6y^|o*-Ur3(ty@d?4TkR)C2#4&^~giFuW-+Q4gY0Qhzr@KBGhppm! ze6~U1%Zn7lO24x!SZ$kGUM*eHraT42m)VQeb)na~K<;8FO7n_pjyxpp4oZ;Z#8J&C zb(#1gVx*f%O92&sIl4N)9kS>Rn&OJMH+v0Y#hQfq6p0@=}UzaJ3qIzu@v{l zHT*hajqM@Qh>uz{R_cQW?2HaJ!kNhmW>!F!%aqvQxD`kdj=Ix3qMAkw zm~FKLdMgV>S^$Lxlg8F3B}@m(F5{&3N@vjVmG-=H&*hmJ=maGVB*-VdjZC{zzPE5Y zV1Gs>>0h(&3PU_pGS09LY+#5EP!!(zrr(CS zs&;dIN|jNTt4QR=Wz6NNMb=w;n4Nf2wl3Zy>m4zFq84G}Gs0T!arVUICNh?3841QMbN?dmH3D8_x25QmUGQRRx z@{vOXWnJa`6QFc^9;x6l%l)H3cd5|o$l4*qKwv4rR6gs&GnyU8s)4Su~X1}C`G zeoiD7zPoIfoD>%!36Dc_R)RZ%0a4(np%8F3;{32$Q#jI3S&j&>WG~0z&(9R1`=jj2 z^e3r!65QQVl`;DF=Y!Ocerl_e%~zMG`+kX9%m(QBE4;YkbwI7!1gIJ z{8*!JHc&J%L_G}MZ=pGgBCapAin+W+E+-}diiEiQM(c?*j&CoXLhu`%CUhqR85Uk@ zpv&!_A2vN+xqLeAA@y24L|sOrCJ7~Mkh#-r8@}!(ea9mq8QSmi!;(e!CDYe676P!- z^-~(^)g8s&M)A4cs+$f30mT4il={0EwIvUa#N9%^iVKIja{H+YnuOSILgk>V2uwE1M z*vo}cFG&Ah1ekoveJoDfNs-n#jpSFJdP?IU#y}UbvKy)6_#J=`q0Bt6_eDwF2KzS# zH$#WZ*q+xgUxtZ3*Ze5#nftMXnoeCnxv#I)r>vZeMbEu`ViA`$|X z$gv_bFH9mrpj_1`pX!V|_nN`R;j&Bc=Dmm)?57g`xEv$|tEh@_L2x+5k5 zLzh}Qi@v~^Z_8}zP z;tJK=_6TIFRFFi`33v_X7kuhhUGA`j)!A>4?Dit<7HT==J%rlV$)$SiAc8U1&P=J` zrpfXQ=ZGF=YzOc1_tBeDJIdlo_X_etFvWh{28LF)O`pN_G$XMMB-{i) zf(^yuU9^&i*LcYf;;_O)D|5xHp063oL8B*MRbt6>#}kTC@%v&YP4v{DDJ z3OBqIK2#$|CLve>M-_oaVO~@66wKM86dHOarU`6dNoyh~%#J?&lbaQS@8Q(;UbA7} zXZ!9TU+=A+%f8$loh?%=YN^nAFlz_|7?q&-pBRpsvvG3g8P{}zRI3qWie_i;9rrmv z>=t-r>n*JcY2pnh+jL?~z@F@|;f4m$&hcuLV-RpYuelf(Q#FxxHm#sIvl9rxLxAMt zA5hF2{L)VeW7=hyQp@UL`zacT?20e6@$y$u(09MtJG?+l`q|iAv@V4pEAlH}20$UN zs}xyIvvQ!%J7*SGi<;v$VzlK;UwUtg-`Esnj4QL7jI($xz}ei5jyT+_>|6Qvy{7HF zVqNX-(JI5{HiC>lHNK=ieV_|}=vXR?@pi_zC>LQuc}EKKmd#hMxSLO9w02&qPh32q zrFmp}ZL{HHxGdWV6-*tN*({7ec#=aiYV;*osjTjq1kW!8s8JR1>6VdcY>IOpdU0&3 zUyQGLnGJcP`e5&j&b{q-JKZ79#=b_h0vY7*XNzdY+^; zREyJM`UV&@_5wFzcUP+Y5%t+o_5`CDtVLB8^YeW!FAJEJsj4B|$F~WUzK)dLehlUy ziGeOCO|>=c_$}_G72V-`@nd8bE^cA4pPMnHa@LyKG4geU?<1JQM4}ckC%wY2 z^ALiaxj18kZ5*O|TIV=;uZfq)m3ZZ}tB?|l84m?XU%0q?_8pFQ7d4h3`RFEZqf!^{ z*8vuyVL|@eDQZ1%7CmAmptUw_(CV5F&&#Nza; zb4_qxkiFMX2YRCpkEnmyyX-2c_;eqdv4oFebiqY zY?WsEHank`M6)MLq9x|T=K!|F{LC|&e%A{+5?`_It7GO0$l;J4MV z(?CEWm8$5dOQjZbC%}DjJL~3;!ym00EhS!9*fc+#osPRO>q>(b3S+TX8>Ag@)m7ET zhy=vmo-rOV$&z8EMQAW&%9(*RqvvfU)RMd3tHjM{A)U6r1s2%TB%!Y#+%=zk73G6Q zwvGiVlp*%FrOFzL`bX^wgl)6q{U=co`;yrZR@8OY zVB?lrlLb-!kj!tPsr!SThtUDFsyUYg5@^ZU-eQ2xvLZWeUy!pMLPbw{sB*}b|2BA1>>U1SUqSE6_D-ODCGu7OvJRXvy(74FYcm^ zb;oW$;L82T{+{fz3&_=&c(8*olnA(JQw1^#_Rgi3HW;Y)o_>7z65uN=$QQ}z&tDBA zz|LNser;C87IfhY^DC8&+&4Lwuy6VT4d%HzU+H;=9l>Y#XKjg;;$5TJmEIgNXVmP4 zq;w|r=|2bW&9Y{V-8FXsAYghKu}VA87x`q7WqIU#IukJnjNTF+pk&sqy? zP7g5-M?Jn3_Cftw+XuTqyGHRiRE0VUV2{K&B{f!Tbhstu+aLYHX9hhkrTMrY>?{IE z^~lo#M26v1tTkZA3cg|6ta-+6^2i%AlSDie|1ibU=~2I8aIi+2WUeN=o`QXy@qpN{ za`5{pvhy2*C~H;))z^|DQq=EDk(-AEN!bDq_wYlhc=gTBcEtF8MT5ZF=*XPg5>UN_ zo1a78V1y-FE1?^4kb2P6a#&6q-o>Q}RK*Ok#;88H($xGMQd&RS^z=^{ksZctzjO63 zT!YLGJ( z+t2iK-QVZU@7??XbFQ_{bm}tfQCk@FrhIeBt zvJi^5ujccR-u`(*9PR1W)EEt@`V)}29t&Z=w!PpcP)G&e7R&PhT&~iL48OMbYJ3D| zUGxyK1RMG`CRh|?L>5@}yIFrPrOM30I+ZABKqq=`b;EDCgp5Q{ysO#J?HGrsz)@%( zmPO!3sX!oU4|bbdFm16jO^}f*{Q3mDYq_AT4c*!rq-e1g%s&1+3BBBI=(^m!@}Id! zSi3!%J{?;(6h+t_j2CR>odw}GuWZzCW(|dPh8T&x$nBbXpw`CB&A(G-pc|Mt?ymF{pSMQS4G92++4GZHt0 z&R%H)9iq;!mi@&~xVsDXEbK`K!&a>F>C(B@v&NF*nW7+?!|5rAN>g-e?Pm79kZI(8 z(?&zaJwcaQ%vTYaTCU4y77=O}7l;tSbmrV>Ml^xZHh)Q)&c*x|JfPQ;qjMPk=vXRy z;*3=)gT?9n_6sK?mVl?y>GTPChoh_~;iSs}nRo>6UoB0G+O<$j;{&H-6}c4%A{(fuVj2PUfZeHX)6AvqFk^gHHXJ6XdahMg7Dlz<@6B zmLun|q)&Z)ggdK>w1LU@{*ho{?%So^VKUA#=%Z}4o|c2>>r`nEg?t)gZ&SJtFN2kZ z#qhkbszV(e?SFLu+)iWGe?LIWUg-b5Q_y`oTk|sN&A9WZbNj4Q10&Ou_X}xgUU_Ed z337T8xOp4OoFK_%p*X)b2&2z#Tj}DACYtZD19zmR`1aQ`1r*Z^(bw zgE@z|D%Nko+!CkCYLzKDw-?X9?W2ewh#RoXn;Xk1@2zF_hEn%pDnhP*aX(HO^o(>& zGz9wC@ojp)8{=|aQ93AcH(5rDA;{!3O&|&5pgXt^o@UnSFJN$go?qrwb%BFs2-nZ1 zxrCS5KUmU)@ubDXa;-tYT0o19sG=p*&3p(1C50}Pz6EEb5K*-%kmf{(#84j+l~~XN zr8%jzE?puV$+XvAZX#V-WpQ+f$?RMssCYs(&l5zsMq$L=cx0T;1xEGx^Rs4LbswdN z%Y&l$sjWUd$nHwR+a0#u`5`np?X+Ugmh6=SPj_h5(J^AEXh?I4eg)w0+xTiO-?;I# zcDqUn$S*CkdS0%NLWoaj$P1ig7miniQqnBgz~qVWE_fmf(TLw%5_q{(=j?yYn` z$soCePB*EqfQ%l?m<~n5-gw;}aC4dgU7Ecy4Ng4J3R%Qpb@Q_PRORqr`Y9%+d$rK6 zR1z+|2sg%~E#;!tkBd<`LY^!9N`}c;*jNpnjD%{IMV>ib{QP2*;aji+x80u-0CQw|6t3yQ9(aJ~Bo;U{0VC2u+u zvSXTl!I23lmj@{&4J&5@7MHNMn5Wd*?74D2PT6aZ#!Bmq)*PN?%2DZF;rqF*NUSNw z8K(9U%EBexhwG~wluI{e%qbBJ#ude)) zT=Ku28ELCETVe0k0qO1@(o*LR|GKtM|M|H!37xVN<_>pYBqcSbwx29~@&dUyfn{xG z)<}fMx1&{{qV->u0K1j+|D6f!|NohI(xfuAD%pBZ{Db8>&w>*6DKhvclYp(hf^yVw zl>KJj_D)XcLS#r#`YE@)%%|QR7jGADdU)Hbkeby?F3h*zy&}g>CqPO&kYubRJ=1_v zaiY{RqG_;EZ#8aC`%T$eY07f+SdDtBvCBU^@nQD6W=(I%pXcwYXL=i1S6Jx_-!_JG zg#?)+4YUX|hyEd_uNJyiKj;1nqp$r2R)lKvotrtjESwQe8!$L}<;@+_LCUOZXn#o8wFH7A%T7wLSR1tH$_w z@F0WqNN$mx{uIlYM=SK>`DWnAgBJv~YK?GvwT{C$d-zqWF4R-Nq=v5eVIghlE8u{ zJI3s8VgjjZ)HM}8@%ZJ~bug6ysMy|(tDyDZt+H&{?ZuWNR#;sIfp?Dg(zSDEf^fwA z%jrM<%`|^%iQV&mDQ+Zo=(X^m@7I}uHeu%?(^j8iF9SN^jC8WRTVY8vH?RBq&rH-~ z2l;@>8iyrT_re0A=w7lMdq@kRG;0FR2?9$ac5$MS#1W=R*xI*xcl*F4@m;F3y}Rg} z(#^>|ysIBRB$8*bFPWm?R!@9!Nxc{!ib)cHW99eGZE}!%{$U(nb``&}iid zjkcm(fI(6wphz3RcMv(T^dlcHv&DJ{9Ff}(kIN;mpw{KEXEV1u#( z4od8E0WNFh2FDH1R511F7La9sA`23D0KA2NXS+jODk9#lxH)N=F-^5d z&JuuaH(!)spwRO{Z-l1VpDp|t!F6*KHOVbkhBwd zY_1VWkGS7LK7!y|hq5#AJ+*2Ozk{q9D(#Q+-C zgc}lM-x#TZl-3wG2Q^<8sqs|#xY*K?Cq)zK!ivF#Jg|DE@f&rY!=-v_Ug8EhGA^QP z?z$l^F41c3`|8C!d8LEJ4GNDYj2iRc)^4+E&>zocAOHe3UZ%7d*G9tlmJ+b={l1aY z%|pI>1tCNthnhR*Y_v!#u49 zR`s;J#>C4~fTK zs>e$RRjt+w-Q|xb--V|hdxqw31`ft>#ZuY5y~izZlfT|&tgp0R%50@%ftS56v|O{Z z%i*}R8FfJ)8o8m{z?l0WV-Jx>Vsd$G1ilDL+U(vAB1}-2(e5w_kN~K zbmd5~K|_l-^YR)|PfhA|&EKS5VP#|DQs2=X`s%i|0`t@Yc7AYR^(;v6D(jn@vy#}m zkOhrYY`BCW@J3wOp&Dn zptU-9gU$p6f5tp^OA@Ti8+X4fZBxb?5U3C2qmY-7B8Ul0Bp{yKonW(z95eA{Gs&5J z=`Vd3u+96#9j)TfYF2~6R>%COrSc^3`u51z31!J-CM)kI{uwy!&h) z;E>BE;{2c}rN$%CIl;@$6MbtcvojfPc)Y@u#W7<+nC9woH54MLS~Ifji7%vi^wqOJ zUHG?`j*Ev@_SeCOMCS!9WFrI0KuZW;<@t@pun?Bb;-N1v}*xz-=#*m?pJZ#j&+ZOi+g_~Qq7NV=AvXlT6!(bhvAe?J&jQot;PKgAZJ4D+9#vz< zWS>MUZPM7CJKBL(j&W&W!iALWtnq`)fF8s0XV5>Ukkm9~v7gGpLke-70g8 z-Y zHe)I@%`mr%3bXNj;rnoPd&lIPQ{0?HOTONNqh?8IPYmnyOrn=MySNzUiRB60dJX+V zyT|);+~I&j(D_QGgNCg-9RW8tvDS4L*ND@;di)m(XPiWSm$(iM2S>9u&yyqP^WyP( zyU?@NY6*v@W9&5~T~rp?lD9c{Zp<&?%`VwCrlfjEVGMtVQvQK49FbowBT4oZ?>5r| zOJ{nmpprgZ?HhF2;pAcvTz-~QA4>`O@SNjGz~oL#ar9u zenZ2;eMS+=@m--gUn@r$qIMFDeDoG?@!W7WJ8QCg0~~!gQ!6gwRPHQ3C(04Oo9My= z=qD!LaRUtAE4zcVO0vxvdVBPXsxQT7unfh#V?j~AC#ElkN&<)dlZzyD+O2-Fd>`LI zb|EH^aKx|dOjU}&(u9x;6G-6gJXDBY*Y`t97~MzKv(`PW3$D)#^bCQ}R<)7yy9KOZ zXJVIZ6w+S(1yTp(f|4XCbIaje#g zb)uwUeDK^Gv{hH1!3$)LLo;TD^ zvS<2SE^3IOB5$>f*aVG9i7;VQ3pMp_0}gz*-OQ)#o=4f)Mmvs@;a9uUL7%tXn$L#G z8pL9}nKMFDlgRR$q@ytJf#x_L%DPxov1RsuX4##w8gJCcb04e|5gl;>5KEJ@ft@2| z5^+R1=&*%JDyUyFgPugt+9f=hg*?3)N7{K4&6p?NWlxZ%8jv6+$W34-Y+iKOiUUv- zyj?y1UX6&b4WjY>Bf9~e^awm=vYT(!+^V=~XVBC|f*he8xEv@e`9AHt-4-xZX(RP>Sy~j@V%7KGb z4M{1S^TBasC~EG~gf`dk-YL98oiOcF(yf6^=yxmk2I-Phi(~mdj(NO3PPl-Sj{1$U zBBm#rIKQkh6;lWoTs6Y;x}y#^5}TQ>;7gS4)TwVP&bYrFsMmM|eYMs=82QhRE}iq2|ZPmZnv`CiD?n)G24 z{!M1EmM>8gDDp_6^_N+|6;tBQp_mbk-WYn4kP~fzJ`?DsC7^7peCOxIZ@1TC-R_%dhu%4F)q zSQ;FN_X`?R!sbb;{(qhYgMHB)?6Ulz{|&mdw9Iz@$)4N$f$q-vitaEg&bPY*nffs_ z{2Y8%>`7g|>5A(9cVQAnup0mS$)ng3s^uFgi-df8kvESf5yn_AI%;JGRb?zNoxT7+ zrfG#<#5Fkqwj_I;j3-A8=mzP|#9)=6=Hz=+k&HxjFdL(;#-C*VHh#2H5^?O`TUgn> z2LTkW8;?J_U#5<(n{2%loumorxvXs7pHVneCEU$fe?k&I;8M26tL*uOkZ5yv4i_>o z2TPjDY$qaag2MQx^s}xXEH{dRA)>blZ;Ba^Q4NfBSnD0C29KySyC=4te)pNpdEI5g zw>W{fksxN;uB;pu_P3jl?AeBZkj)SkkZ|}7-0RWx6Ca~SE7IKj+a`9VX;+Y$%r=nK za1a3sn>btznmh*oUq&wq)P#ixe^0G5S#sEDa0IygX#rF$+X|QD;~{(7YYB{emE9Yb zfGE4A_*lw)>?^3^JWT`}JpP16%=xSz$UnFc{%CJYsW?KhQYo5LE-`u(3 zMZ?X+b<2T_Yyow1`f!Nw`cE&cclUSO^TD^RPA3I8BsGW+g+Ly2&gwzr>3Ujh)$?HKyw=NIblykP}kZFObH_xJa|P%X^Nlv3%3 zEzNC2h-`GiekF;Sc}TpBbWt$Iqp2=qg_tKTEsR>=mhe^EvnW->YiwY_FJ(+Wu+qKG zHHMW*uF>P}2a0gvv=pk~N84#I+ah7>7-n?@=W!~8OoKgNW~`@|+U>;#->Ath-ya8~swo)H*Qj+NP>{QUbmbAM?V*#Ey<0S5R$eu^?eNyUt+|S6JUgl>{F#Ng?*tk)RH9>K0 z=JPvz8xUjG{Pqs!HYXG3NJ^MS1`si{ikmW-!;Yb%`~??{x?E9hMPdH51AFmwt0hv# zDiY?r^c}KlBp4kHDd}7eTb6^48}LapOY$7&VdHg->~;RU)z992k2{|Z8O_`yRJti5 zlJ3z2I?#!M0H;)00WelKiL^&$MEJYit`*&WP&Vr;6z^K({9stoVNmAeVWPr#%L`d_ zl8yDi@cH8|lmhpB&&v&J1JDA`NtowGL zCy+I>g^;}8q=--~N%Bwf;EW~zQ)keJ6V9lNvHkv)kJlY2U}^uxfbX@fv*9^|P^s30 z5bwt05Db)H!bnK}mMeHH`wq)Y$_o7K`Mmsu`{$Aa2^A#uJGU~cbm5zYX{g?t%!%<| z*Ilop3Ep@}GBAH+Q^26x9S-uR>-rWCC+0+A%BAJ-Gl~iV;Q1C=zMo)PYb;Bh=2#5A zfC}=-ra8l~Tko_+892h1-y|&1^5@pH$PAvml^$f&g^&`C6SBS;D(!vW5o6Y8Jpe+= z%gNGf6!ayT2Yc~HM{$&CQnFV&ef)*S#2@gg(IY>tX z5a$r~=1MUqJSSeWKkQkwB-4r>zer|18;c;3RZ4EqhTi%9tmX~M)7YKqfI>tW!F-C2 z)fotGAUDSEjs!Ua;Zy0d;+u@6uuP5Mo?Hh~{R7bM;=VcxLzx>Ff8EJ5KtMO_gW8Mc zj#xteabdL)w1a_?{!*K;p(T0>xF0V8(eQW1OnYKzHC+oD9OLiIaTMFQZ{|bYyE-Vo zjLASBFp#EgqOP^8rCKUwi~dwON_NS{!XM>;XCy(kOgwzNRgAp4jq(w>I-ft zmCM3WAWi)cQ)hmeaib+*CB^Pxvv11WLHRyjhZAii@FxZlE;O7~R zp;Z2`8dZl(thZw)s9_%`07zhAhxCEWy*DXz0QI@M_x?LHx=m;$nby zNUBIPcl`?aEpcIVksnpoa4h5gU$@GB>tbYfW3!mN!5t-am?FoC$Mq16_x;#AsUB5< z%y{by@>u4i-dw_gT4z$D0{mB&JPu+U*4o2wg9pUv3=fj!V~(vSPB5^Tw7oCUfI9PA z6DL}YB6{>FA@`%kV?0SQU_hC96ZKivHeO>*&kc%9HZWvdQg8Ql?EL@B0FLZB_iM48PY^-JQUXT;THCY(~>+u=WAqj_6Nw9C#GFvP!W#B)1f4n?e?V1biB4 znkOB$(v&4es08dhvc2v-=k;neQFd=c;db!sPCfMMcJE8ZsB#)OqWHO#o zij0qll1aJ$7g!L4l=${;w~ZM{yLIXH=_(_Eg3pJTj3)Eby1fj`9XXHq9PT5vmpd_NsV zs+q_uv;@28`UJy^Oq%g9t8j}J_{jUextq<{|4GJd{%6At?9qn#STcA&>|q6(+IRI} zlE>or7vGx3t#qJ7){l{-N0-@jF4f>a|H{*_HzsK%l#Pq>33&qsv>(elPel2Ou-}x& zB!3s-52je3H16TO_6DDcy%0e){`+=6ors) z_vg2@w(5|6U;K^^#rH*_Ua=9Vua=KyWP!VlHN_#H$>H>u<@JgcjTK(yhMNvDvN8Lm zy4PE8JP|KegtRwyL{!t0C*JJWI+~CWhg5~4K+pSoo6?}$iYhrOzpV{fTN`heO&myR zEE)};zNfK&s}Xf_^3`Dh_2p)AVFYoni(OavbErYCutQ(P8FvG(izV&a|BEh8tH}fc zjb;zToX3Y$W|iW6VhwJ~b2{#ehbJQ&XSr)>CSEY0p&4%?BF=A-l=|jY;G`XHor`O3 zlv<)l+mO3hmbtc@V&Z2*2VLE-?<)Q$F`?CrhM8Q-?pR*an{)yQHR?8 z-GZR{{@$SWC}NfrPOB}dB9*>CHSAGSx6KJGl@6!fZikyLhc6bCTiVT2qd0!sD28gfgq(tQsln?-ApYn>@iiLlvYj?-RdteG(o99HN zUgtkjy1mRB7jLZQai85UU;dyPK$jabfl>@CDiq_U1BimnKmrnJb1jOI#f@g0^8nOF zUBBzkcsD+;_Evo^1J&wGz;QBuBcbEp`c1y+xlB-&#D zUduf7mgsTPYN!7?(>pVoO5sp_J024ZHj+CUQs zbPW3qdFv`+$1J+qqc`bW>}7+q^7?9bGs>^kZHK{;V^QocTo#npI=yNYMQM5w>2sRr;RV+E#?JxM9)lZT z&ran3O0CE?jQ2;f)@A@QKRRsq{7+Yc2|m~)f->dyOI)V{9DM%pjI_5#B+BM-OlS$t;JPnV6X zPQ28c`UTXqF_^7M783_`DQRi_1d-ko^BwGwyT!&qV^SNOJ;OqatR3;imMu4Q(PEzZ zfxxhY#t zF{Pu{?X3pj;g|m^@z-+F0wh z)1%HfM&+aj`dKl0!<0P_6E8S*?3IN9Vyp=h`K{F;D149aRn{ySq^vD%1*CG_p&Irr z7#in#JVOVwpmwfjg4UsppdvHI#CmfA`NJ8YalOq8e?g$kNP=nf`yAKw8XZ5duewSM z%*;Vp3#rei46KCHfZ8Gb?v!ME^niB2YY<&}sj#~ZT>4ylwegmBpctlGn z|3*nZnBAtaO!`O?I`pq}jx>H>^Oyk_K$O4(kYppe?GwDR&64JjRPg?m9}{-R=L?A8 z6+6^Q8dgoP7Yuat7HrTlT;KzSF{<}O?`Zwlf}I@gF1Y@!>OX%RCTZBf42Fc{skS4HHiu^O^eZ!)l?1YatDAPvwUW6w^QArJhK8(Blr z-=_SXY;qV)Zf#7deAdy%p&jB(F7xd{A50~nHJf{9lA3in6LtEfpw*9G+%a4=niIzm z>5dwem}c&2z*U8@T`uke-97OA9a#Hm*m<){Z+CqMy-yy3Jn=8h+GP??2QgyEShQfy z(&)Tz^l%)&CZSmlIXe6)+V)4RTgQ=lz-&5!FGfNRKkL?0zjXAB;NP16%H@I*vIa` zuFIZaVyH(;&1_!hub9SD+sWK(*YaH^0`Tgb`NA0(e^c=n3&-gR`heiWVt@_~{mh}P z2)5D=R+$CrpZEtAevQTEXFqf5|B}T{lu2gvGnm&#@lk~O5S{@G_DrgJa&Um3RznSJgLwhty^5H~+HIfPTn-tE z#5COL4>q%~Lc!qer8FSR6dap|pPIzvEJq5#<5(3~WHeqBs)e^q7)1-Us)jayJe&}J z#+f7{uo+~Ye*mF##$YP7dY~V_Jm`Z->9-N1SNg6!~e7?Ts($CW~oLY~2i^?r~#P!rF z0mfu`n_Grpkz8QHH4q2D^ukmbpU;1HuXP=Dp`m*s)$VhCE|%1}{`ma$l=B~cNr6VU z4W~>hyC~A7x{yjgh+`xay~c1P;V7A3RuT4WvLjtq4AAv{cn0)3{sQW;g@T#C*5wmQ z#mMTJa7LmKP#l{p9X7vs7%KG}?=8i$7poCxL4~Br00R?uR8^zJvcS3P(tZk>l4HIpgG7x*m7wSh5-QAJhDkn0=JfHuaBFMZDi{2>Dilh#8Uo}x2(wsIX3NS~QwslA? zRLLr9uoP|2f|qxq(GJP(xaf|3xiv|wg#v8+o+qq7)&K{_$JS@#9hh&GBuRu^>(P+sm1Vg-5zrkwA-r8Me^3Ng?q zEzt?Zjg0QM?xACKo(f7=#gpu&LpIVJ53fuAuDk6EU7GE@_5V|Uao#__WI0E~c^mBE zo*wlwRrbD(56SpfET9Dy?78zQ%+i)KInLNb&xYJ$v`f9rNLbi8<_On&ac@E7RB6UlFZ<{&9PzdqPX8=qK)>nQJBvMnaYn#2?R+ zUwHWF&Kjx%C;Jm8WgxZ5RtM>@bvrKFM18SA$Sfj~gN_LDmUIaNd~Li+xCP(;=CP(b zDK-DsdNuj4^~#_0d0-&JG=At7LXPb@m5g&VL&PNxTEVb^%xTuW!GY#4p~!y#@m@*6 z%ApZJ$td#U8Yk-aJ|GbmU1aK)0iATVx6BfzUkXJOoT(sSOs9e%i)qG$IQbXM%CP0{ zf23fK6}~-gk**ajTn(I2ntj3VUXBf~I}4kZ`XN#nG^Nya@-X1+e6QAJ0`GF^4goHT4Xmv`H%c3G4#m4tO|5*1T!a{#KTvGMB)@F~) ziC!~CjmY{bsSc82*40Z)NErizx^8)cj58%}5B#fnjq9clI1i?gHCB6dX_~ufT}-yZ zB2HFOv65-ZzF0q}O15Ny;eZ4jU5 z+1%=UfRrII(Fs~fdaf%NbFLGjBY+vjJIHzHdZc+&rH9n{SYuvo&*F@69cV0s)pNio z&sL4A?EMocqH1bQe`+HB&gfL56Zm@Jiv%#DIhG_@gX&cHd8?eFM18@=A5k||Y)8s< zBV9`>&mLez6r)5HJUndTD%bW4A_F)wojb;=}HmknF>_`2hz*xOkZ$$m~Rz=&~e3Jgb7bc~+c6K6>Y z`BbVO)SN1_=E{;kV&c5B+G-alCiR4b?_(9)&B7qRLQ`q7Iio_3sqL7x5;TqD3~%2E z`hdJHkRVE#cTQQEGdl3p^D+|KfUZjI-cWLLf+*aaywnm{-jvb=xcuD+hr)M5$~4BS zO1vi;&wZ8at~Fa*w0w?_y3B&Y4;0e86qZCEPC9Mhk5pX z8Eek;(q9EPvTOlQO;`+ionQ3MnbRhWgn;M2lTnQoF=+XDk_pl6d4_W+ASNR|_s3uM z*=9HF0`r`9)~l$gO1-+gl@>Szgzd>O)Yf%J2zQ+dM#L+qZJIet{H2cX-Cos$sQuhk z**BZCl7O4fG-V31x4VKmp8E4+6WqHq>0U|2bTvVG=5OiE`^NBP9x9_hJ*l=c zkj2k4*4OJ?-XTG{M*0j+O!1+G!+ZpBVB>o+ArT5_c*j8KOwhR=YbhZAv6u;-kTrkl z@klLuUEihXEXLNXH#d(CYDB1BO|JBWgU0Mc$z`gVNUxzGa;5U5jT;h+QBHHXn1^T< zMEHVK$%7-gK0zP;6^G=1b+W7K!bQks_2g=wCdTtaQdl<4t#+}BrSo_RSzp4ebPRh_ ziOCe!F{1IZ)tX$uL7^6w91oCf$Y=)NYOPy)cUclZE2wA*OLPq^@Ip?T#%zvlG*22< z8*ePKmNrl)!LU5V53h|;QEfT|Xpil_y|L&YrG(;+3qp1e{s>YeFCyk#z8uobHnguy zV)cjY16+w#G&`P zyEVnXV@yA08QwXC8+U*F2^& z{w?+zd_LG5e+g+GnfN)G0+Lh>89((Duzg6LW7(`udzQsS;8Y<{c zXJ1@f$kZ?6yI%&nq)BJ6|6>mgN(=N*_urHJ`(hN>AR)5V%DT7G2t#6rdKN5pup8@M zaBLfj!n{qxC+Iub3%%N<|9}B8mxw}Y9>ic~64VP})0a^8KkpSC0?_vBHub{!F%V5O zF@@xk7=g&mxbJ8Tqd%q7(dBf=M~$8IfOgWXa(if3}6_LQ>;j2EtJ|D{csKoi5^wsb;O}| zcAvbsZ~KN?mnXvh^cg7AYDE6Hy30a)Rzxum!LXntnCI1CqO8HlJ0f^G#{S;@`rE}7 zuI0e4xm$_X=KE_!56A}V`Fw*pH)Xl!tTj6_;3gQR{h5u!VkO$>jxQOh9P|Zo0?$tW%QQ2&_ z!fCl&^xsRS%q%V$RLuu>JD1hJjRXr}>M|lOc9B^$NIHqHXT;jTgo#FkK}$cUjzaxWBY29#1Z^G(@Pur8=k+rnFsTfeXRMUW2!RnvV{aR*75r7m5-cB&YKsVp4R#7iFCCa zr_Pp4W!~q1NpPkRa`)w4!S4~Xh9#7RIJ38Q5F7={Q3X~aGh#0=Wdm)Ve$dcc9$Ynn zX>s~uKoujr^1Wkqf|i);$|rifor#we)za5RZ?b2RDlJxj%6q=Ab{m#X`EDUqe`UCGB*U?92c0PT~z=hd9Otthxt#9tp zebapl8bp??*zg9+rs-4JT^l~Pq`qC=;6VFRxR{IAZ{)lmNP(s@24+TB#cF8GEc;i* ziq6>FcdNv1hZQrsn^5?@0Yj4U)TD7o-WB+jIt9!%7o$hFt!_Kqo4)75oi{7KF*%A* z@tHWOPU4kTe5%kQ%xlltT(F)<>rr2glMzFB1l_9OzK&GbakKp`STfGI6OH2Qnpxc2 z5hYM1-u905fw*pG+c)gIC?I(^cDR;6b`c3jbS!{?18H2|KD^!bMts8+UwMUR?!nAE zz7vh1frjIAb!L<)H5!3~V^UQOF;wR~fjz1U$52}hLd9+5OJx^<9%dKH_y zYN~EZu`=8Va;zP)v5~&F|KeaC!LrWd4`i2!(a!GBvDPf@yR*A>YF2sz+G+l$|S#?pS&eD{0v{V4j7dvuzc)PYWU{w=N0O(txbC9M-=1Ij`gjlP^lIr9gJcKWabWadGz)B$}pV+t_B8L z!-qwie0;pT0hBs*44mcHiiwFhYR`1_BWSkq^#+S69GV385zN0s=20;vcbHgK zp+7qH-0wQ`)EoKl0|^l?{FQ3?U~hO>Sb6^ph+MkCGO)i)KL^o9}wsERhK}-2U#xVe@gWUfz%xOx|DxC zebB3y|6kFv1+m?}+)wE064TI*j!0vake#F2_4MNflW$0}=LMS#(yc$8gLdv~9+$Xf zqg*6dxL&(+p#8LF_}XruoIBXJf!l1la$8z{{tT#cwoHZYhBP<39rsfeRE3z7gY`5U zxU);&?^}zg)6?6Nuaep3tJukDH43t@@?|QCa||Yn$%rP!_M%~s5l)=6fCt=a#OUqQ z;9KC;&MVM)n>mZa6Ebk6M&H0e;4ZAd@LIs@wWB9k6yFmK6!+yPQV!K(j1ZvI$&a3k z4dJJ9d|zkHdU{iQ+nxFJ1=iWtZ06!h42SU%PQ9H2N?0AD7y}ZAJ?qH*JgezJ( z!r8gXL(Gwg3RLQGevt&zAu`;yC!Czv-#uvc=YAf~T&>T1KtB8X#9PzUy=?ch{_1}o zay~!M8fI+60uD)yrp1&hgpn)!vNRKNv;<`Q=DZsZAf;9@96E(p>$2ei@k)!y>GrPE zjKb5Y6=6C#gICJs2s|}3&|*hOwC4+giBOniS1b;n1wy zvNBPI22Nl0h*j@%uC3T2H$HQ_KK~|=aNK(Kkvm05C~G)3*);m$hJoRLBV1;ye;oj8 z<;LpX;|YC(dGz_}1GznP)4l5Wko8Bt*eO{1HbboIITw6ZY#p5EGepJ`%b8GbRLwUjdk6Rb$KF>z z#r0(ICLuThg1bv_f({-axLXMB?(WV&aA$CL0>NE^Gq?tKcXxY3zPnqy?+`V{j-6 z7Zu3LNv4|}#K)IiOMAal0CWHi8#{(?X#dVN$gL0-75n&xX8+FasBA#AK>@c|6&l9( zcv?_M0%k+#y^vQ?e>e*9r}CQeZna1rb*TAqP^y!fjt&T)(|Q1MTDp0>nD#Sw$(2TC zc&I4nI{wAqWTiV#+u;#fkYDHb*v>b%W~LUj3hmYeBD{#+%XJG=i$z*DI7m^nHjkTf z&313K#Kdje;~C0eJ0o{@(Sy@&^g=^{{qA!I-CUi-88i*31l`27w5CM`JU$7)vYA)3 zZ=$vUQWx{_2Z8svL3%j7UU~>78y$Wj0|g_{up>IkUVgzN1VmE@_!jnShkfTRFYWCy znJ*i1MjOXg@5SllI)4UJp=aa6Q^D&!F#qOicu;Phdq2@9ti$+Yma~KKllHxt%v1<` z;lOxq;0ld&{5l4q#6y_QOMw#LCDo_&0cbBb%t3V7B`F$Q!kosA@iy4JN35MniY~3V zLIKDuO^bC)2KX=;ZfNvezS!a@vHWrh<#tr7(;uP1X=rY&{(L)a18#qQ*4f{$580E* z>q)4W)vRihW-d+&&k^_O9La29T54j17@cQ6AWok!-8ftcHXNe>$#Lw%DSK5)|ew6{Z42QuT@))#>XBVe0g}edWm;g@zDt-CqGa4 zc+t2uu3=3GT#;XwL@rG=#f+^E8>JvXSRTkp-+&;N}u#((BabZTn2D1q= zQA}Zm$H#32FlJ*XhF9ShMp%oqJy%_^RK{I12)n7}J7e4ISlO{-elBQ1mXvAh>cdnq zS;7a}w3$5hx#)zg=Bfr;C5}HJBP%zNKi^b8T5HwY$Unez(JM6rks1ht4|Y-j@Km-& z`Z`jV27G?}LS&ZM_msnLx^g?4R%`|9;UVHrC!zhZqdnne@8w*}QLw%6v-!N`-o0Di z@77W+OPPqX2a~3UiiQQl{N)gHYfRp21D(kWcu%N{Fqk8hiifv+aga&U>hb4;ywZ4r+ins{&dXB36%xY4#8pDS|?~nJjPSEOlYxCpO(O z_pcA+^QaiqF4K6k#RKf~~&w7#Vvbxpjba41;9 z7zxtz#M+InnLO)bhOm)hQsHhd?gKzn%4grkQQ!?eSZ83sgW*)|y{b)Kix>!%!a|47Fl#YPqi? zZCJKA9jx+|FQnkc$4GZA7yoiik;X+i_jGsPzTikA5Vp>pzvr5iPK@+OnYHmOGEoXA zO_~}TK~Me}?9;roMb`1{nC*NMcgJukS=8QIcI$L(kpk$dmc7y8p)QTfL471sfO-Rc z6%Ah;W~>)}7&_%&@$DRi70m?IqPEwMfs`~?rWFPl%losIuzJ$G|ZzCZ9P zSAP(^8?$kK$Mh8Q*mL7UlKHX@GJNUiGDR$ZLtoS`1sfBirj4nItI|NuaZff6JwtSp z=XFz7Z+JaIXf-(6dK*gcwF!L^)(DaoW^RhC63dE<)j^$1;Z#(lQ6!G%dVOPW0hk6o z5qM=yo0Gj1v|MeUY-YY(w+}KsFZd*QPTA_|Cu!7UT$)w>R>Me|XK-@Vt1>W9q>T_a zGgOWw7GRX)y^H6y+n3<7JBRm*nc2Mb#$Di~G>BtW#7m8T>`&TPPd4TgYGR;`BLlH1 zO>Hi*M@yInr>&1ARBqKs!VNwpj;nr5T%fZZ-Tl_hS4(atYE(S^$IhEpu~a!vp-eIt z5+K*`3ID*N#8z8JOTodw3c_baGbK%}!kCJ`W^BvYE+6d$_TV}dmCmO1xf%p&Rb$Pp znnb3BUt*Y{_(^o|)IXW6++*LL_Y?P*uH1o|>TNkr>ZV+kF-H7s1!g$_oqNSdGU(^N zV-g8qt9pCwgpflA(x22HRUZ7%LCBNNbXu)}(JA0RfvDMx3)uz-g@J=18z!F!q^C^L$&!E2Y zAc^W4V^Y!P-|ca>p|aBO?`LeZrqO)9FZ#LdY+Hq`2oI@7lNI?RgpR{-?tWGI9jZVV zQXjNe_H_6V0btgt@Vx&QAUE~latlf1ceeUjY^emj>);0k!EdA$3x@q+u5q zih>VVQj|4&q)VKM0ve;(tcr59X*AOGNf~*3S=QM^W}bmHoE}LIB67kD^*jt|58Nr) z44maUF)rSB4tHRm=XUUX`oe^{Qa0W_LVIrq?v0n2Dt47l1tCcfm}aisr(IfFdSI2gAVW3UC6*j$9#x!&i9V}X z0%qP8Z8*%>i9brb1 zz!VeZF`9I(4AOetg7JkpS=%1Gv@D2yg}VFQlh~l-75b=30DP3l?yo&gRm-8ApMc8BIu<1hCR7sMm&s!oR$apL9dl1f#CA$zf2{aw#&f(mxyv z^9x=pAq8UphOQ1voK-ssvDRixu$6|ct}cG}#fn!)I~#4|9q@Z4@x~?0VSXxu!#qs02x7#n{ov9D&BcxLj`MdAwJbO7@4lpSheL z1KS!b?9C+;MwF4yOdhyuY^VksOf3ki`J7tWCyo;byiBLB!hXEboMMGv^yK4oyRsX@ z5=-Am?Bg;Jm{}e@ZCk1Ev9*Ay=f>;w%G0w?V8iTteCM~&IaOkm#IEv9>9dRon~uF$ zoX$Q26I1qw!F|=j0!8IHo zcHmu~g}tW4fgk3q5=3LY4W^+wOeTMQ2RBiV=ZrHcbbI%Bp|X#$#nelAH1`t7zay48 z2qpn5J1-s<-wFqa#l2Q4(U+G(AVtSLQ&%lV2bN*wZ0z~=r4bYQTqU(Hm00aJZ{e5D*H+gISR78Hk5dPy8-VLYjGo*33qMM2 z^hzdTd+ed793SXXJnw|K*nftJtUtqq7*Hcmo%$L0$W7RMawn7b0$;CJF6;+}?lgm# z21lQ-U&z~U_vE&=uMXfQ5+`mOXpPm{V-zKj2>_phk%q< z3^bufvFo-Fl^IPaVM&i$jF;SUIx);@Z8MsVV%fSBQijX3Il#t0gw3?I+Q;_S(i&|m zEC4I*Q$-Q|I!8IO9`G^GFvD)G#-cHA}MscCo3g0F5J^@poIWFT1@= zY7Ih7n$C2EbhS;E@q<-WbyS{vbGy3@yf2+Qo3|lxyQ!10;H_wy`pvcc5c|7x=) z5^IOK-9^nH`72Z^LXMCO0p_WvFNnJjUuiu*JyhHzJa7Dl`u&Qg>|?X_Sjy1ZUkxZZ zFey|6TNBIWpC3RZgci-pF!lnNUkg%B_)M&Eg8cM;Y>YjHi$HJ`^!6{19COf`uw`g% z7Zs2Q(v;fOA{-2cGV*N4>L>TnIp4o{DdDd!qsV|^3%quJye*sA_Gd}fgJch-jc_n3 z&669?c26QnpFV%F3nJ8ujnjyD=kY_5^%@dkC2y?Pw0i&Ct z{I;nraeyhIjH$J7K@<=5g}+W+sNWh#j0Nc1ln-SsBKJNq)VU6KA;W4SzV;59>*5*q zd|u!wZn4Eq_<)U_kAXEl8JCN>TBp80E7sf7y?aDP_vY@&2-uI5=Glj%<=BHcLXJ>OiLj zp=FO2Hd}ESs07W5f)jWpyB%zBEqE+eTAHS3!$!UYl@6{Tjtmdqm*QxoO$(`7X=D=u z*D8k+2?WulK{*PQmh!dre#y+@%bUbghQYS9H7C_B8g!-@y!|3!SY2#7zvHeacTA(E zS(%YXgp&e`uyu}C@VPlZRJhAbcPO3G?SzDQ*gWYG;upbW)rT(O#6hmY`66i2B4EWH z-%D3pxJY8fCJh&D{9#SqgmU7Hc#rqS|3z?FV`of6>DfJAhnUn^;-BJ?ec ztO-7d=IA4<<+>RRm8(w{pevFY47MVmRHFw3k<4+t?<;Zq#(7LgH&L*TiEPKyAyCBO zp98|R8w}y?WJzLt1H@K!u^-hfFEUb#&B1pb%Rw;N3!DMpHr&Lr5%F~v{!fIJ%>__O+obg6O%JFEX(|; zGVm;)vPywcf08wTmv4h}sr{7z%>)eys-xvobSi2|sd3eXqx}N|p>^Qf+Xez|+p#j3 z%%o^Yxf(ATUD%^3!Yl#N@uvgGH4ARL% zN`Z_3MK2pJ)(c!G|DbXM8h6k96z@asv9z4h1BPy6@DQygaaZEdbUh-9 zngi!O^GY<@aGBC{%>?{4>1C84=>|c)oaCJ&=18`DD-iLC3ch`4vaKvjrga+grUS%< zF|#$LQFpYPLGEJ|ynb&;F<(y7gARr(T`zsUHsaI>@HF!hL zSn;mry^Xsln(ZbXCr_{q$DrI;ELr-UQSKK$VhBsXV6~#)Ie!W4usV(QyGP;a%%iS< z$}vNAz5JBgI@b#eL@2J%Xicm zeo{CYqUJ|mcX`4XyRA0?m;!B!_Z_uyYzjKoZ#$kss;x!LwCb0?=oRx`-Sb`}md`sM zZS14wCR|+mQFPu=Qhezd_!Clm;tam(u*!WaIG278Q{b}kJQX3@MI%!?f%In_b7+w$ zzyle*T(_XizarUF7UAyQME^d2&l~|}4I|@1_w+kANP|T73%AnrZqo4)?aKI5r|uBf zRg}W$F!F9BKJ*6NEPR3VDu{a}Uz1DFk z=cEJ6e%K$y2~YEftroQeA-9m?=hVrmiW0)wO=5S+lglUZiW*DmRI)|9}Q%Ivq zH)7kym?c?zTfL{`KEWadK%~+I5s$<}+ZXQ?qfgNgqn7W~Y`N|Ogt_~$|Jt;-W^F#$ z4&^r-xs8Qfs4N5+QO97#lBWz7iSfeyn{;}#-MB+2gQS+apOY0p!f5dyvNo82qW8@% zHcGl{v^%I4)p+5gdqfyP@M)lX%Sh~&v*fYsJ}uraHaH!P_~%3tNTVs=ZiEv?Qb41u zn`J!voe)lzJ3R@$_j|hxrMpY2AJ`q7m#PmCUgAb=0vM^-EGv_gR?%8Bb@%FpA$ahz zbLC?$*2uX2^waMF@qEo7ZQ4GOrsjVqXjo2vg7&!HueBPloWrFFXeu!1mgL}*KcHeG zdi?JECk(-)Ooz-n<3&GX_MXhditB~bdT^*7{-JX z*&omn9!E8_dHuLJ&mpOxP1VcqR9jlZdblAC%r?5!XWit0Ux6ZhnZkWH5p7?N^!F5aJepz59wSvp*7PHXm7=MX3R!SY+HIE`(2qfws>gUdkA8~ zku|xwJYP{@EuIj|m~o=HzlW1avXoSHDzrtmin%04?zOE%mFj- zCvtFOs}Val@J(i~XNND);yyu@rN*}ake%Jn?z92|effa!r0KCM!Q{4d8vk_ zyzjs*rZ+sKS@84bbLI3MJ{OXUWv6;Br8ybPXcdn`B+Bm$fH1SX#zhXqeR^R#=OU&) zJVO-LVX00+ws2CO^@745G~iIrLz_>&eE+5zUa|FC7sxvK!J8jSj-^*NM5!tBD-o%X zmsvsSq7U#wb~gjmSHR^mE6C*DJV{GN1$#+i33?bYE zA$+snE4BNqWtEBKnLdc*;Z{{3b~-Ta*wo`QX~E>RYgN|3Rc=$OWo^zmFUr}~)Aqg2 zs<|oFQJYa#5toHNb-_f#xip8S=Dj z`+8IM;LK}iHK_zk7dyn1jOpK@GDwS@Rn=7uAx696$J z?S4UaS0RdI_Cu@}LH#sy`W`O#i&%)$PW~B!rCanpX=Lapo#W`9=MA24MVYzb*YuGu-3%Q(HQ#IHS$R zgG5eoxQ*^v!k;n`z6Y>N2g9%XyRW>b4bfdVy&GbRtnrC`>E2F6--x(d$QEb2g}vtg zdF1t}S2O2TA_hliS#so8|NY@tYgmt0@}F6_Hv9k`8(ZT3`mbC1|GEYEEb`y~VgJw9 z{~EyG-$jB_J3aWdeK|1 z`u8>m7!?tdQ(s-*k>!~1`|df{RrLs+rKJU*|)nKk+!EJPtxPBd%`=P>|L zc*a&6@p~kDU#d#K;~t4T{m3iFG4reZ z&rhImdAlI72k?c^rlL>C&O&gGv@zNJ-v~N`L#0bmQs1=2`NmNnN41n*|B4z<+P_dS z_~j294NLV8-g?V7F#2wXx@nD>Zo3KS2^9RRxVSjOqF{gAzskN|uUNMu_r7Bq$hF5u zUggudPOn3U?aS0s;c5oTe6J9-_k` zugT~PYK09bdlgHwgR@K1f0+rA(>*#@WR7gUon`Cnz08h0LpduPe$@SX^B7y>mBT7k zJD|W&YCZnVq08S7kM;kuNF`6VMx&N(>9c*{1se~Rr>g4$1+VbpZfdKMjdT>b!Aw&bMM;^Hb?7Aldnq?-j~4K z@_}_|PTuw9-%Hh8^lx@0dh0mS3s!OW$6Rcf4$|17Pp)t%$lNXFeAH{29cf)*vu$q7 zcE5o)2sMWgosB!FQSdNhm6_f2C*Ce{V-)=j+g}{amaZO~{fo83#onY>+u0{%=r%^M zaii{RQM*)_++z2U1H=Q@q~1>&N;|v?yFg^KV_=DSSa3sLDn5Rf9k(T*4f~k-I5+a& zQ}pAHHbGcax$M<0pf*O-|02b)L0p-Ua#o&-SAv6}b$vj7gajw{J zLJ1l+8!9XC`AaCVxMu^%(fg9P#8F{nQU#!=N(tb?Y+Scs?~8ScJmgu2GhU=B}AV2<4V6#q!9%oY`oz@k31j}iE^M#Zk%$Z2O zL++;n6t+T$@QSAJR``=-DC?A)o`9Chc|wZ|>0Sun6?%Fd4Sr4BXcIBQr7XQEG5%&$ z{jhQH)}gEpgM|EaVCQR11-N_h#!^<7mZeSre#pMRj?2wQCtF!0O0;4Ww*RlN1QyUR7uB@_QFSC4hkYKkWVv ze=?#q+&VxIM(6#0?#%;7c>>4rOZxYQgkFB|K%1qkXecx;KBgaOV@s5OKev|rWM8gC zJ7Dy!+lgyVod-1OV@70EO5&pkNvD_Dj{pDVN)h@cO4Jn%GX=Cu^d@ekmWaF;oa1sO+8jc}y zW3z2;oHK*fErVTTTfmn$<8(3@NfjK>33Kz-ZIKm)R;!EIT|#@I*{yZygq`=3c6;Ry zYnq#~DiL{iSa`Y&I#fuM0qL~6SV~!B4bS5+oOll@nBeA~mwNGabLiinTjgC^;n;yt z-*WNe8j1yLiSo(BcadT&%4|D^EzzJ##c!gbUnNm#QyqTfE||ziClwH&sjzPD{NZ-V zPxXPzKx(eNB;VuzG}L;UHNlRQ3$pb(x^}9=pJCqkK(5EO2v6|QLurlZ)*u=_ygDwo z0{ad~+@}#f=&456yG;)>g4#yhYH+aJ`9B)XtWpAMytHJuB%raWkrMZpBO}?YDI;Aj z@MruvSw-*X4T`hufv8A1110{h{--L9z4t=u&FSTOI1AMaGxq21%O8YNByfLoEE9a0 z#^0c-ANfI|oRUcLaQc~#iY0bbT#zgr9AmhEs>0vwszKEX`}w~uEl(=LmYf__EkPr@ zIw-$%x+KKgPm1G6xD27RX?h8o^2`=LzjS`Ax?;o)@#VqzH39KCJY9MkZ+e#^z1Jqs zCiEtrgY+y%vkrdQ!VM17 zaYy^7#05i3ObgZF znh%OIb-1OOtWBl*r26cvTMdM{r3Hj;4O@o0yAIw=wNr;!tJgpSS^HGyKOYXj@lr`G z>XXyuYr>Z zgwfbat)X6XP09aV?(d5c+5DLE>;2#-`a7f>+sLo={1Yl8A%8*`JYM%fg6u{E-|{g0 zW26M>A&I#VEomL~japKX1JjfMQC}J&V0`8Y<4N$)hzn*Q;K#|x8_8*Z?u_ccSNt8h z`N72U zBkg3^VMzVvSL4mNU3_O5OPXS`HGxmqUF7qApb*fZfN+ieO3sQY&h4maDFVrWDY``l z+T%o{^s{$~u)F%l;Ohc>=YUwX`pGwXqYb*8L~m_78)&y<-aZX9CAN1%^|W82!0;3^uCQoF8VFR7n87ZJ-_r1|HRF3setZ8Msej6D!ZpoagZ~QyOQqVLn*cdNKYww^$VwUdL@^S`~92aTqzDF z2Al|Iu|IT9YHGjw)yc^t7K^^BS-Zw3)X6bZ#7rd|Qofqa9=^;Cju)>{#rIb z9QZ4y$v=KEpK<1a{v@7?<3AVHyOebRy#mP<3R~m8JCW3*uQVmXW`?aS#NUW{d%>Kp z+DuLvAmP+D8Bb0(yFoEU{hwX^H&VLu(-^&mppYi+5Cq?j9-n)0>2;;?3A) zzV0*5k7(lePMLyD$7^a738Z_eX0%#-hr_u`&V7xVSWfVA)aCKV)en!=8q9oFh@Otz zR$#;G*oX_+SbB?CZ%PEc`txQNO}DclSj15`jzOnXtyu4Q>Tpu=dh~|?^qI)ihxZG~ zj*vp37sC$Ni$MaMsa-$|pvKMR@bzc%8hz6?tdzDTYl-6M-G|GmX$RDqu@NF^b-S_} zic-lP$yUq;+l!<}b zyoirq5_%aaU<5g*nlMMKzi#@1v)@g!6N{!#54o-3Yoz~YN8v__9|Tg&{zSP%KE-qG z3-3x?M4pWn+Eya(Z%dgQSDw1B=zmChT;Ft05MQykf+gAGE!ocoZUCQx9Txz0U3u(3 zqQ9}o7`W&)pNIM7Em~*8Q|f9viu;fXQPj2jx!|E5V!R zYAQI>7EWp_-$A0eq(@lOfL1zhR({5aHfI#o%SO$(W7)Y$jf^jF*pK(Ylk%>+;yav4 zZ}+Hjs-=NKg1x=HhW7Ro%`6x%{S|Ik)VMt9XbGKV-v;ZYK$?t&M?{9Gr2I0m-@Z@C z*6X(G2x-&XeA1AQ$7>dDcNlm^od?XRnxe!~rDa~a$q_@!kd!OfNS0~Gxwl51<%F>0 zw%Bp$nse|TGiZE|#~M142)ZyUCd=W}x;Zcpk}YiJvg90QmIb0Zx_C2UJ=+oiu(mJU z(gMP1!wU5 zX?`=rh&wM<6gBSsN)-ku@Zl{+j^iX!ij8Y5Z(Z8&-=b69e7UuGktx?|raHjK-fh{>+xET%LjXh-p9(u0*ajNWF||+FT`NxPTTTtS2Wt zDymc-o*#~u95+}8iP>8`fH`7(TtOuZB$@x+&FdF4)3z|K@-igWeVBUK`V;33g5{)S ze$LULb3uhnS0e!~?l|+7{aoK}XIrO(pu~0RCidGk&BI zXvrsw6Yoi|1*2P8N95xJT`Ft>;<2<)YusM`gotmJat|6{4ZmDqb~I$7renkQHhFYoEPUG9I`WVdvvLYy7oU;jNQ0UQy7Bl-n@Cal=v#B97nC9;3n`@L26(tqM;=$ENq^*=tluryqo7u^GX5~EOL>D z0I+~2quxYMPjK1$!HUaaJG}1m0?13>-5t{SxN#J$+J3LXcXIi%8h~=?S>1{owDY(H z()q^a{n*eHr+Zvbl?)o`6;&BY=b;w31IyLWV_xcc#po^`bX`HSK2P)~)1zUIbg(lj zsve};QtYw8AE92^AD~o-5$%^QV?0WrG+SzAC_9+R_j<1STF4~6(`f|OZluMP zR$RDnnE0AhRF%!y7tIa(QFh7n+zV=mzO8WV7>Sw>mI?*q~xHYNYyNa@4{1=n$b#G_}4onFkigM)+fvp(X%U*1=A2|6$LGv^B{&)*VU z1_uYxL}dBc;b@T?=bfyrWj7v=UE1ST9=ADDdQ)xMXm&<3K?w<%K13%d86MWDzuA0V z9#$;el4lNnwU^(uy*xjZut9rB}S5s~=g;AhLL=C&MYs-RyBf z_Tnx4QhxF}?RWUwLlp8L;FaLg7Di^E1*c&3+zB=Mu@ zyv7ODiw6QfpKW_5~&)C$w-Ex7R^a_5AxU7NH6 zDK9Emx5)kjqpe(|MuDAA1w*lXL1)r}@>rg&pKQwTPS59`WOkhK5y}Wb4D3Q~YR_3i z$VPJ!E#YN)sm*+G9;1C(-sfL_n;AoT{E9~)df^u6T+;ZooAOzAo*^CD8~hpeK$4;MRoHwd+g+mBlf0!m_Ti`w8)T zbEVG*eV6WqzWl<}?yJ1i7L)alc<+FJIWIiBi4#L#H6K6>za7v~t6KF&qq>-lbRSE? zaFNA?9C9-FVdHbh3NeYbE0RGvk=)!)+ah}>(eO9)0xdy z{~hPn?lj8QZdtXxA(s7t0hi+jAD8PD-<;1HVKVNCVa z{Co&tN755v#g^Uw(F+?OV-VG4G&o8^kz}@7{%}E=M@|3a#{21+L@2H1vJ*4sUdfH9 zf*&3}8@6wm@0JB{jGi99iMZSuI=!Tbw#;PDPr$uL zgNoWZF)Th4=7$Kj!vb8V&xI)hsk{V33O>s{KnpG92aYKM^DtrT#5aohiK zktDfoqIq4BQc4g5v&oKlE6_)%YCp=B=4N<(a_sbzLm>kLqpO+2a9zMvu2(dYP$?iV zT9+z&!q(AIIg)^jOpfnLIf{VCS^6nVd^1jNAOxNI653lj z*fL*N`Bxb&;;c7${zopyUFLHDrJTSM(z%=Dg?`3QvC8k^T~u~EIXZN_0RJ3URgBVN zwqy2T!{iCH)w@kZy1R*Xr9xS=hl$O*MM#u+on5hVYyd3EK=mkp>G=@r=q@7J-MVOR zz7I+A_0wnx=$F|!DeP-p8K7%OQ!%@fiI; zW|?j)(bx#}Sc|oW^qwvUQFGTZMiVj`lZC2pi_{5T4@O?=zTqwBVk}pXmuNykLnaneAp zd0B}E#ew8H0qD2Q8K3tqZO-scw7a@2nq3Ngib3n0{eCWHD!i+70L1mAdcK!^n}qa6h{(^Ul!-$Sla$w#m6j&){#F&O z*`^vYd=}zQYps_2$y_RsMZ48qMMv>FBPc)Q91Fos#avEK4jjhRRD|) zFv#dBgfo7%4)hxHGM2red^5lS^RZmB2D1zUxmpd`Cmjn$Rkm$$xH@pdvXs%lr5t=q zZ3CX|vyr^oH>3Hv6cb`9e4hM~B4Exk5NymEs|nTlpiVfk>Z=Y4oytqG>KAqXN(=m~ zhMyceqQnI5AJj>hz;356+sTaEA`i|7!V|*kEt3~n%0lu?%sRUo(;Z*89Xa787j0AF zC6~RCzHtN`N0eX#SS8$*=7yNm?#3`}Z}=94_4d0$h&<%b)|FZaNp;uXj3GtwxbiA; zZm_;D?8!(8*MbEBny0O4($X`fqC#`3P24d@WHGxeiw!q8P@z>!k5>f9b z>0_ir z-x0MX=|5Ozqy1!S0%P^l*dJMoqw(5r#t(6j7dOJH)z6`(rHURA;^WkFX;<*C5nv&@ zL9!&0Q~^FpvIKl3$NUKZ6BBL-EWNw8b{^9@@3tky2Fj4iskeU-ea7S2s>A+^%e6iP z1035c`!63*DmC>Ix(vw{);MEYKJHw;b^WOpr|Bkht~w&I_p~zDy>~;Q-ogm{(-e-K zg5xM=tJE*WV=h%5xd8+Hkq(EUG|5t2*xWyrbf^j=f00JKk&Wi6tB~SiDopYA5tMgY z`)lBybyVCWkAh**<~I7sTRq$lN1_qdIN?A`fbZ7qJ;B)Na%h;KDfbE>@@&p8PFGH* zw>&^9ZAnt)TLmvF@FL2GzTV_SJYQXfQrZ_GU%!%qS~e}7$@}c$98%1_X#Gd2j+07O z(E6ucZXbK;2-YZ7OzU8}Ic8FW&fiDl&gQj7xtcL3{EuHobO68Tgo|e<$Z~wuzb1|H z9bk;CJYZmqSSrzC*(^0tLOjmOoY+u?a%HdQyB!q;31~fe$0bDN5L<+3Pvju|!sl?F}^d45hl zKDPV`>vJ^m{t2bJL&OhB>e|BaVkCm^YlfaQ(qN>g-!<1Qe`i9ZfKj}jP}i%yHc9h|o68?kCPa%!X*ODVQ z#x|n^)P-_`3nwkPRs)!$Kb1_G%J&71F-KO;>Cy=4qv+h~F_z}XW-vy&UbEY?g-;aL z1~}?~*vyzMI17$R!x#AGvf?~kNULfzy7uhaYM{l57DrhhlH8M4QdmZBvh?|?%}^Pd zwdFJ#jQkOs0muR1vOLYyLhRBPbrqzM^nxj#55-bSv}G;vscL4C(%{}r!4PCV(jyQ* zQ@+3*da?KOMQmn9{HHz^g*7C>w~gyz0qx8CdQ>(vOW@Lf1gXm!AC>p5e06EGc$bIL z_v}UVQQXv1aB=ba(c5|9MMJzw{CAeLqGW!$GO(Zd$!*CFi@~!_w%OGhdjzC>3k(L3J) zQ5S+2Q;Oyi?|{&E&FwEdZcm);3L_SW@$RCeKTjyks*B;{^Wo^T^v!0zf3)=t)P?)SaQ)_z%Sv3c%dsQ}NQIJDwX^NC z6Y;!n<(@5<9KokyXORrP`@zBH)oGF5Fik+$pFUmvFHI}=t2-!}aOak|${W$C9H zWic-aRgxIw8Z;Ci8N5bTW4V+T1a1 zet8yn4$gpG(hqPF@}UM}j{NdIP~n1a?n-E>x8!xM&90ie3p#^DUj^*0KtdZ_FX6~@ zh#vtz^_qT!SV)~mq-@U2P*m4IdObK1%;fu~iY3NH#dzUZNiE7iWq%B&!*dN-^F?Yd z$C4L(BP+=)zimrSPbQtMo^Xgj#Ud4^xc00}cMu!V&^ZtCCx*X__SUOd3J8FlYir~h z1Xttr9_QQ;yx4xRvWZ&tOQjON^+1PZhEYJ6)v8@uYM*-7^03@|{_JtWa}j{D2`MjB)znn5KyHhe z5XJxe9W%$K{VDQs4aFzAe%W2BT&KBw!PK^gR#nI%`BX05u6ZlIN-!JDZHIZXVAEc< zClCKHE=FAJw$=%)GD|fmrtHS|mCxnfLg0W=xukI$J>tUk)6I(N)~5ykfwPE+55xwn z^wfhrbz8J%8Q68B)R}4DxE!t_#hdMf2ev}3n{Bb33{qJ#AzcN(Ug+^?Hrk7fQmgu~ z%GE(Hu+z|!4|dj3wDkIurCHNM9emv#VL}vY2C|?9=@DmjCf_Maj9eF1j9@cqPbJJg z`jdAz>U7TKVfoSdT^V^0T_YxD{vQA*LD;_Mf_8>tnCCpOsh$6zP;o;Vrf@clM;bqvaXy;GeJlKwHy-|A@CP5cW?c#!YtmU= zltyJm8l9TRNM6Pd9g^aK!&2BcDWyV5MlkUh>0lz)>`0;6mMm^6ZGkYk96m5;^Bd0b zu~Et429vE$XyfWnVn(ez*?d`97cF0fO9XDrODC7lfK zrFg)M1#bAHxJ+H5nkKAi=xrFrM^iI&z{(eaIpwWeZR^sGpElz0GUTTw z-5^P~q}(?wr&kVg3kxa$Lz~j1s6s12s9RDPj)X4)D9L#Ar-HB9jCAGg#`=boD`iyx zvQ3bL+p`(%N9bRv)btmuY+EW*Yqh#65vjP(<+8d$I=nzFi)TIN9m+v7tj?t{AJ#3n zk!1N8_d!C%ChN^IP#I1Mdmo3qL%9YK%FF$)S)WR^qN`r(ICu4W!}l*IZ0A)x-!e=C zdC)K9!?G}6rol2Kg=I*eyP$k#eD~$e;I^Vdl)^MZc*4A>=w=_ILOX1iLU|A{SysWV z26laeUsQy0@tK}qTJShY=*z5gn@Vfgd&OPr+X|X2Eo{d4m}AAZRrl8y0|SAG}}XnGl#-rnTFjtYihJUGH2>4nd>I>71V(mO&jn7I|AhK$t8 zlCP|bG%M21Mv@&Xi14RAGY3S*CUC>ZO9Al<5z=a6BGTljjtNR9!h98z7v5O(CR317 zp@4_c=ecm8irwX3FCr|55{id?mh{@ zy{ShhOu=(V_|i5=xX1ElhQ}USobZ=F6g<3i@WjK1sgAy=H=#(*;QpEQLWQ#0ojc!( zfJar>`7>TBAvy_@(k&;&FpRy1A8TSsGH6iXsF5@SN%yoLQuB%-iYjH`MkQG?_mHD1 zRp3WOuO7ivaXu(hl?4hmGB;7*Ydh6Fs$0wy|dhKppRhX)q^JCevs^Fy3(kl(As7D$+ zmCPcU9@7tHp-FM!oqJH6ewwh%TydRlkI<%s{-K=P!7%(4FO`}Zw2QVEs?2l9wn6~4 zQ`i!&d8w%E=Fc=J;XL(|(2gN&QnrF|0}LCk(WFq}O_O1Vt@lo0imbCs+x5L%B0u$q zq_@*hzaZLfP8i;~1he;e_u2nC=?oDM=8gXd->mECo zuDf?-TFEq$Y42frdxv2dj~*Dz_;S8HgeD)9onjY)e=3W!?MMpkrW862$sgbBBj4sRa=#ngrF3RHAqAZLo$Xsb& z?iML?atGq<3v#zaza^P3EhF5DERC(o%GjE$LDt9CAsezWQkF`oD%Db58l{FrCEQO7 z5ZuT+xJS2fK~Pw}a4p>LwI8Y;uDAP5&oGSL<$+(1VGu~5U#DTN9u#9~+$hAdCH}l3 zX}4ffe8iwWR85G}U%5Pn&MQ@g2i~4ZkeS5xFe(7I%Q1V`?e2@1z|lx z8AzyC(hP+2!|>bH>we&hU*^m0C$vs5xmPvYn(kpmaA^0fL>0O)xxE705LURkv|T#x z<&JD8`qQ1qjK_1xG?*vPLnu#D=*}<<8=%|0z;w8BKCI$q`k@^{n*?S1?t<$a{YoX( zmxqCISY8V4-D8@R?)AQ{aBS!&NJqOYx+%LV&3>@#`sD(;D#O#h8}z+~Jh9*IWc5gs z`w#!?fBH|}ZWs>*91OO+f{h;7R8%ta<$Ss_OI-xNV{H_cC)T;sHSvUNQW<^C>B&Y7~v!2Q;8Z<&$RK7 zEK(bvl)|a!C42l?DNRqo4L4-|EX#i@8ct_?TKk^gzK({mV+P&ZlRZrBg90Y`l)L4y z<iE&UT*nvZgc(4XNd-QpuNP zJ-aTenN?YmMg3dye+wNPbzp-mwsG8ERGDur%3QP{cbk-Xxm%x;c^ogdR%8u-8R{tl41LZKsf4k-5FHOZj{TixVWhK96EGJU#55X@L_!s z9bc};m%33&IIQ9^so)E3K$FU{CDggmXv)OogzP`CUk)8SBqvXtl$Tz5NuGY@SyjYx zpJr}7v2S9Z96WeXjvYHD2M-*SmtTHao_XdODHhSG(v{}1cVqtCvVz+-aGMC$h4rGz z7a)HA^PktcO-xK^{fR#FZF^#O4$DHNE8Calp`tak?}-y9U~09dhtcAHx=D1 z54X9XQkrcX9TzM@kiR0 zAxOBsxUCHP!Amc{Bu|`tLMCBP!tgR?E_&)S41iBcz*?Hf}KO@iA%P2HZgg)kf~hvQs@*U zkFYs}buTmI!=78oqggvcQMYa2bwqW5ekl#%7u385Gp=1@I{*!4PffF0ug{xVqtj+PAGzr2{uj@9%b#(9-ohxgr`qDru23h7Pid0!gMKhIxb!qoOfDMe}W(%elMrZg1gwgJ()cMn>hx;iGc&*iqeAm*u!|3JqfQmEk6|^&7u*a7avQBQFX!OmoF;zGoJ$h8_RF2Y}VZ!-J zp11pj=~DqZKR>T8DrC8+IA$JHKC_Lf1Z7#mO5`LgTTnQ259|5)IsGE0jQ-5~H`}yW zENDMr`|R5{uGb3{mCPrf!!s@V4PT^r^vDtYf`)q;-@18I+lLC_By5-GpMO4HeN9;Y zovdTTKro+0kPw`6t=ErtOwtqiZSNf;Aud-g=(3f5Q zeh+g00zkG$zsrgt&tJSE|AeuE^ScV;FwfH1A^INT@m4tZ_5tG&K~I~VyY2B;Zd&2Y6<5A7k>co6umHjvQmdirD{Qm}F|LLE;yrWwL9&Y9jDQcbh>>KRi^>g}II?$er#jq0oIRkEe!a;2{l$B+e^5c( z)>Xu~r)8)#Zb+1=OC)t^NE3gN)H)5Rv@5a^m8IOONVQ$VaaC$C>uncKS0HoX&}`g; zyXK*P4(6+Q`(Qj!B`^L8nVj4E5OMQD<#S0!a-*tj9?gzPsZ*4F*>TyI8<&yHh>T=Q zxVIOj)XGayC5QZxYP>p63!)36Sr!&e>kC&^CPS!Xb_D_OprTm?9&wo9Z)^|Sm3#(L3tZetKxYL z;hCtUL~~TQKb)EK4w%Zzu=rMmLt3O5)%j;=9%5Xg`!IylgP?_2RiB3^P4Ft=Gib z+PW+*E@(PbO7dK?$;QUUWnyBVDyX%68m@gpn-M)9Xd{-1Zp@!y>6V6m;l+bYhlKW{ zLYZY^7%eZ-VEMV#hwJffdkX%sE=}}5_6>dh)|A-a^D=^d%sOcKD1BHjm%YOIzsLt4 ze26wG>#qr%!r8@P+r0WMr*QuIH@+eHK51=~E3&w-pkEGDYt^_;U3{EQ|8i`G;VAxG za!i8BmC0<+lTVzK{WCLqt)`2^80Rlu)-R|2OH$zsceW{E-{ETUzxu1cl5c(Mn{xd4 zQFRZ5++EU4F|=%A9M*Rg9A;Sc%(XDJpV!W&A7#dnA~tOipexJI|!hY zP9IG1X=qnZr5A&AL()Bj%fx?Z{y~yfe0ZnWjA1;VclwU5@zW7fVFH`d4Wz>l2pHP3 zpSQa8DI1~l(DP1DNNT6?jE94Cm)Z`VW)*aBt}Dh>3A2OqkCfDdFZQ7iTygW`FLAVA z5AS;5m(j0YqrZ+PKiH0kM(;bL~MEP@|Icey$4_ zwWF(YInSD&n%3<-{-=NWFXiCD13Kplu)aaz>{dAc#;L z=amXPgFls?R5Y)xuF19Q*R;*4=%-?hZNpW(T**r18n+Q)nYl`rN;eA2GO=$$x4W2` znd-^7-ACu=?n&K(gnJZ8Do;Zn>+Ng3gs_41@%<3;?UyDMwS@JjKerI!3TO)3FVv%f zKJ&yAr*u{J_`ZE|{n~YHzm4*S@5fwu+(8>p$qO&Mpo(d(>b`pQN}O-lUc#;HJ|a_7 zllld+mTrqOZU_4mS4nd@9a z@SL2Skf)x)bNYb;xHkNH}eqK(WJ}tlh{qOZWgfDV>>DNw4w@}I8Ml-l|PzUz~ez8=PfAepCATPi4 zlFaNsfb-#lco^gS#Y^%}{}fg@!^JD;^+lWb=ecGZ|L})DRE6`26GvQRPqG9qMGESw z!juR;;Y@||&DA#MmsuS<-RKD~m(`x-@!rE3=lCA3d&77%@O_(x3I{V-`0%JJGwBF3 z3rnF1O9O)+Zoc`&J2JjHFZo8~l+L&b7b6UtO$f{u2H-kI#t89Rc#v&E8aQs!4M|2) zfW08)R$eypqf#F~AdRCZWb_MPkm$*ik{QL6m^Y_TzyJ>EqJwYBYb$mT)Y!v>ev&px zKRZp%lX#B^qDm#&ITzzK1mPT=mxo>taA?DHlMLtA!ga?>r-1{$FH=n%2hmH*hf!e| zTu7992=C)?Z*->Tt}|zcb5~dUx1;2iTb2jSx#u0%EY2t*~cPVCVcRCxX75faa5Q6Z9Awk8{y zby;pL$zrr13$5ESAI-{K>y|7;i?Y;OmQ~$lc?03fQpr@MnrTQq*OX>9l87s#bscmI z_g8ML(T3SaG(@k2Kiaupb2HP#t(a0*sZ%nrLul68btyM1D(ekOS>LHJQpmG9PJy09 zPMt{W%!fetQ&*>O=D0xE#<4OP;tjXj+6%*kvBWTp&k%nN@|q+Z*El~Z;9BSY&7+WF zPKPwm4b_GA-edP=7eZrB-`&G`U7AhIEQuCcWQD{$GIe7wWr&| z`I;;tj-xjm_xR=Bwp;Dt%wx982k(C%umAeja_QnFxp?uSnp8+~?_RFzTtQu5`{ir$ z?mO?w=`*M0;)RQH;o=2V6poZeOQ%<(+rlk@w$! zUq1Qd6D<$(p%R>Bp(2us!8hN0Q$GIqW4UzclAJ$(UKNd0CUQ^b$%(1Bo?I)j33QND zvnrvjlWp$qGhO##WH;F=O)3z1UbXE3`vte2_|>m|rESA@Vf$Q!P@z9DIi)LCf?xpVB zFPRG7-~8q`DA$KtW^T>G@-RK-LkaXdotzCZ&f9Olqjf)v{=t?1dVS#9nw*-FiHS)q zd$Rv0Y2d+x*CN}^?cwak3eGX~93V^yeckQh{H!Y8lY2PR#^)AZ!xwRFy!YPwT89Os zxr}jQXR^Gd$uW&zI`IpK=bwKL*Xd!sET@6;wm8G1oNhKFaHP?|1JgF{Y_Ogh4Rz^xvJvbvHPdy>U12a-Axwjy9Z$P1- z4lP?x`3&R!(FZFC&CtbEa7@Jt?Y!9qH=2a~kwQf-R|1CX2$uz}38xUQVZK#`RGK0i za9pX0%$G&(tc%=++zPVBZ?#2ktcYA+?#MODQb(@hIq2%5lPe1ym2i9wavlDZ8<3k` zW|xsZigDfEZCFHpRS*>C+1K~?4Se`PZg7UGPb<9G8;yNg=RZtgBP=f-S4_K6b z3~=r?8bWk3{G~$>r-W-~TY5~zTL%xxLHOd*Sa33eXuCtgInb05CMm8og9OB7G9D-N z45#{rqNkmXc=&1OCEG4Yu2qEKzSAm5rVa)mBtl0*SI8S zy>Q13@mWpb+b7gOYzP`M)r2T;L z`Q-wYs249@Qe`K%VBv~qN3uul9In{s7dOfBQuvDkZc9NWcwkUY+?SlIqq*gc_Fvy` zSYCcn6jn~}^t|)bhSTew8@8@1!&0Hmy!5(3dvm4v@Up&*>12I(s%XK=$X9wicEB(1uN30JZzoFVZ;q%&}wkw%dU=TYe#J|uGJgtR74NG(4p z)pkyrc=+Wu8Wk#+vsFCwVlva_12A8r1h+ij*k6}wtZ>fAG6w3^d|oP36Vf?(Or~Fa zUP=e{>%MFHqCn)Uf&%t?m`xoT#yu1Id2gR{s~+7C>>-#GI=lNWI>h0(&n>t`@Nae^ zX>?kuwB=idYk1C~Qg@Bpn?qJ1OB*6{Yfd3dB{3Do*I=q0ZYoP{xw;t1)rCl|EHvfv zd_ykHQR*re?>h7Hd{eGa=A2xeL-@It%C);KxjxsH8+RcvZ_Ojm1(Dmx=MLm9@|jx^ zS)ei+{?IQd`?`u>#PUjJ+No%E z%I2V0hGgAwkHm^-uXIib({_q4+C!J+{aDn!LUVITPw~)x< zhL^+5FOQoaUvAsMF@G&kZdGM5T9n((S-BBilPl3BxeU1$U6GqOo^9NgyNxATY*u77 zs!N&oI&PzZ2XsEHa<9$|28RspjcTf(zu~y!g-T?G>nfD_>!2W=gmm4VLK;0b#7ABl z7x&w!!@Z;%QpY{FlHHJ%&XO#&@5{ctrc18aEp+Z zG;sYj_~OF?9=ftkOza~mv|CcZxK>1-1(buzW`6k=E)l)9oi%RmEt=gh3*a)B8<_^NELt8 zYDJZI8g6Y}%9XOdOp)cjUzh^R#5|b?74cMlmQfCtCnz4d?MP69Gk=zo{y`b1`xi&J zzi{g0(^NAl{CEuDA}7~Z9D1(2unnDZa$Vc81vl>D%`bU*%r7_?hDuAGSH4V;@j{=h zqa7KaepK``T<8-zSJ=g_$$riP^>InGVxPx7F~3 zID^YUA3k3&d2UhR_RG$z0~Pbz3OZ|7aNX04-TiT}!<~flzkIDMM6S6$MUp7W2rIH_!awabo z4Ay+dZVj>Oh*P5=ff}AtYnVt?s9?^QWF4|v7?Il4jAT!okdfz~k*VjNmF(m`y|EA- zw{`6H1xbhv>BgslPS7AUU3YZqW?myyyfz^Xc+}xgYoqVCvQmMRBasbwt~aRQZOgSg z5u_tmAvfkkW|!QmUf!o=xRq+shqBNWSuLaqnwnPR*U9l`$m-2aBC>QD&nlv zI!L1}3&?x{na{!V?n+&5FISOYMQ$u?$hEs0a(Q-LF5Oy}i#ONh!i{w~e;wxa4Y_!u z4EL&BzEzVevo*PTyDr!7)=}QN%q}9$b><~f!5poQ`p1Gcpfq3)!qwd>Y$KSMdP{`s zx`pu}!jz$v$wBhcmVy(t=g_t}Z@LW+dIa&^IY2f`=78?DK(ziV8gr z4>10?zxeo?2Gc{bbb}vPM^ovnzZA$r3OFuNno`SGWhJvJciRhcy)i2nH!jO3OK0Vi z#j|p)asxG8mU00P%7unB@_5LGv~o`I+{rZ2etOkH_{E!RPZ+L=edDU#FpP&1Ubpv5 z95-C--rNB?mr{5i@5JLB$1mFT7aQRh9``8vg{UkleG2O0TM-_|i zC3E}&(B-Z9!;gFEGJH@fb1!9GRh!RAX{4kt>fZIz>yswyLSY(>hEqK61gFgP2Y}JzB+^MS?_fp#jRwk%Hgm2?;kA+!xS_6^ zQBu@BDLxF`-T33$jOUZrqfco7PBG2;vuvz{wuKjUr)bDt*+kFt2r5pt534BvFkH%0TCe@KT?%u5?)8MmK)2FT%K#l*_%x{eXRxQ$e9}* z9E+U4Eplm&TYb3I+PbaBipcD$Ag&+{kp(K%(MGFv>2BeHXP7F4+julEMl@Sli6E_n zNolt^S%wLr;#sF0m@sk@?Iw?5njWrp9@9h^PUyIG0#~x?tJR!a2j?u}#2V*?t3~xh z_Xy*q-Mko&1lkjDz9>9zG}WrtnA<{v+eg%kPHH3Qm*X{=%g@P;+*P?DSLIgwhTLw= z%0g>FR$HsG(W*!#s!6TYlsc~CCLZ3JR5s&!<}V!3oABo|q~He1UrFd8KGX`)d#ewX zB)AP0d?EpTfTfkDw{wrwHpWMNH@Q_H6K;( zB4mLRif(WuaTdU%TLdc0W5(s6^H>jgD$we1RhOWIlB8kW5WYsq&Lb zJe~)JVY#$SCm32 zONG2gA9;Za&bg|!^&7|xNq25EQBdcdGPXwEJ;#Fs!)bu$#w&Zc%ETtW+@p zALQk2zBQ8x195=|YF(I=jj>6bn)(_ef=N-sRe*Vd|%tdrs7W{Zn%o9l5KZ^P&h zI}RlDA2s!X2$K=q1UMz*M4$T_b6@6iGi;a9k(EkQRx6RLR$Kbz%6hFM8+G(~DpcE9 z!PFm;5gh6lH(Xgsr4zTYQRR~g@`1maUi9We1++K&36;|wDyMtQtP1yDZ{vZY!?(6W zT9i!QtuFQ^g)i}pIyq_Lx@}O}IjOhvket+7IjL~9H7@>juD*t>p^j@+FQ}`wLoMU> zg$@EYnqhkmZq30hIx0A(UAO9h)F};&EodCRTZCo{jm$*{Z8Q$&ZJZCghfz+dVe*{t z%OaD4@p#DcSDA-ntaFu@H9A2<555r&NLI}%w21Epv|>a z8QaK4QWb8AQIo~YlH6=_ujcDA*SaGMtvTGYmZjX;kQ)B@%0E>sqaQl;E4qd9apDng>pJ4Ke5Vnh0VT#%F`S{=)bYzM?JQ`X9*;`_e#f zCI>0N`*6=o10&96y72x$YFh1AYY2c7l|D`dQ_Fb+(Ls&z{7_R%dum}G+apk ziBnH#Ig|POT$FBGdOw6^wbEf4m`t%OT#Y(Dz7OR&A}3J}zWnf+XP=Q%Pn=SvGPm@g z!jekG6DLpT`J?&lGtbJYCr_z+0ncSR6(*W#A4$M=2BL2|0oO_Qa`EdOmqP zHadp$z%4Bz**~*iuZ!b2=f`2b_~MIl3h7NxPoW9>*C&*Tdt<{dNci#Cr@f0J$m$*)`?|4eE5(Q zi*Dt2ztg~Ly7#4l?i%l&GmJ+gBiaX_dHNacm!V9YHwD(wH*em&p<~7B+8WZ~tc&5& z(rpt*a3_OI;_Nv*E3rIZ{_>YmmXrDgLZTQkd}-p9E0^^Job2O-@0!w60LkL{Y9IOp zUsB5RIyJFRa|p7Tt}9N35?r_?V|ZzxJH`D|*lT27yY74Z;|R`izYEGR9tT3#4i~U{ zXr<{MCh=_QUYG`9yD<;=M^5VA7&F*#FIMI@)#a8hPIty>?XMA*sXLl zfF%oC4&%dEz9rKmIhh&D$-W}y@ATKN%ZR&DU4IN$tv7uir60EeICJ)_{OCtNlG)p{ zy6}Nld*I$2K zU-;(eEdv$7-}#g8$alZ@T~!+9^O)ZuK8I6+#~q!IP_Z~SHz$h=i@HsMzTg!mm8Pdo zozhjURKD>geQZD7ADLfZ!ld$-O6n6QkGt`709^DCU^t!A0A2MAVS6)rghr==?B>l| z!WYxA?YRQB-^ruJYA%Inf#tD)E^g?>|&# z)1(A9y)PvQN>sKD{doSgZy^}Bg$SYfD;_Nj(@LdrzfifFEF0T{`z-S%eB8S^C}8>C#zsZXojWH#`N>b@gAYE? zdNXCF;Z9*&`{1`<{kHu1pZ&Rf;~QV^_AmN-bN2Ra`NJRnfU)B5XHBGchi;ePdF=O>GS`u-5c`X&yKr zwWK$w-WFI-(K#MZ|H^>fv7f&=`=0(_PAI4HK% zWZG({x{BAo3#(=bt8N?@U{O2QPBDL)oUl?*FWvgWnN+^>+xeiZ=RVh58Llr>M59(Q zp{g`HD&>Y3uAt_MX|9~EbYvCny;{wvaP_nbS5td)19NU}&B2xA+&5cI2-9vLFA7(r zb1ec*uCw6y!nQ(@F|eU7Ftz?^!3Ryk;0o)`gQNr_1l|rGXFG5@c0_8(e5lxARfcDX zIx`3t>hd0@3TM6;FW;1Mwj#^z72Pi5Zu742<$#p=_PnfiR;AHysIovGetk+bdH%U_ z*k3LB#~P}_*#&dJ4EItOC)Ex$-pG)@5y6ZLmN@d3%f z4R>#ZVmMsGh!$m9Qp?n(lH*H%8>oK^?FByw6+w6|L&%)|>4k%s3JmRg{*b6OS?q+L zVHghxf1QO(k0Tbp^xF9fX99cTkct_%!ubtZ-`Lpk3TL(BfQqm?ckalA3l~(`>6DBv zKBcz|JB2y9+?W)Ve_WmERya>-{z+ITDn~C}y4176Ib8-SU&9JyDqw?xRQ2P4!z%OR z_5@Tw?Hk{x%DIVsUSOY`m{bL&#zk1xl`AQ^@_KY^RQ)IM%rt^$p?8%3qeQt@DL{Wvz?0Bfnfk9?Xlv70%r1gMKu}$H#Sh4=R|ctfX?3ZdAJMo7ji) zjH%Le40Ux|M^IVV+a^hPk7VBAWpz|^Mkp7RwmjdgC!s%;xD1n&pkNN^s30B{sEorj zBHWL(K4@RpPkI?#y6s`UMBC1%&GX3f#j>+q4&a%VtDFx)xK)MQR)hN*=iQbhXg`Xc zOK!a}Jp*%GxE%@0Jc6{iEyd*Igr>(WICw5bxpfKZ72!IdV!Mj^#%%y$TLy(P+kx#t zVcRCdB>NUu+Lmxmx!RU}m;I0R;Q7wx@`#IPm-RJSSy|P7#4mlgdYJi8@yq_eI&vlR z;loGd$dSXk8lNk%nNHYBW>A~&Xod4L&*(1z;{F9gZTN62oNww_!IvMp70yW*(#Pu| z?e5O6gYG;IZkP|{+}1O?!ujM$ZLfYTFLQ`2g!4o%vwg!r)J{(8@qCLB-$~!ctMj zy__S=L-L(Sa!pJOmKUXV^_nc7IU`e;#1;AT-FjJW%-)nr)R6UN4G;HuDI9r1PQ3hO zdFrXp$-(`{WMpigKD=`USz)w@!PO~;k^>4KlwBFUI}Vcmq$j*L4Wlo7q`ct-`3OH|W?$xBBsAMZxguGbq} zs10(V)o(Kh9G4Ox81J|`H9_7zvAm!6^|8F2?ulgF>SZtP--mNCH7Fci6dW^v+ML99 z{oo$vUBJZwv89VEG3v|&XjM@ax!!BNsthekMHkcc<)(tng`Eby2_b5@laR{ zE@Yyp9Ut_kFf64&;p%DnK{Q>2rO7z199@&{#5YY3>V!Ik_Su$H{6Qq!dpknbTE0Q$ z7&6~3$%J+sIcCdd=}C5*g7+;B9dVG3N`LRhFG+d-;uoj20v>3KxL*}&vd~_V+x5G$ z(piz^=Ax{$mSwHACglzu__7VjweWBY$>BP8*D3FPxL0w7G(;a#nFqbl@C>J`hF!Lb z_T*4Jgjds(KEHYx!p4N7l&eNg`0-ft#-BRVu~8Bep)I%*~!wQ9aDfG?6W z4Q+^c{4|W+!e3*YQP2{vaL%=4dUPi%oC7XFdT|x*nX_l)M?deA<-nywuz#x2q+vh+3dEKgl3PP^>oV_)xRV@`uQg1k= z>~qgPCojG7vJ^N$Nujeuv?1G(zXrQ=XHFGy^Ye3hE(n#E`}ZHf^VL%_Gc&ELT`ycX zud8&UW~2(s$$b-A4l4S%-NTI=H{{y&YZ}HWm-)iEf*d=3RGxkISyfn4kv0g{k4j{2 zOLFVhEltO*igjN=PyzR?Z+%Pirn2th#fy4=lDzQ33#xRa!t)%?0k>Kymz^@5Pt+%}Henz3Pob_fKQh6KBH|xwVI`{Z~XmDWUzOz(1^T9Na8%PO*EPn!@#Yos}*5%-_BeMVa z5gFY-EoH6*n;4h&zH!M+Ov}WP6LRdS=jHIx6Ed=IQnE#^0PRSFZ}GwnNB5ug#Rw&f z4?SJ~F2Sjfmtn+8mra5Xn*3nDVxOj6SCXJhuH&Y^(hylxg>zF@s|_hPxRWa;0e%%T zx6sh-GuU?#U#}6S#Xs7SWZ0sH1qsTc3{1K@apmAu*Z(j01J*_Bs|>89h;rh9zs z;YQYzI2Pj({T&Ya{{X#C+LYkfI(h#?@IqrJ!K1YBc%kPV>>^Hrl53fNqo3C zo*u!(y#?v9ABBDyyx7Gke1@S(4=Rewg^H}^H)JuhDtDrJxmCX-OKmEeSEbTgNB^qf zJmaAdXD$>~@m~t{T)Xu51$N3^*FvG4^b;THcI!zO^!mDMHx_(^YdDF!` zXEI#q8*v|jCFB&R?t^O?(24m#%NG!KC=3NZuAIwe@vu)V5-xOpIpqJl_yae-sZB5Y z&|V=d&A1AC5IwghCc7v-&<)oufBNoLIA?T)a|!okr>^6b&qz+X^MhnUnh3xMfP3-c z!h*c{<{PSDx^o5Tqqi8z0S6F_E z%Xh04&a_c^O9k-7ifD^&48o zY%VKD4j<7k^QnAf8XtZ55z28{E?;rw<%-$EhYzY^kSk^fK?UpD+M2xk?z{5VTW@K- zf?|1gc2>_f_q1i7;TH_Q{N*pTtPB&%%&jG6&^ByHDj45=_Z|7@qmMO>t5>gST$bn9 z(PL`z1&r?g=14V_($8(DP#H;K-(=f6(W^m~|5Vt1i2Ac6FNz{v z9ZZGf$De#Gul@2h{epmXVwhXAw`AY=xUL*#iXVUck#6hq$;Y2)+XSJ~o(g5Q^E>an zqrWgXd-kmM*(+DB>Pq5bX+(~nIDzt1({U8>T32GUbox^gyGzn;Lte$(0e{;VLagPym**A7lf;?xzz~kbocHZ zx5Al0*?#b6+Eloo(!Hgh(S5JuYtv<;=K6YBw}iQHzW)kmrsj&sk5GnS4grIrEW@sF z<`y-VajkxgYo>|kK-Q;sg|pjs0@Ft(h6APfkh`la|c%wBU{= z1^!HHbVOR1!(cp>7AC?O%z~S^eQ~=0eW*`dcbZoqX-~0*mtiQe(!+N#3al#Bicncf zp#pKEDl)$&a&xsMv*o5N)>~3RXKdw1B+?h{QBmrZr79f=S3qJS20N9`x?)fjW4K5% z5ll>&)J}y~8-i(umWL*;1GUpk3f;Qm9?MkCrsihh<`!){48e{vsNzQzW>kM70ftd` zeDJ|32#%4R6NZ9Gg|Mp!V)Oc^8SH*62ttJ{B`9ZAkgZBMM!G>F#z(#_Ow!sEt{TGR zx>Z2i=CjhoxX@ISl9L9^2EtKlnB>(^whE*QDWf&YDBMPr(Ju*Bk=c?89s=uanTOoP z4DR+uQ*Nx)<=S#pF3p$a!rX?OyS*W2Z*Iuxn`Qar#)f=yy)0*LROH;vhFrYemaFsV z1Ir?J)7g%0tUC!x>ad*$mDM!46$^z*Yi=dN{lD2BTp1q})m*%Qe;rFH zXv!FM$N6)L)o_dt3feCy@w?~EhYIdAgI`h*#0g?RxLV7_-3r&YXi{8SG#QhR9^OuO z{iB-`)N%{)>8Uv!E>HZ$N@te}>&oXAR=a?YQeN=z#Df<4P(?Pf>vA_*kPBfVrU3cfVIi4diKDZ=!)buIB|Gd=V%2YoxM;ds1=_Q75P~YRNB{+qsss zN|CHlF<+mPYa2J^M)|hPH<#g7k$OJDb&Eu(hw#~IfAV?7zuI71@DNs}O9^(myTE%8 zZ4?ue-IXxzsGWuznACJDh@HDbLnH*B8ZMZ@-gS3DgI`)g*lu`AARPvu-p#r5_)|s8 z;ct*Z^gh@Rl#%}0hOWGf!7-1})Ugy}>dNYhD)BB{yr2q3DxA43!0OtnDqs1MKCXhM z@|ViTGiT0d7*!U-j|xhrJqY?y*|my%Zr`3oURQKGkjs}Z=}-M>Ut3#Or5{ahX+Whd z72wydA>W%fWPWa5$`t^9L4m%^nou8>i*cx!q_R0EM5(OimIkbs!;k4H*o0is%r6h9 zAZ6Usr%$UQoAnP{DzNTUc2n_91vyPsg6rzw6=^gZdLN>)o61ruX#J)xzN7tueIY5gZ{OCH)I1Md`OP+AyXra9@K-cU1z~FS z8rpJM+mL3-(SY2CYA`{?Sbe$lLTWZivTyYQ=c z%!I<1&=kF9Qh%s(QZx)Nl7#8(G&DwVN{I^}?A{U!|9VNE!{9&2Jpm^sF@5}p0`bD! zN9{1uS#Qg|=Dj!Ad^H+|@z9eT)|}mqjzP&4KNR9aA68+-v+AaJ>W*QcnaxQJH{nVi zQpiaarjxu%9exp4gd!{zSx#|9B^@4oeI8U#^t+8{{;9kTV<({d#19G-b|%iHxtf^@ zK<@WjZiuXuMdnu_D;=3%Z^$B7HaFT*fqzqS=&uy6a7G_SGVIH$*z>{(xGJvm+;0w( zHVC>tOzE203?{35L0;AiCaqf zZe7t8+!WY(%_e0lKTg5)dZ(EbxJ7hFnPNe{5zL5Yk7PFsD%3<{bL?qm^RQD2(#Sfg zXN%Iv6*2ZeV6Wv$Qp=R2>ZKx(PD#oz%blWZw2QLVF34&#FN-yiyX%qMSZv6p+YLE) zqakOmHsti>rhIa_E@!SZTfNcg%KEfA(9LseRUYTQ`VAML{S(Y9^kyspYhXHgbfb8@F~NA9-fbxV!q&Z?}*x|G`$UELhD8`9xk zk$9M4y87^tknpR7pgd)>YSYG52^N}N@kQEXZl*WhP-vsjbcac_wD8vJQ%laAwPyOv z)>0)29w1TYHlzbP9}wGoQDUx+>!pJBS(AlmQEoTpWwwg;t1ZY)W->E zI^oMaZ&LAC_1gh(?_?@5xk{JYX>i3Z6|GdtQaC2}YoB_(DSRnm@M7BBa>9j0p5CM| zeXfjEu-q+GSl4P*T>=8xZ<{+dDk3?UP3vGEXY_nSa>(n(5ckzo>L(;dyTOg##BG;83@N;J(zM zZWPy+?yn2%-e21a|C{LJ=4Kr*6G`=p+6zOtQ1P{zK+{SVO$p&Pc>uUEQa4#o2-`2t zy})#Kn$~XR{dmLqwqY2LA{cb_0iHLG1RUIhiw>P39MSO3+K*&BrW=CyyJ0w-uN!Xt z!!Tt~aKpF{!W;?nELBQ1qK?!s2h)9;D|)7+c}(nsdb z&TueMt`LXuQ4Cc|t76)>hqlXu6y_1cyYV3H=RWR@o^i^j=pI$v79Q@)u3iaBZWT_< zAuY671gXPbL98`Q>X*?G7OD-I!$aRZ`o>%t_Kl|8*@)!!dQ)c6XKt=G<;F@wt}i#_ z8fA&nlxvHTTwUzIE^>82aO~u&H)ql3=F#`&DEz_$<|1SXcJ3WcC3Sd7Vi`h3b=3=% z)%>!ATfneC^I4Lj3riqQ+mDu@z)n-YOpFC1vo@SNrr9I0!M5}&R*ln*o58h_X$QM^ zZ{u2^yNVC9NkSZVj$qTXMd??D?jh4g|3!Ur$T#fKjBc&lXfOe8$5LrmWTmqtbDcYK zy>ne|HgCwC=51My7Ny);lX_Ifwao{{rar`VTIemzKsB^pw!qcZl{azca^>Fy{5a?& z!VO0{PErP=Mc2yoCp<qXoHDzb)5mw`8_)TNYdM zvL;JXgFk=m5UyifLCDsXkDqKx{bC7WlE0E*x7?$-d$f+GjKj}~PZK6#Ud$}~@@3H3V|e#+T^-RiSg^bD zxV)2Tr_nFUQC9j>p&VWeh*H55e%_6B;&J~}K7H7Z{E~o*V>Y!u1NeD1?Y#fC+YyBA z(`^r)Bi13bO|pH`!a7soOn=%bT%{boJYbjrzpM!7R=1|(d1boZAAu9$Sw7dcu1#HE zpvk)6KaNMcI|?qr-tRcLJuD>3r4>mW$8tZoYnn;3-IQSV;PcWsSwiAt5=>(d=&gof zJc=ZTx1?PkqJskl&tUEMfY^=aZDG{KjZJNO_oC2Fha^b{XOHvpVi>yuI#cL^?2hbP z5hi|(s3p~AOV+DxS=xx??wV65E;U6e?Hnd;nB-Hq^I?W74Y*9%Jsbq#+_I~5rtkrw zD_nIPE1x-m>=R~aVLUIYIPMWY;bne_vQYWm6E2ZA%Zz`$k!u|w85}%tL7qX92jL;9 zd$JO;1!25!l8nH~Gz96Y38A7{_uWQA=pNiKxvfWs4TT4-4qxS8f_n)Q{bEU?Vo{p; zqSPU^Tv4jIl2o!K*~pY+T}rarF3EDUC`*mJEYxx`SIx@Zaz<`%WK@|&q>< zy4aR03vIc)(2~pZkh!K@Uv%4cBxQEV$sNcXj&;>NgsY^NAuAhBRv~L;kqt<-%9T)p zhY=^-986GA8VjzSHx#+g6b(W;s*^ow? zZ+LG=2M=g?+Uk}GW!#kM09-j4*hL8C?$({cwCU%1U^nq#ZbyhSNV>SAt{?xl!aaZ@ z6ioLpjE7EimQJURYo;d6TvaOhvMkGr+==GoMr~GZRBy`N#%)<{%}b@TDy=L!9pKhI z8FVgJPX|*E3TOQ_10?A44a0aC3FAk9oR1q@!rxZmd8voXJ>1?O26V1*ALU_<)6uy% z?bP&?OixY6!hMkUP3%);AtP|F=ILqYPX9v(59-SZb%iPBCjE+3z>TfQ`H7N|VzHnv z8sy8~rkD@%WO@|7sE+eMu6X4>){~P{`ckwh+FJNN;q+rPDpP zgBy!4EM!?`5RWUIxtHzaHgAemv=Z$ zyBkULrGegV7{+5mV#su3X^cKBLa3;s;-b~8OTDro)r~coo*b8AA*UbcFdi>>|Ay$Q3*RBw zf4Ln&y`7O-tE1Z*tl(p*+?17SB-K_%n%RPM*hi_D)K0{{>EilBZ*c}iuLpn3X*vmE zy%GEOm1LMf!Vhn5C#pzJxv4v!duWf-adlJWGyFn4weL_|dQRBzG?{MFUHvEuPtayI zg=aXLNulA*etw&vyDy6i=ju&6S9YP>Yj5<@BgEC;E#P`}>1gU&aEi~Y53FnGk|YjJw|<50OUPhAgy9oP5zukO-HS8AQLBlfwa{j5$!GIY$`>U^MG4~J3PBnyH?ECvghaUt znu%+Te0JSj4a3-NcpdUS?p_+0mC-^*UmA#iz$=kg;GnB8xVtc%Kk=n{Z@l@2zF@4u zZ!`7Fsz62+T6{?#UmD1l2huw|l-BCurGXc9-(QX?8k^rjJDWG}1(wH^iFt1I(m=xU zaq9z?g)iY-gh zRoTci__8;?@a!vJ`6HzBw2Y7MQ-6k|GMX=*<4X^peDXW2i&ZF>^&ncmY+J)`HI*8&yT?DM4( z%e-IHK7p`L!+aL~@95EEswgK^?)Pg~=F!vtdwesxl?SgSz9f=+S4aM3f8iQux~#{k zCr-JS2BPfgYm;yfaqcb6J*(YI1Kn8B1#wt_p1#nhkCH9sQtVHgUmCc%JVU=U5a*RI zMC6wOT?UoQ8P3{#lcFmP@sJu`0;M-{{_6^} zF!&D7R?p|EOEC5(=og$Mv4iNg3b678ZsmGMm3xcpH7U2UQf=p@-o|8J^1{8E*#TAI z2x0f(9KmK6%>Oe0JowTZjc6Hj4?j*NslJtYeR%nbwcvm8xJJ|5g)!lIs z5t#XCT>ur6YK6FXKB#*8NG@o~gda_{AU;a}kDcO0vrYwKceDjy(>&v~qIm~70t*uhXko4W_cK@U1~`Ovf5gag~q(h*XLw5 zx-GX_cVsTRD799EYa0*Y2+N-%b0AVKQ{v>c+MSjpWQ8(#M2uL5RB+vY95%J@=PHTV*jOqHncYImtG1l5Z7d zqCFyq@{@A3FfGSQ$K}+%Q!<^ImQtr61&pH^3VTW?ulIOvrNJ*QmhUU;UbV|NGyUuYdjP@W%Lx8%h{PDa)&C^6tCu$>0C|->X83 zFHLjtd1q0ZH+K$|;!b!U6*+kDkbLDUUy=Xi-~W4g@`+QD%lD?uTfpMtqWr@@{Db`J zSHF^TXV1AWo>OIb{)HFhPyfZA%6Gr_U0sQs&%3yU-!YS@*^#yNHGKgd74j{8!JTU# zDxj&1q*AL^t*H`@FUg|kxEADEHxv2mQk zaBfKVoD;@jK764a74B5PQqj#gTusYzP|?Y7Y!|*bkYx#N!##%&A33b~(S>bOE|)dU z7QdK>xo>|6BDYG)~!g;-&iW12K`kI&O4h(_kQlvha$hqnt5wmB%oi|Cz<^` z5W>@+CXZd++>ApNtLQ(hH|+?demoC6*ZcR+=rzGFR%T~swd^5p&da!x+$r>Ps?20M zX{9Q|P-)Eag}&9ObGs|FJu08Yxf`uJP9Vlv1KvK!XLNt&>+4($@WAUHa2iAotK~d|3bQhFTvEKOL{?ha%7 zCYWeq)}Y}M$4Sy@3``Tyudm>vr)0lkQ&N7UJ;O z*LylZ`=3vIIdX=mv1)Pl1~NI$`=QoK6F2dU0;vWI00E5Dqpf zZ{x7AP}Bn^_X4M=LQc&b`W#@#e)-YxQdh}It&@+X+HuF#R!%3U8_kTY zW3swNX=G%rP7@D%cph4-x8wbw*J=m{lfvVqS*G~CqAQ43h2WVL50hMBg~>78xkX1C z7gHN!dPg^p?zUe*>ki^J4yG6PDC68UZo;2-HT9zxHZ!|IPz|^<){-b+mwK)uE3HMD zYu=IBhTCs=DZ45w`3l-FLfdkG!xqw@vYD%!skp|2q882-z*+Hue^vPQ!G&~Y5C-+# zrKj9#4G|I~!-cjpstTh)4VaS2)Aw+7dS1Hig0mRBmB|vjbsHA-AO6FpS+Hc}>yId(h5SIEUk2cPh82 z$kG+gsu*jivc}=kaVwmUCssJ~Ug+=LKGbKi!ud;I{GuwjhF{?vO6z3M3TNizb&mk! zB<_Q)s0H`7Dq6YXS7oFmQN;uBvm|sD+uV6l-qa_(Bjp{ZV2M-?X5pLJORj^LE%A8%h zZh~Hb`#}@Vv#CI5y^G%Ds#?~KCRcW|JwrZJa&mizBHD&fVa@h0`1Yfca&&Y|_Kok; zH0q7ItgWr9lDu50%F61hTUqXvk-EwkWupJ`@`|j%p9)YOv#*7Ar-GR7LE%niCXd-4 z=pR;x^O*gfc~B8flWnhU>d$Z3`r{z#MTISe{f*~AZlzq*bRB zwCjg+;|GJu#(hu(JkG@aRT@`sj*oGhun-q0Vq@!+B>LGo!AN#M{ zNmq0mjV1+SbOR4OH9Yv#F!`_4n<^W%rmR;Zh&L;dtW{bNnANtdl{>I=pXd&x1##PX zY+xdcOGhfrjBYtY_Q? zxW8mjzg$%}(wJ||tD<=}x+9CNHK}BpC<7ug0vaZZ@>0o6(G}7(nV?UXY3d;)VU2~P z&43;wfvz&f6Z%Dh9+%DD{oRIw5qA*T7nMbHG1-IAtJn~Duykvi@Q046%H%fsAC)WU zR~@t|-PFWiFE1`o)BhtjrRYvvM#TWm!fXBvj_V9@IfAG@P)?!*dbr+jj&EEP?P z3YUT^ct7{K7ld0p(8JxcyE%Q@3TLiX{Nk6sbPo#WE(i7>(5(kHZK(m#Bq7XiZEZuY zUcD;k&YhDxckaZ(Rj^b#Q}IW|=J|8y<=XXYa_iPDRmgF5Fik3s4;?y;^pQbt5%gC| z!KvPGD~hjNxeB=~v$MB#B{R1?VS5IJGxI%v{+uewsJOdx=e8^_EvurMO6Ku#?%SIY zz96tG1yv|g(W~<&PkcYqawG}|XDVk|@5`4j>q=CXjdh!!U(jtdbTu{V&h%I=rk@n9 zR%Ytlj^q-~1=G5I<2uTFS8k*IsOY6)k4jN0{jOZOB4^H=K^tC|8<0DgjKKbNhU9o-{VOe*Uhstc$k1M>{ms#HP=g-TH8#mOS=ZY(cspMsym=~3umo8n> zFkGd4`}Xa)jhPP58R0pj@R$;gseHYK{MpBtekcp`Crn4bWI)@nY@z+*wm}+!a6a5T z*3E?}48wj~E?49h`oh_>XEhI&mqMjF)18=@l(Ax7JFTuj_vf4EU0*cLG9&%FbMq+g z1#KIi3tk(yZrwzCENfX=?*gv%{$z9o_Tu7#eEji8=+}27N?qfaJv;z~Gx2@2ADfep z*{Q<$6DpjwETQe)6_LXjs|x3r`zf5a0Fm7jN66I_&Vw+8vtjHtIQBt!`{08o70%6C zS@&_?KRu~0xMa;m{o%}EXW5a%&eICB98=IOH95Lv7>WTD)Um0C+G&8)O@BhseA8U2qssrdd5 z(Jt!6DK=@>13jig+*|dd7p9dg8xPctCO&-3F7#xw?#ST})JO&2gin7Mdc%dI?K0Q~ zL=WZE<_Uj%kYihUlWn(2Fre^!!MaHlwKI)GI)1Xfo#;<6y_pnOHlzbHl*9dLcFxXx z{a+GoF&~h+xiD#@oqN`*8|`X(B{AJOaC*O>Waei0UAr@bJr?Ake<^qML0X!o+8KuV zQpxR<(aw$sJ6sI$zS5{Q*QiDa+~D|3X^GS@PFI_4sp5dY1lXv0^L&syd(QX*VgCksT4?^M0 z70yX`59O*#u55M+=M&x?V*rv0Iek`pINz7TnJb+8DV#l8bVONLSd!oT=5_h$-~Cih zpE(^1m9T6Vu1IB_|Ht3_4|(&=H|5=T-<9{?eNWzd?>$vyQqjq_Qzd4q8A8z`-1wI9 zTt$WJ>#x5qzxc&3HY-{he;>z;pD`M;~cAR3h_ShE@DJk4HU%f;iNXP}%$Y z-~V3z_HX}I+lKXF-s}@>dtK#?v{ zg>v7$JBRc~kkMsBq!@1^M0YekcF%kN=?U_YulWr7zot zUmmc$TqTd1BXkNl)zLou^5dhAKGrV{xZ;{{zD*eK!6=-!V2dEbDx7(3@yiZgM_l1d zbW0LGV4@6pT(?}U|ME*Oo5J}4;d+o^7zR)!j@|$;O6oxAZ%T0Ez!@enJ?P>64X8F8 z?>#~_+8C9rJ_rN=p{kDspGFEK7}+RJpP_KdLVXq*98LErxaJIIR~` zQDK_wWZt6vP4jW4v-IN9@$ev|o$%Nc#+$Upe*Qp@gNGh$K{DL7;gbQ90fYO!h$pm7 zx_y%FNf`i}opaJ~9xzALNvboq7ye3>@wrl{N9YGLD4SJKkXYcyvkk-Ntsk+tmCH^z z8|tXIV{Sv>1ic9l{b}i_P|?g4x-?sxge!Mr@nKcaKVwk^Gi(%1oB2`6Or>lF;M7Ef>c_0DML0|1zB$ur7R;-&WuYrJ0a_t zeX`sdk;SMa3yqR2Hi|M=&B?8`mRwzI%H_G1T)NYdD|bb%%t6%b$W@rvC~%`(huoZR z%dNRcZqGI3?tDY$7b96*YRS?v9-n~9WNI?sT#>oPk}T9$WTn0?m1b31 zZEjnFO9H|NT79VX_U+rxFpP(rN9QVbCB2XG_KC_NGB*7|y~gbx)^sH(m2*M3s+jIv z?MnqMl~uZB0o<2Y5O#Sr1CSl8rePjc43`aC&mlq zWIjA^bPwC2gs}Z22H_Z%;^w|V+}xJuyXLn5Vf%+ILe|z+(Kb~*r+mg?iWENK=oj}1 zVRmdsZll3+@?0#T4cU%NlY6f7T)Gqnpk5)D!3^~EO^Dh%%RMth{GK4a=WY-Tl|0RQ z94y{UcpJM2XX}Px>;X77>-g+PQ#V#SS9f#311m-Z9gK0Pt~4P|WrImj`X)+}qjzek z=8+21*g}}!BTFd%qg;p22yM2wlXRPqZtROxy45k0;{LP?<)$odG-MrSqe+Dve_obH z9ItMP+n+AHxj7%7w8E|$>>4SUUNns@MEfdHJFbd^Uy{E48g`~1mow>~w3ATixUe9E zfoRYWo{gmv>@?{S66hzq_4f+bMLLZu>*Yl4aMxq~>z~?o!U=Vdpgax}Z8f(OA5O=o zr1&(|59TKEf3)=oJoP~#DR6gg-YJCEW9Qc^3I7l_mVSS5$A{X~5(FO3Hz71&dTZ#( zLE1cDXaKHwcH;JvZo{NqS3*O$ue3As(#{p6l`Bd+Uy@d#BoWL;wkVAZBF{$~Bpl>vBhKw(*eEUXe<>A)RJcvaK8!kD~$j zkVGZEdx#EQKfrOqxrfg0C20-zK*G zsW3?270+iBgRtD^TGueQ@W+=ewxo%+Yv$03IrN{L>objPM>g6uS&G(VzOf{C>+>?- z#6x*zT^hwmq7vG+fE1}|#&GNO`>rfhKvQTJ{X(T9e7A4|!qw{>KD3-eh+!CR$mqG6 zcXV-tz(Ypz_xGJ%fliU;m6~nZkphyqf5Dv*qKdVaOJ7G>_3XAyXrJV<&a2cu%%8_4 z8z0vjHC03=R|Zq4xQ$dvhaoVRSLG^KjI*p%esY@$+C#fA&9nq)FLEmcDmZb_=F16D zPyRHBcDgZruC~-wqezo+bdCejeDK%C_|9zl=;gL_&C6}H7viPbH^e&nW{iE`?>IKTO8a^NnLFZfR;c zIDbJ{)}_UB0oREBaMSdBTl1XoeDRos`ZL|IErzBKH-@Do6~uv%Wd++l$771k>1c+|^_l#$$~e;N4iN<8*LPV8Q6E!>ry&++f=~sQY8w z)Hv{`34?wAf!w(cBYhd@@fpKrNH@jirZKi4%nd?QhW<&(^2O7*L-FNji{++nqp?=Q zBs7DGZKeppWLTAME*|>{4c^qk1dS_R*`0Z;4oY(R*LBuz4WXgX?%iU-@gO(OnN$9H z-BA27>2dRBaO(+3;&S&1!($p~04MJHbZ$xaw7{yqMg6>6Lhup0tKGYI z{TUe_PKz5$c$s9c5X93@XLke_mdy2$ozqPtmOf4nci{4Jjx@6(SPYCQO_K|HT4Z zjeV+tbHMY?Mr0e)jqS|5Sr+TG777KFK^f-2W;L ztPwUJ!{V+Z%$<-Y+s8>kM)-vQLa-ejEC|~qAuMN4L7lkrCxy<=o~#?KL`#BvLSN_g z7Q#?mNpU?U>dZPiGbyfrsIaf3go(NBd{}3Gfq`ck9Q8w+i^Yh`i4ypJ(o3R{J4O>W z2Ea3A7{*?p?^wuDm7}mToq{eIknT8!n@-$#gW!x|6Y0c#x)ApuyqjV?E`(k~Q|&mt zIx&Eid&F+kM3&ZDvRtXldZQza4kncuzAc<9n=yH19KbG19SY}^I^lwY&Qs~<{bM_1 zSmLnEC}bAw{e&dUp7{*yZes7;=|!{WSOeY;uJ3(t2@z+@_$r!WrS17BBfw zzam`b8*H6H-S#YH+J%OH$2@KuS{16d`#jck;5)Exim zEVrXMnQJY|a%WA-Qp0tQhpQH9+-6@yJrW&IA71>C19up-LHBqI5Xj%^?vs8A^l|g~ z-M1hq-bce}PfGwn(H3Z-3?9h18ay`faOdrKjB{bw7xEox74RURYsd!vmYa(*U%M-F z8@FW5*U@9gE9PR;;TS0n%;*^a{j|#G4F}wf|<-05r{w9xjLBP88(f3c5?Z%K3w5UMRO5xsB9h^ z8`V9a`O-XH)e0D%O2Vcz%!&md7dLdU5`t;(Vra3P|pOJ2pNp zIVy!&Hl(j*p;BAZb6*Cq25AXUIXpVbm*|aoMf{jos^`%z{I(KpfXOb~XnJZ|{n_S| z6O+E3U0c)S@i^)^Ha@1uG`Tmg?r)9sm_FNq?LmU#+4UD!Z`PH^jKjDgKGSAf61E|~ zXkfqV2h(DB=EJnuP88-9Os3UsbJzZ9LOZ3~F1QoU1-W#|wkmlBQ>Ooxj3c%`>r*?n)MDmS2+w&Y&o>=EpxfrhbH z2xBQth|a&-EonCJfL|?36LRRljN~!7s8uVnxU{5iRBj<0zjv?IBblB#DAW57Vgj%a z_a-LdZ?KxSekj34v+H_~Y)at1Q+%*IXzm9~IKTdomXPp6h zEyydjt4FV?T^C_^&Fb??mQNgR`wRMN%OOCg!v`H+zwpafrJbutqqrdT93;Ce^)~K9 zkciu7@Jmg9afGaT@txl19|E~ELkrEM49D;x$=aT9A z^PI)`<;xuNc-~XxwB~3S#!leXNqFt>mkNAoAYT}``K5tGFFOFz z*b?4XsE8WorGeZx_uRSjx}Rj$cxD9 zm6u;e8$2(gBcnV!K1MHeWgAl2$Ns?fV>+zU3okq`FTebXrpXr_vW>YK`7qk@x#ymT zJgfD6`st_j<&Z}XAJ#VJ$vt-Tm~Z3HY5l+Oh0m+W^T~Xuh~-QB82{O4pN-p(;$FPy zRw6TBhH>S20qJ}}+b{H~puBYL(+l(AwZeYG7s;_7Fny-=GTMgqWFG7jo0Yii&uX~y z;H*7_DD-DuEW^HueW>?yu3wr|V zkc^f_8Q8^1QLp#DG%(UHfp}ep@LRt$Fth^q%Dy#wOJ9Du20Qy$KtpSz_;|t2Lv`}* z+u-u0vOOn%^hbZB=XGkp%l^Vk15ckmqvw?8i{k}XQGQYgJ=_)Y{<1vF5xhe#Bz_Aa)=fqC4F4gsADKF1UWpzPbeD+BxVzRfg zFfZpWT#%KGvNZUup%i3kwJJ|N^Er9?xzEYLBggPii-DSH`t%%bIN@`wnhE>85|=wB z&g`>gP`w_K;yuiyx{Cvj=xX}I`6kSzjgBmC)MdHSlyWO0HOZqNx|gWw4PGBE{6h*4 znP@NplTO~voffWEmLD#dhe#)I0D2M<*%z?@XeGxA&!+ z#Ql*@WUD;;u|*+58>AWJz9or#Xic8iK=Pa=vq%Q*6RkgqwED*K8StEie%F^&)ShxP z4{z-YJb66?-D_O8geEU`OXS~^M<4q7!%dTbsopf{7SdHmR~~9GL)aJ{8<+QNjo{_IhwzPr66{(Nhlxp$1)C#wyk*PuI+-+E+W)cPM+C0dQf4%S*I^N1G zz17(^rO=lUJx%}E3>{(&pU1tCs8}DgHP|Lzw0$77vRD`)Ra6a3MKK?cIez-TY^x(< zwXBTQvocjL$g^X|QNM>@y> z=dOipxJwUD`*!d&GrnQ$b$A`%@=*(~^c*gxv0PhbMzbmt1(72CT`0g%{l|m=udi0r zmNRG1$d7*fW4U?rroJRDc^~-yv-h7(k|o!jCwxLj%E~M)yQ{0aTI)umL4W`ViUDVK zW_L*LJR@K1o3VXf?dep)&;NJ)dc=*$ zh^)*KjbeBFGf%i*7srol_Y)p|Swo>jdgq;Y>|gz>e`)W&`>y;sxyxO+y;K&LSL~O+ z{FVLP-~Fv!xNxznxE@qsKL}7BxiVNO@pJmQxj9$r{o8;0Z|%^bLm^NC=B1X#tc8Vp z_E&%P*Y@{+|Mzz4)G3coUeZ7j`L(Zo&HnHYziIRHyN#UdbE{T79h6ik3b{@qoWkX*g(PAMQ5i`bl&-wcZewG^73TQi2B9cL zfr(NUca(O#1P-Mid4upn5sg9>MBX5sckHYc7~h#6!XVo(98UPfm((>HN=Nx66n8Sm zQ^EN}DF=F~1rQduP#=L0r`0)q$`=QmQ0BDs^z@AKQghKPE8x9rK=TQKDg#(Lm0{@o@PejO&sb49>_!(>WZ?WF5`)1$}nAK zgFrUwAbv>`-{GUbzi%A>!!wvU)p!R^Y$M5n8+y8OcQKmd zr-7KSQAn5Z82v>Ni_LW+ZVN6fI#7VPvRUnILlZVHC|g)>xV>gM(~?fxEWZ38mZo+s zqF4y|=}@&p7F-UQEN6UjPbwp6lAc<6#*6moW>%Q zg%{Gni_LQ2+6Sc7U6P z{1_n_C$Ui$KGv#SG*Ze<0b~y^oXlE5O!A^)t7FqOv*}95W-4Yc%pSCt=MUTQnSC}{ zH!D~88lYsE(v0ede}_?&}& zz{rV(zME5@esl`wPwY?s^iS>TwFg%?FD$Ltl`EI+%$YNGe7%m+nJ<|$ezn5XM9IT*(3O`$ z7Km%94JCTKRwG@` zqd@&c^7KX6Nr(KUfjfxu#d5-o5=S?X1b0w=w0qh_#`~SGWV{Y0)HjitQ{+LG@C60_ z{?bXxnEF;b#=ow%wW_^4SFs?Y|DsO(xW=WxzCDp9Eel}J^C%R~gj-ozv#VFHIInvP zi~j3~F5r`-9?PtU_&n&o8ByWP^*-;t_ntld^wTywGc`2kqgOZwu*PBEN0rIROu!ufWha9-^xoNq6z*rB7( z*fY;QZ-^c|;B63nE`;DN0;Svmn#D11IP0lR67B9y|ry zU5f5zE{03P+Zlc$)^KqlG#D-*@N*EyISz;Wq=Vz2k0=ue>(lU@3c7Q6WD<~Nv`8Z{ zDC?s{vIcjg?GZjMrDPsn?m{|D{D7a#QBfWzJS*wECFU@Yr)|qf*i>NJbBrIIV_K~G=04Tnx~$ug4*)-2w#YW}8GayP7+ zy=P7JaPAi-Y);I%HyDKRzh5>##p@~b;62@grCmV?I}H6?M`QD*2!yf4F*My2NAqPnnwzl0*`giH zs2EcZ8lBEcD-eqHvyjP=zynON27DU*Wvg8!`mOgHZ}+=4B^^t2df{f)a%dCsl(V zil`K`2SnhdT#HpWk;=6ildjwvRO}IUn8KMcEh_sWPM&1t=JCk8%u_0enyhe)Q2teu_8NLA?F}K3vDaso_yVH91YZQL*p;;QMy=%o#t) zOFGbm%6{LzefE35`@6P#_ihibm3CiN0naFqSG8CCf%sg!c*#%dQWty?L0pvnUwZFL zlC9+B$67|!>v6S&=t{>Ng+GT#;xkIt@QAY4Kiw}P&Sz;XE-rf6e(=Eus@EH?n2-Af zWO?<~SG_(%8{gS{wNnh1S47&Ks=IyXj-C4Cl>O{yKl8ffg?i+bt1(`C^);6ph4GJn z{A0Ux`Lb=Shd#`UEDs(y;MZoHc=m+dx_Q$+QX8fnbE+9-Gs@IC@u3}aeF-nRj7ZC| z6NU4aQ8@qp@7otOR&a+jfEPB*X0z>MML0RH^@G~*Fu=1Pn;b?WwhQFr8k&iTaxwF;XG8%&>y(I40zttQwm1=!{i6uluG2_Ni(8hal=|?^LCJd~8!c*YT|Mv(G zg?2F>jN_0TJW>o4M<0@EbENGf5wrS)V5_`6FyNWytHu^LX3@{@;`NfiU2VzThEssT zVt2PBJdgeyDY%2^#vYyhnSa59pHt)&0))H$wK*XW5!_w=xt8V(%_qfGYnJX=y>QEF zxkamGm#mT12Ef{`NG4ql>(cA71KHekz%p8~CzKAd9c()|#hNyOBBvj>15a-!k?td4 zV5LtibQb+*w7Ch&`aoPu62?N6t~OY$c3swn)7F9&Hx`l;J%KR^Y(lx zZ!eU!AuqP=sIAz(`fZzPT(?sDsz%`}R_ff4{hH{e_-!b;nybB9R2s9;R}(-epHOB!EWsyI)%=}&)ZKls59?DCb%cKOm}=X>Yw9XopDsF%&IUBmB(?N&p7(nG=C z>iqfh_Vb_r+)-9ef6yYCd=F zoc-uWKk~An9=Ut`=FOX4HeAud{ma9Y)sGr*Pt!0U!tGnP?bpA4-<9@f&z@6VUb3rd z6Kl!~%2e*F2H*ew_wDCD`3%Ba_0!gV6Y;vLRMj|?qC4x<%IMZc4p`@x6xd1!uq zkmj~cVGLr-m~~}*>?6afG~VG%xuF0@aqfH1$J6bmC3UMzl47X zEwlT)6*=dvNeN?i6LI>@Vv__rvKNR49^tveukmmpiAMS1MY(R$EqY zaq2l)KoBz1w!9)2dHe;w`7inL9_Rk%YDs)h%Z+~aBT;9ABjO>9}*}P z2g`=Kr0kzWATM`UQ+|Qgz5G$wQ%Cs6GA19K;$B=_u*HR7E-fuvLv4z7wXwe8^>^>? zUH_tKQFTEa;!)c#F zMwE54R7feC6%>UtcHThlq&Cer^M0?K{AJLzH&ZvI08F?4Q)>t=uO$B`Ah#>aG>pVA zy!=^|RyL23Mko;4Yqx}f#Hh>U6D6s>ubxHZ@`8?@J zB<qif0;~6b=i~*Rm*i2t-$9}gl#@H^x=rYC_V?1%#YFZc#Esf%iFCq9iX^wz6%D03oC(aqD{?q_qDC0?{1fpDKE_=_+QmD^-7R zm4!RP*D9QBM(NzKT03W*Y}wkpB+vr|^+{e~3x2X0Wpma~IHO#4(o7bW&YZsVlb5~# z3vC&=nR<3hq=-aRntoW9sr9=ZGexOC|4;ex93aNnqkGTe@q$9_%iJ&;0mOG%2N1>I z2{}S~>GFYnAdM*+PuQrWi7_Sy!sr6~c4;RV7Jn3t!mzLpNf>?bYLhEtZ#rNSl4~`b z^t=^?z%tW>Q{;bN8h|U7LwrcxE-0IMj(&c^xn`aGy0vp_*37M1BP%mgu~w$;r<;Qu zfxl{A%{Y*R?vfi(1RgdadZyy@L|Y47yQa5A|9dbDP5z;QG(jrw3-k&42=d3ik~|~7 zcMvE-LQ%_Zbyf-|3t#KyTMe6)?}?dNdv({mycvddX^7bHqIl*7PYsQ;YgWwMvts9#6DM-yyK_!Jqqs#33%{I3G1F-{AeFk?nT-zm=91QLd|B= z$(50UF9R_X0@2=eQ(9T&)9*}{OfBv4;6Ym`77F27k8R4sdYk*Pd4Ze1oKEp6!>9=D zvKhrL<*v{>Du-d9jAMDE%P3tBj~j#K9aD~G8qDcI&QPZ)?=g{=yVNO9UeMV+7$zq8 zr76@W*9_)W4+X#ehIn4bs#C&*HTEzGh9lMjQDU^6@_3TaYgV)}ijhArPS2p{6Z;sC z9C0KaV~jB#01r1MrU0W9#l^yQ5eLYy*&L(7P1uuV-Kn&f!9Ja^psJ-1OC z4f!CfiArJk$&TOYq@ly#d<%d05KIQ>nn}{}`9YD&!Ka3Fn%F6;M0c?zV!RkWO`ivl z%`^psCr-%)vp2zWZ*#3_wzO`xS~08C&6+5j`5k_T1(Gj4{iJeKHkUZroQKS>(|}yj ztip#-bh)xCR)&DpN$K_369T@_z#cxF+?tX%JSuj|A!XG^qSA|Duy)Po}9tlr)26F_3VE)nPmVO?jBo4G~q~l>9M$un16fq3u!%|?^ zORH-M{$af3GmO3IztHCHPx|b}N&h*5=N6=pGEI z7-Nh_0S%H)fSwg;2z+n@!~K2y&So{VgfS@c_2KvlBxDRque7^9hGKZ0L3&JLtVLNm zJ3E`)IXh=_^YfxP3oj!ZrY<3NntFgAGDi4VE>O-W0lA-=JC?btnl!Ov#+L;WE`qpC zjo)byhLg$Mrw#3ryt9&fVrsIh>{V@sliF_Ufv5NfCa0z(hw_`q!kxkMl4nNtT)zKh zg@9P(tVJH(rLAx|n-U-H*4?vbkKdh*N&YxRO}_jE-wN$H6BD=V!`JJ$IeHIqWs)X9 zxu$6llnwc(eB!;}k&qFEY>XG{Wv3X7$8*{(+As%c7$_Uc2>E7aW>pU}Zs-1M+DcF! z7yX{$cz=4N8HK?g9wmjDo}5x$svdSz4|{B$wxPPD9w-;`zDfSX^fFEajpYqOc#-~t zV!SCnT60kc!TFyA(%Ht^tvAf*nhG<U+~CQXkMoA@U}Y&Y!~ZZQ0I;(iw3O(@BHn8G0zcRf`PAWTD6l+24OEnD4a zTeXp~MvH4+6eEe6)t|p0kkb=+UKGgP&DJH9&92x|@Fdwj&_*Nq^Dqh`C6G(%xzEc( zM>Ch7}~a?B-~*9VFcVr9QxCi={q|pQ8tURT!+OM#x0d~J7+l+Sf}2wPPJ;~jf(Bw zsM%BXroBBiXJ2PheLi0S?~nBfb5y$&-lyGPCoaX zz3{?GH+f+j%IM9A%f8i-WFbd`6YYlrI)>KsZZM9#N>o4 zm3g5ZW&4WCmi)Z(@+)dXCtR^i9n4Hm+ra~>hvP{-s4g*S)6_%yg@J?e2I`f#Hy}5$ zg#2JKPSmx=fNHgH2#u53y)olSq|jFU7nGhCDCziPd@9I%`)X)HV~p`xLztQZy5nYI zM#M1busg-0=s?@$k(QS@+l`kF%esg7D4mk%XFG{`{p$} zb^5fetgl;BJO6ejZ&z>JvB_P#?f8k4_R8yTS$S&4GFs$?+CDQK}Q{5DDBs_+KKT3I@L?n8KR9OZk5v?S&gRIP~H8WXj=xIYA ziyLOw@7Ar_%v%FLxpVTFwIyv8rE04R3nff1PbB9L*g$Z#1|B&7i%*@ z)Nbem#26MUhD(PZ6?XgZ@^qfV_(tA?GCm--V)H=R2$B3V6@L_~n0&9!MqxDH7&XM+ ziU$}a$ySIww~p%@hWn-;;H@y#es_w&@x1#O*72d=%8J>}b*z=u#w35oYUNW_Eq!9u z?1I%Y8&=O&61fAyb{I%PIl}`tjUXCVGFDLk&Z|$NaBk+b$;_&yx-gM?;Qa)|@n1+N zP9~8Jq3|ObsfBb%Av{Me{oM4tsb4-Ggt3HiB#tE!;epb?&b34Y@a&T}P8xe&vsP@^ ztt6Ug)os5f`KKpKc5>I09iPbA(L&qib1f@1*R4=rvrMzD^3)*NW}pl_QEG?uMf~9| zWLhPW2I5Z9YT2A9V>K&Vtu<|(+#YMpykTqQw`?(c(!(eEl|Fcx$7)XC$tLzO#`ruV zc4sVfAKqIrnQz-%IcM{e8Jl7KgTIIJ-sDdqCKR80os9mALhR#@Kej*pum9DqUcF}P z8ynqz4N!)b%4K``rI+n@fA<^q#v5u{pd&bi(mZ0E?>SZ zd3#FK2$XhT``Xv+5C8C+u87U&HR7xIx(AjOyxwTq+A1$-)4WvYDj_*~5o*rK=k4IZ zgMRun0RCZ>1bja20(<&dp(Rgxy$EQ+Dsid`X-hXlA@kE?7Qsr-PY5eMC!Gtt ztYHAL6oLvlV0D8R53X8G`%12XK<<#QNh_C2TFY}KM3`=1>FaUHf?N7TcNejc9mzwg zEU0e~%Q*7DopM2zcy}=%4CR|HV=!1pQ8@{}p>ic49^r_ajvwnyT=gkRyb@=H4Q3iB zZ)tzLIFPb~2W_16Iql3zXRg%XMU0hd#hR)s^2HooP`Q$yS%o1UFMy0>>Nye5%2+P2=(&ezA#5CA`(KCc)noX7ag!MpabR-FtEX%IHjR`7W0D%#Tx z#lv-?ty1sj%;Ls3nSvXNIx=l}M9%3jT1SM$P(ppBnijI z2!HPLixNijK1kAf)bPdQ2*${{*(*q&#wfW)wVlrr$a~CZFa{OQYJ9G6&RA8?%Ua9a zTQ$40RI_@gpitW6cr3*i1KKJ|W)#klE1YGz!dd==<1}==*|CN!oQ`&-v)XoA;S4-1 zA0pNOthv*EtX**ri%k~gC|l&`fyhl*bortxWG=wNcpwM%?!qgP(IK~Vv_W{d6rTWM z42u=RrNfU3yM3^MK;_&I@r)hZF(~60+s97pCzkcr@j|oNUcEeuO~Iy?fJM|*5MC!>!!_Zwi*TRB5cqS9?nyn)=plgDA5}G)jS;M<*QCkHGAT? z;T__4GK?ePS_hX&{n`5^o*_suTtD|tXIcpd8yTW;O;!V4kecrO+g)>NZFusTyrf^o@Pjx!=a?56NcJ$~Gd-mDq?9icuu2c%|ZAk@uLcnQC zPS*14%yZ|?DNk2i5!avhfajk_;rw;`<~P4-yLZp~ujN?h@#~w2S~V!3Py|yp0ijG$ z+8sW8$jyM@J}fQDiqoD;OG~ai1VL#SuA2xar9%xyB`6r2lcT~EKE#JFr(21GiQ*82 zFccMitXCtSrs@qlW~EZK)wNYuCi5%RaFC+yJh;X~vHdTCwg7^AK&{!ZwbfNu@Z%rc z!zWi~OifR#Jc$v28Z;drpm?j-Yqq+wCO%6pw<}B~H}?%wHk47Hf;Whg0t()aRclo* z8x+dqGv=GJ<=4E>W~N~A7Of}(6*T3S|o=40d!_2}1~AP=W+68JbFczq@5Q3uFFo+zJ~ zfASXdgkqX}rpqNDJg=^<*{PJmd1C{GGwA@zj=4SKC#^ZX&Z+kJ<-)LhJt??%@19+_ zaM4bmKIO8~A6m_}<-K2LLO(xr$o}L{{=~lWWfaZ_LqtHnLIL!^b5bs2h4c0>RydFG z*@Iei(!KpNjs7VRu+U1ZTOtg!&M_4}rm!g`h1s0?XgJG(2r-#H@w5RA&+!|_(J~M& zDge^(`CRU84Y-xHWxI6#tgS8HvHf#1cKoOonwrX%7w_8j>o@GyoqM*nQPYB>V++e` zR-W2rN1uMiUVYH8$81P5hF!{zD9#o{G|4(9NfTk(6e@KOub z5pY=u(p3he!prI->Hv#RPyXL5x@FTvTH%a`8eb>JtEe;?o84U#EjMks(z2$uQr;Sp z@?)KcVi_g#M41!L!4CNvFez(pgF)e3Z?vs0oDM-P=rnx-muSP z+twnt_ zXj#4^YBzmc@vAgwvqW$v^i$1Z8BPi587~URH(&J4{`T!LwkQzKnzyHjp6yY>xspyo zIQTmi{4ao8E zoLHov;uiQ0blTrAkQcd7qM;x|;m4h_LGFH8qr$m+!Z{b#nB9G!?3{33U0JnHKKaB> zpE=$05GE(f_Rc%+_;m-9lN0_@wh(pm0EZHM;ogG1|Ni@SMdgf4jXHAWZ13KE_U4;! z`f2I(wFYUBFY1f@T)TG7g^g;}P_oR+e#w>N)}1?c=Ij~!@WT(? zozw5}WrMH1_PSrA!3kXQ8RiS-*&t0UX6}2was9fTJA2m7o;|0$hHEH@gQEG3H{Nh1 zCRbr}5vrgI6tQ*fTWP~6MXy}B;`s;g;X0Bped$YH#yoRsn>G@|#5s-rKzW>%Ea%Uk zcjYW$AQbv2tzUcXHNU2U_@e-?g@pyXaN&ZTK7BfrafHf-t1RAo@3&m3NgdHN6~)a# z+*7-O4|QItY8`?gU9!MCq!7Z87up_tAr#QPntn3TXw+R959RX(Z-0Do6}}AUKjHk9 zuYARhjTO$19Aky^7@sZBn!QDDZq~y#l{n$L*{2`A?TRc@fk$0R?y(jtgc&MZDy@c5q!6?s^)U=OMGBgzyWWrdbaTz@_A)1& zYgTRNtSP@(aI9bW9-|;a(X2JUoBpg#7i%TgB`G`#=UM~OVpJ1-xKbnIr(v&FBXo+_={+t#A&RNw?0v%nd;pC%R*ejF`rQV^o@hobM;w{So_cKgh(x^L`v~ zS%(yG+*ph%`!Mc@JPn%{29Zt&zF_!#az9@8Ppcm>2iuPq zl^PYxG&VFKiZU83Rrb^mWz*E4*>3gHXWZ+_5(uFDcZIW`IL94@^Q6`C2dz~;YK_@f zZEfNeTg;#IvZ5Uf78S*ddm6AG3^&FYpGVLSobZ}}TlH6{D)+qdnPzx<{1fgcJ| z6rU(#QCk0tfAKH;p5>?vMTuP3d;q5mhkwMgkSo}g>sRf&-}|2Z`Jex}D|>NA+1S*a z@vr~&zqbGVfB!dr>YJ0i+Qm69K(UbbsKEZ(;y--!YD4dn2e4^My;ryc?{?PvJZ~xA|Cz((NlV#FIdH%D!kM%Dweqq`#=BZ|Lpf3qX;FR z!<4I(!`-`g?f?CM|6lw5_rLFo>#*ME9`8B7d-{Le1piWkx=}snQ{U>cZvj91=}(=<|M(yO!`ma^RP*7(hwcCKZ~l$F_oXj6 z&!G^DaKgD?;T+QJf$|JWW-TdH#+2u%d_7hK5w?T}N%~g!GCgVClGod3UW2MagJ*l>Y8IJ>kV67UbD63W!qR;vg+!R)z_A+A*!t|SZzhLx@c>QcdfRzY?akz zyM6tdeWHcMM<0A>XV09q>({Q?ZB3xJZ{F}LHtLmiYd31vs#mSDwrU%SQ(arJ>iUYU zF5Pur>&puvt&KHnD15zAkv!a$6y$3(C4DM;o)0;+^#HX7Nq$h+YJXaUdUTk3pil>) z9wcHnA3mAzEPL=w(dQKuh{}o+vMgUICteg-ZJMoBwYaIbtlHw9*PKtwQlqK_XZ~~^`gY=5n+O>pme>Cys{Eg6wOdi3LRw@dHCqwm-Ht1A!G zbq``a2q<~TnG6z}UAG5+(!yl(-s*4?tS&oub*@{dRq;taTdmntqiF}k^*IfUua|T7 zmD#+#H&?P_?TYPbuKNoCt+A|mch#D5>u__v%7hbctw!5V-!+@$ljKwyZLT5FIIRlQ zepl-Weg>^Ey4tXfO3l_csUwV3Mm1x#_JlREbE?}Jm1)sm;L3|!`ztcZyMK%^ z#u!`S;krqTo#ui)P5lU4n~Yy8;a4vtV;!w*EBUN22}lLyRA1J4L3y00;{^z>h2kS|ck7lLw7cKCVT*kB2+L{)@h zA)Es5m1iKzkhsM2@{z2>tv9$wxao?&LFFfLe2WQlWGDB;A*XOa*&K2m$^ptKEy{y7f_zcA z9hIGV(o^|C$eqqB>+^W^0`g;L{y|xcFLK5!E#T?G^cS!GRle{<7I)NMcVolL78HBaJ;Bk>MsA2S zNc!}2;ll}M%%}tpFX^N1W3hxk>`<&HK-rQu`J+sTM7!V=JN4mTvcng10L~9DeWWS$ zecD`aT%aHF#gzAV#T%BV$4;cH)VCtfm1K5G5UhNt6ve1ZI46wpO_Rd|MD%>!S=Q){ zNjVR?f8H^oH;pmIKRtLS*N4v$$pg={a@>0E8Uqr$_E)Vo&V$mJNL=^cK+iJ z?Bc19?CQDGcI(PTTfTeSmC|d=OLq6xEycfKcW&Lb#f3$ytZ!IT6J1-AW>y>DOuK3I z%9`D|dEIVZyJFX_T(GMb&xy{vdF|ra#FX2m^LG8}WxI3xmMtguWO0Y?U|xbfDs)jw z{w66bvhGU~Iudz`q&Yb~uZ8vpQf{AJD3jfWoCbveQNCt%dGoTs)mq0k>RRZj6E?LP zYpGAtu05!Du&!kNiIO=IS8Q z-_0X&1}N#rJqlq_#tjm@dJ5&O>-Vuz(iiSa!{R<9b;m=BP9~dIZMChH;p&VPnag@! z7ir_&;f?v)xUhjy;K9v}GfapLPByEJcdl-wOv85PJNDE>!Csn~u(xKW>SWQLEobdu!E7emwoU&E?43fx zUQ$^dX|CD4!cR0-Eu%Q?_J+z{JTjWURUQrTZ8W%VRQ#KPnoaJt?8qJz%@F<#jnVZQ zN(#l*2GdD{c&)+JMMc%^thMsHRi>N-EBN@F9;1QV2i(ROV~l>#KOU}+#MlE|n7Oqgxk!g{77Fo09#GZ;!njg6xgtcl)Ewb6v-<4j`T#K|{^=5OcR9xE3nYpIh4|nL=aA7UB}W7=sYj7aP!FTJ4_^j^u(2E{zev$N zQu-M*T$#%k0<=ZN^D`75@AoCkkn2s{b_k_Dz=bUpHJD312*d zOo>3BCUpyA`{Yq52dB`_d(V*+RtUN4Cx`RWQ<~(flJ9zNG708SpKoj)F~=C=pEA^| zeZWX&J6~ssF#AZ(OuI}~9J=My<#q^VSv0$L@fak&KaS>oNj!$SLj!(Y-bwlpKQh*y z(AFwdyM5=jUAS=0&Yb?(PJQx$ef;4s?Bfr9F7szjpM3B$JN@x5?cC`P?DF~3cK6mb zzsI@5+v-(b{B)PesnzC`L)}l6PEF=*da7XMGCz-MShccbH*Z|9tC!E%g|i>onNNQ0 z{LY>J(9VAHp`HHdeWmqlrTc58^^sjTf8K6fzhNt@+AwSKMc!_iVuw^G!-)L4`6*IY zrW7G_BoxcE87GxH>j};6J-di?i~hqDB%Ys-*+!GKcen(e`CzowuEI~=Rh}xJ^(yVP zVKq+IDPCV$c{^--d*q~CL2GW_mEp=}JxBODC`B-E!=IDoQra&uLD!xG`EA zE(zQXmr!&c1rHx7#!I^eN`m&>;`0y!!`$yn`WQuz9i*{S+6Fe|1-Ia}C1SWy#2yMt z^B#t@|8|It!-LasxqRa#OLz0X1=0S7^BzXM^tK{oP;j45gR;40%}i6{Wlgj$(%5g6 zWL`-&XE6;8n66w^dCK?PI_miU~kRl?X6uo zdsFnb=$#pvnx|gRcI+i>0#8(%w!6{v`<{^w#dA>uctJv0B9Ec`H<9N*O{qFlS@E)`7MIf3n>JOe+M(u#owTaGIbrtRuDrdWayT)Sw>`y- zO=KEY$TlUjNadYVITTdJc}3^Nf~pp4HRH8IGWCq|xv51&(-q8|T#BYBnkc1Jc8F1J z7p&5mvTA;h)k^!VQamX8oa&rYVT|8iQe%uU#uEmVT2XNsh?9>&k=XB!5-=zN>CTKx z`p|fm3~CAR^X}g5^U)H0delEI^gZklfmft}AXI-EBQOv~!>s4e%YZ!hl|fMAMM`2M zG#vR{-U*D}CT&>xSTet1$>wItwr}^W9XYhmo_YGHJ$vG~J#+jids_Bm zM-SOyxgR{Z+YaoXvwiz!ZGLV-iyjTeotjnF7j0?jmMz@9Zg*~9v76T}*!3&t?b@Yt zcICoZyLj%jojY^N&YnJHXHLt0?wsAYdCQj9)~#9(Ws0&Kg*x~7j-vbdKT4{ptRc52 z!ehsc%|>GK z=g<8#3hv+cm*&?`!IM~+DUSgf;D4MteFW4=T@ic3g_^XY>@^> zSG0DC*ld=9$)J!|*onrv9Vs>Kt@#Q2%C0GUtJAcTwN*P_Te4&IMLXJ9v?I+$d%Cr3 zFIvT3%hv4;$?&FlJl|;9UKGxX!@!gi^P8 zHo)dCpUqn_U*!C-&8bYD&9&`IyC>|+qIah=_F}PV2Qzh>?9{`H0o(kVsAic~!}1zq zbIQJx=H5<2-YA+oIcthgIET~B;Y2f6Y&2DF!HmxdiC0(QY|~aR?z39)pskB4xn0)C z7FAwekzIKCJ!~P4F~%5=1mR?B-f~({^;1xqMe@_9xTh3pu6ROulMPoJgs>qV3f5@v znS&I=1pmDFKL~B+)#DkJc9HxAcPSI42fx5bBO}L&@`O!JO$M6mk-y+idG;~;KJ%f6 zP&n@W<%M&zv$M_vr7Frl6wdbp@lk>jp0p!ze{(q98-&My7^1?A-w|=815ex`%w5LF zQ4$YiqO3?~82nu(nr8qxCVlQUo|Nh363a->c`eX`;!bUgwjpzHxaZmZ)n>}2lFiP{ z28DW3XXJ%^$5Xj6kDDN28nwFfDV0k$AsI@gvho$m2%enY<(iJD5Z(%;OSy8VHswRT z!3UY(!xz7U$mO}~oEPPh(*WYahx(2*<8?okD37&yNig{9pB_TKJ#HdLsT96oz}-oq zf<46OgUW{XhwQwBk$bTr>YlnPP~MV-`Y(&ODyvs9X&L}d@J#o!bpQH|6a8B9ZB1eP z3d-tGo@0Fa7{4@djL!_18feWZ`CQ>A2UiOEKpdXko{)$0FdfXk(aRd8kf;)>bDn-yEEG^~-+!mUu0pGsHJwCuEk!WJ`ao0-&N za3Z6PfN5bH$`aOuqwmtrAT>LGSs+BaY_>VQ$4>|8^H~q8eZ3Or^e}7@Lny|J{?IX8fB3$30b*m^giuz{&fyXT>o8Cci4;E0MZ}H> zM#{An6#oIEZ57c)bnm{BduTj}sM~|u!lsJbsqDkTN1pHx<|u@Ay1g{FD;dp$6fxTw zZFRFvYv(qsSvq6&(kZLuu3Ig$VYTeK`X`&*q)+I>?@$J81hg@T@+Oj=65*6;R=p0C-XDsf{HrJPlWiUj{#2OV_jit zdaP!}A0=|7Y8m-?`XZmt{R;u{(gG>m(JHf}0XSPy5tkKzpS4N{Ei?CmwdP;5>hw#R z)2FPME%@oWb|xRbl$BIooC9S#2qihj7-I-w3<&*x=PwP6&;1>aUnqS1(Z}{*|9}70 zZr#4+cio2Y5elE0XT3G{DliX{>3}0xy$zpUwGS&96933z@DOa za~=tQ=guAb=%bJ9>eZ{RV0MZ0!3zt&@P#kb_Nw1I%S7zM0bKB0IIpZ&pBR)zyl)ETJUwY|fJAVAQ@;4{FFtZ>#aAvY*3b>;2Z|Nm~J*2cInb3uPa{IhkPg$QK+I|ef#aV zZTIfoT_yh@$QNZq*?gov0k7rd<J!PsUCwDd z``mN(?ib&4Wpw&Wj$!MLd-oRY!iDp8>eMOaQEg9kh0>d{dH(t5?YZYp+8(uE@*9ZH z9$?Sf=GwJu_VLFbJ0EXn${6j0vU%l|SM1oaV>U5086pirEO}w!CyEX3X9#WR~Kk*C9lGag7#U~mHXM0*<1DXz2P1RkG3FIsP^aDIHo zaEcJzh9ic>WI-C8JGk5S?V7T^nyBVyrfh<5 zIkf?2LBTi0OlVyE&msalX4RF=8@66qvyF{)t5kV`LESb)m1<2J`i6)FS+Wpy$uh}3 zklN6SYR#6_RlcoE(Xz!!o7uh34jp^iY0v%xmO&dRyGDC5_Wl(ak0TF8~9tf4$E zVfhFwgFSi(DXW9$DAr(Kcv9gdrVr%pWYtbw;ha~SGP|>AcIB4Zm)c32m#=7|Z_ytW zr=WqLsPZc2IyUPHXS1@_Opw2bO8n@@~6V~vFSbBPx8Swx+QiHlwUIV zuNks+YeBhHYn0Afy?EMcxf`b0LsV5?j|%4?NlXG|b4G(?N1ZgMeyW+nj<(nB3o|); zwOF?!+87+xMt9y%?N%+@+z=ahDKHnY(;2nUZ`C`t)Xv&sGiz65|D_e|*V&@o5LL1T z$)dqTW3($}L(+*PNaYU!N#pl1EHSYRoBxS~Kc}X1vT(JKzh?nbBrhBOJZ_+z2BDmM zGmL$m@csb2eNNTblT$eqWiQEXPp4)F^9_4;rX-rM5FlgHX1j(Dl3zs8`unqIA4{`?jsGuX|VsKE-0m6{?(urF@#&YeDfO zZVU?n+)*}%m+CQ`Yi+Fk8%k%CkX&h@6vZPb$Gh<;0~J3?M)tOqYQ>e#epQIlMG0Qi z=48M2Vf*&&RgA&9QvEP@kUR0jx1#p4vb<~y3k%NE_c|&IPRq{E&HG8?q~?hYi*EJO z6eufRD98)smzI`1UtU)(r+5|euF$89<0*QOu;?PVnyoIc*qys~Tv3cHoMJ^Dl+2tg zr<_n)BR~6E!a%I)35OqLPkyNLy7siVAro<_Bk~15#3U?A3jC4HPyG6ZBz!r59QW?s zb0vBjyLQdlfrE#fryovAGT>Q{nMqKqHEeZd#qLQaKw8MoiSYT|yZwZDUTHFib8?+F zRp95Jj_`{Eo+}$wyL<1h-MV$l70%u>l@@lC&NI_9R%By3kiJ85(GO6-sorADT3TaaWzBd%$gY%-A%hjc}_PFYUq?P!4tPm}V^tr-V;XK9@0gdIscVYn*Eejcn6m@(vv%U>VLN(YuN~MuXS*gfd1|w+t*5^PkcqM;Vp8KJ2vsdaHa0eF zZDZZmE9>sRF8fAhLyMNGZB%R4)P&86a9*6i1{o1NTatuR6fAz&th&OvrHw87Uu~=R z9Xeu%j~%yzN1yT&&K)-V{_Qy#BqvFYsHKnuHGzuWCQ5+?K{F^y zI$E@--aWTT@@}NvxX1A9remAyOVtzWI zNxM{KYkESX0?~ zz%~{cq$10y%U8~^&vxBXX*!0cI~Zsf9!TJkAVu%n+e-UU0Qnyv4-)Tj%g9)}J<%jd zhHJPIkj~X@5PLY4}NBYt^jNtoW~cf`Hm^Y3!A^27!)MI(1tY-PFAHL1xO{&rI66 zR>AIO%eGvawM?O?xlnO~82adCGPeKN$72b*JMChy$mJe46ge$O@~!a2BQGaxYV6aa z2-8Oy{i9^o##eJdQDu>9H&rHVOqdTfJ12uvUb0J4o7Y_VT)ts%&gSi8xnsMvS)9>0 zS#GN=T6HUkxH_XFJ{ex@%izf1#<%aX2Sqbup~hLUu4(fez7SS@X`qB$Uyo>#n=x}; zYk`Wws8sz=+cK-<=dD`YZR;{?Q%BAAJZrlSzHFJ?K9$XGE944RP@YkpciO5)l-yn_ z+rYL1jxok(7jy$BeX#0?3g`KWtW&?j88Ghnz?7K7!P=acfOE2RWo5arSNs{{IssB|G`ZG+^?OwK1&}_!3cYu4!OeKjaa2UcYc_aB@ydQH zDnvP9iBb^a7nhfm z4hO;F-pO3~jXYeLGBhnAwgl2xT3ocX^#D6T#J+V;hdjqJP5I2s%xdpZ_Ad@lD3e*fh(NJhR9KYbp^n07Y3g&Z zUrkTXsLuDgg1T28;p9=wOGLF=w^fzjhRP>iXTn|>x#ATYw1Z`(Lmx(F@&e#bp7|mI zr8+X-y?ZyLk(3Q}KQ}+;?E>Y0K6TAU1k0&fz2^D-@WT)7&Yj!NkFpYrK2U8VTE!3$ zS+w2YgGlYgcLGl}B{;FWV+4l$=%ake5fu0ZKLvi^zyXz$Hti|&XTPV33G9L|V&dZ` zoR{0SrbVFdC6mzUq}}Xi`kBXA;XK9@0XnMpy`(i_#~KyR=|;-*7{?#&Yy72hD3@2O zEnBNK-L7qz)wBVP_cOyMAnE$arZ1$_^}H{-<6au6E)+NDfotH~`%Ep^lC&8M-6b_B z#sM-8M*T^~VJ;vEY0HcEZ1LV*TUoqojfxf@*|yD=OSW& ziNz3a!EY*TTeX$R6>Wa+KHGcXkj?MeXOo)9UE$1?8lE4o(S(BC^OY(S5Zn^;5nzD* zCWLxPm49Lnq|d~Ig;QeF=3k4EM%E_ehoYHN&d`K*2`Hdh>!LW#Wt)~${)?)M?zErC z6UFM9Bo)(+j!!6DyeO;4zYr2NGyEhwYd7wg-M(wKvcXU8Gfw`ZO5>#+9hHyDPX#ww z&e)X73qn!P32}LKd81Q7shn0g*PESz6V5CU)xK!29+5Xd(|%=Dn4p)zPtUj|q-Y|P zXL#_TxJkMoxO)q5bnC<|@!_8q$hVsbJy zbToGWi5JVaTc8iXW=oJpVjTsNq_oglqI7QN*G1Y$=d}SVp0k>$k-4S$fcu+8oWiAy z6)%1<>+pe5{juJ(NzLKAvL$;XQ@3yK%GnoND;iH5@~$a#Rrywc5$ z!)iy=wFmgv?P2*4^}HSt625~#lp%?w$L5$n6u$AqYo0k~fE|iJ_As0Xw0go82t%$gcoIZez}7#A;I^zufDgao@sEG( zS30;tv|97SBzyPlwG+>tu-9IF-Ic`W&z-kZr%$_LlOik@!inOy-+9}fKK``r(w;S( zASeBP8F-?MKT;iWZ3$^nw$vf@%M}=3{pwepAE(TJ`O9DWDdt$mfGbuY!k+r%lz$0x z@9sTUCc}Hz>@Iui>8I@V*Wa+oiAnoJVSf3`U${(l$xM2bF?ICv%P+a&nd>X4Px76{ ztFOLh-}s$xSV{E|PngGj%pk5^yI~)E@PVB^b=np8)C0<9PBwGB$BAc7cpd-z=Rda# z7cRJho3=>4X*bWFc-Cb?(agzY^2QzP)F~!m-gx6p@p;B(cLhatAE?KqEZNg?l}7wB zB=)6r{{n;0!x1w(B-1+rX>BLH9-`c7q-Cb1(=M`FyM%mdyinhWzhoE^J;_B_!@13k z;7WhMj>6ebIJbHyobifDCq{4Y_&LE?;XK9@0XiyuFPafFPLx(@#4s$mHe^|oWvy#CkYE;Yv*UI-G{yucaD*RZcHl}{igiVsczzscn-RUyJVw# zurpBdE%wIxx@g6k)eYsZWo1ollf|6PPLyn_T(Swi(bQyug3qtiNUqZ0R5EWb<{ML# z%hg6O>zsnF)jbSX9{A{sqS+U2c^{aW0I@TfMrARw`5>$Cu9(ghY+`EKrZtgc7E5Jj zK=%uINGLV>ZYqyQiG;alCnmX7f<3VU5H(t5=|$}XWrOzq1v%yvj)Uu*&MnEI%x1yu ze9LWq?a7o({cl1{68^!mwTMp&Ty8!@R4;vxUmwJmFJ8T2cKaSWAx*(5hjxysSZz|o zivrmYpm0XXJgI^~;f$hQO)f0d1eytl6H%hTGp%q&kHR1yXzJnU?y4 z`d?wy8if_nqUfU43m2@Ox#P;_HcDsBC2*zhq!rFQ`&_RMJ*|cM?)-$koom`Zo6g$1 z^+k=Rb%oca*=h=mW?7pdj~Nus86u-(Rp+m_Q8;hdg6735ooTz=nX->+Sv#GZuuBuO zlCh*Qg*%-USJ7Ms{m0z)avf~FXW3I_;MFmB$&6l)=o8I)~ zGF!_|S+zK0)!Z)2mJi#+>@#+7-wU=+_FdV%R?PC#ROL-;55GI#*8|%G1v17MpL4`9 z0*i)@N2YKd>|WhL9N|UPB98^1`0a({Pkb| zwJQcuK)Rw^`=qCze%kpw_0&_YF#Ptnzisco|9+ps8NY9Q;~Re0^L7-@r1SUR`Fp#0 z>t>iswMgcK?`yBVYG42Q*KJC&fBeZO_7{Kg7k)C9GKnvH{OAATU)aC=U;Y;l-z^+3 zS5~var~*sD_dg=;9Oi0@KmULJ+&=pFBfnmP)50k2P~LK#$?tySckRmMtM=1>{Hguq zCqH)ixz2=_|IO{1lRW?2UVHsD+karcCmrfbC``>q^b8yz)L1oC5 zCI9I^{U<-Yedf#=`3D&Yn8_4NB?rZnQ{oB&^u#+?c2J;c+4yOFn1_=>EjY=W9hj3Aa3?Dv& zYuK-k70#ougB9TzV>~{@4o|mq<&$Z$a%zXW4%I``n>p=kz1MEk&F*c8svTRZb!=4~ z9a^ckZMELAb#3C}^&0C6yI$|uTCHtsn1qpiwbt4;tw7>CNXsc&sy8KzCg57bX(2He zs|{POHl0@F@4RHXTSb0plE6!e9W&ChGQ3o&%RQKjio3wc?zT3G#cAtI@3GAMA+xzd z)|lCAYlRuR(<<1ts@bLWwq4rj*!k6tom=bJg^i3|tmf=;y?P<{od)pS*TTV;sl4V16C0Y@mRS_q3*TgH3>Qgc=Dh~^4 zUkhpr3tFJu(?aIXdev^NRqd|QUX8zNq|6_hsN&QC2g)hV1p zbKgWy8j#8Ru|7~Z$GJYy16fUZN52t5@tN^S2*rF}fl)YX-ROrMaZ92HBpGJX?ve_| z6~-)-pu`>Y;-+j^@h2P(NmvJN$@8WqNcfLWU2=DS2=z4xcXj_X@sR@0eg0|UV>nna zZ6bG%QHS`aDTa+S_^gjWgYId+LF$D`Be>zu>4{XJ7%tlT{C+dkmG3dYSr7gtX>O0Y zV#274@SO5|RCFK29@1~BBW5(7WvXFZW3o;HupsY#i3YHf4hl~;`PzJA5`oPs*EDb^ za#nLjMgvGzb2fGjlOpv}nUR9LDkCir+Un@6B>0;YyFD6nb}Rm5qn;>uYf3Xw1IKtt zo}(Gay@JfqE@Kez;jbk@8XCuIxrWB}rsQC-Yii9Rxs}J9i2I!-q>|5QEJP`+jc_Js zllhYE5uGSb*xM7+_S?H=?YE{2_GZ3f$J%Q)?_Z&7GuYB%MjPl(Q~aTp^1&cTvB6jT z{R=rr18+lqT{GHMUctnzZCtOxmv?o^Qt#xfsx`w#qhNPsUQnvE7*0iR7nO~Q-CMY4H*egqt4TVy#cxsRGnXO@vXcj7LHT<9 z`VE(fYaqOFJOVJ!GH)*}FG&{V`RX;#*NvMu?CzbrelIrut(bKYU zZbweaCR`_hT$^R1{W0GWj`DLpBJxH4P;@twFA6AQ$}^TNL|9}b42nq7ynW}kUB7nS z{bIdyDw;6JOqd&TzoPipZ(R5M5svF7NvEMT1+v8Q?a_7TL%Rz5iLHUMo4V(vo{<-I zN_wRSndOs~LfxTbbF48Q1xAmYV~p`Bf{yN_p5E5(uB}ZfgeyY= zehia-eMZh~wP3bbG`pc77b67z4qmL&aO7|cD-G) zo2K&0P1(KTtSy#z+497^txWE=)yX}!HnrE*XZBfTcE43-_S=T+>(hH}RbiGDc8NH} z8K-+nZ^3EWmP#|WB3jb(y-Z1UkyRPCC2zwnu2${B%DP=x7GXwOT@$U_`IS|-pNCc= ztp@kRey&R^1GH@CmJ@Rubbf%MTfhHG*Z;gG{vNF;FCxitNsG5jn(#3%XhCynZAJA_ zvD<2QH&n;hDys91n%$_j>{i`WPiD(%yH&O4h8D0*O@1wz;Z&F$)e)HVTp6pz?-YET zo@huw=J~k)@P4h2RueNw@9O}$p(ug)p&xhUai_H_n<2u4;5}Y4S&urY{G4RxheE@1fP6p;90w?k!RPw})*(ZR z+okB1rnLWH7=5Ikoo5Q}?C!mC8vYzfJLGt*J0gd_W zW?OSS{Tudyl&+KPxD!qAX08tGql)Ay%WF=&=QK~xX!AFrxwfb|IIncl%5QSPqqoT+ ze~GUsgiXVrlgi+Fij30pQ^#6^VDgKjY^Q12cGGe){r+ah!+8j^1n`1qld)O$@Ul3*Tx`3d z59K3%fD^g+5e|10hA0%bQV0%$)2;mcA0DK^9EzPZkb`S0;7R^D9ScRcOg`6cAMp$0 zNbUw{?&4|;$_OIgD+k`Y-c^Kh>*ig7P<&GncHG7|hUH{>VOQOqm+u>|cYFV|C0ZiIy&FC2tVOgBw_ zDw;Ot(rgXxSdLd@P=1_FMi|mU7EXji2GZSNtymb@Qg341?E?4JjWmxN`zssv>!nru z_2RO9u(WKStghN=P2gwNWUj8bd3Jrx&TXvQxypvj4Le(@*f~vJ+okiEmCf#(+_a&+ zpb6rlCZda)Y`Uap+%L%gycRozJx^F|elH|pFKN(A(?v)Fex&GrIiV|xb4BJg(RB@$ zm{(AESL=4Ursr11ZgdJx*E>bK+RodRR!%0Aw`-!S?Sh*(tYo*c6Lu#*WecSlTb`V= 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

Zp;niK><;p<|EWK^^|epROD$( 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.oH%ahXVG|WJYb2q_FC|7lOzTZ9=E~_?r5O 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�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

O7=0ZXK0-4Mn4^ib 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�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 z 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%0D<9RW;4l~}+DypHsM)qX(p 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 z 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 YNW`#_qQ)9oOYd#gb1Igt6#sB~S literal 0 HcmV?d00001 diff --git a/tests/PhpWordTests/_files/documents/docCzech.doc b/tests/PhpWordTests/_files/documents/docCzech.doc new file mode 100644 index 0000000000000000000000000000000000000000..8def81b13e7a31deace04e6f9c71b2db41091f64 GIT binary patch literal 10752 zcmeI2TWp-g6~|}n-Suv+YsaJ^F=S)5P8z`24gtHg)Hi~&!LgGR(r|Isi8sWJy=xq! z(mqsfyH)$pN&y~tL26p1Ql(Z^xV#fplqaf2NJv4IDv)?VEs~*qNlWbh{`2i;uP^Ie zJBT*T&g%co_syI+bLPyMnKLtc`Onqw|MHcsAD9K<0aIzFXCfw)mu`8l@xP6w`sKbhBZxPdfqEhnq`FhC~;f%?1(gh2$X0c*iJupVpx8v!O@s)5RG%EdQO)61fw zfx{-lZ^FdPLnci;ZoW%TmL4`^G5LxtrDXnmQ3`!AnsWVf8YreK<>%|)pTDnX{A*3n z_^$=GfX(1bU<nL4z`0B*a7On9Uuv^runT+z>;`v&yTIL`5!?fs zfaGo=-UIFhdvj^`6Ssmk@Kx{t_!{^+co2L8w1W=N3A#WxcnItR4}%`CA0)s5@CfJy z2SFd`2Zz96a0Gl4JPIBIN5QwiG4MEe0z3(x0t4VUNPG0@I`fGeEfMVNDE58OJWI=(&G+0` z&`1)Ewe>JrOe4vBn(6{H8cROSjsi3qYd%eL0UC`(pQfV#jmD}^bEp8#eR(v41!y$Z zeLl|=pwV2Qkv+ZLnis4_c-4ZQlW((SwqrtZ%U53_glUB6qdI2}o*C3J({x6~N3D!7 z?o;MDw}y6NYeQ}YjWYAq48^R4BQxWLpFtTj_e7t!zp^pj1I#AF<}9T&0Jicykf<{4 zrXIep+ICW_n3D$07!<>B)tFz;EV>D!k>RXEz8Yt;_l2#B$~vD4+XmOdKM>28+fTV6 zC!N0PTq&=n#~j@|R&!M~Gub#)r)EdW1hu9p8JlgJyujOXZPCo$mk6VoFcQ?FnF!K{ z5uw(!mB zmY=ulnAy1SmrGX(FZdIJb5#ej7i}`zKYhzvLGgf@IL&Tc^5-EO+ktF*MKXKonxk&7 zC`x@9>L!o+a&hWpWiosIGsinwS(Nt_)KQOmsyOvzAeo)~x8pq-D9Sq;OlGJ4<*1{< zqSWW1PI}bmi&Hm+lG)2w9q*=4j<tA#*=X)k={>|-eoUfL0c^C(Mn#w{Ov8cM6Zg8?<1TXKe} z$yOJx!OzizZ~{rkDd!LR7>sDSkd*93wPl{mxuQrb4avG_N@)+M6f?=10z8=cjsS8kALy$)xOiw-##BUckX=cJ;^2yS7%7d9|J0h8_a2=F
zJO{MyzYJu!zX4U?b%0A?E&-iOy$#s9m@7bj{fA&3m;$QfGa&vSUGw&ws#8Jx&(G^! z{N?MkgUR&cT}19(u|hkj`^#Uex&rSwukQZD?%r8scF{d z!B-m0j0~n*y;P4P_lyKKo0h!EreR+0;*Xh`jZUwsT<_AY|Gtp=r!L`5bqm3dy|1O8 zqN!avYsu6r(5tsT%*8&@$8`O))OwxaZRa|!oXOuXu@iaqUxANKHOgUi8knMgHR67U z9$CBo>)}o0&@AEy*@^7%iw+g$y)U}Ta(!hDlr``_rGb8P%zn%^i_M~qneW>Xwgf4w z&Bc0q##}QoPJT1ChrBVfjog^oXg_e<#1Xa*XUs>W{KK6&$>S-98%_f(MLOpyhnrFZ z)<4_4dQ&$4rfhWZ*10tmjb`zg;lBAG8x1yzmt*dCi k?v(v=v*4ndSEi5FRn)Hwgwk7BTo10}bC2TG^Z)MLw3fJ zHA|8`yAd*&WYGWfeV(4_x@wsD&2Rp{<(^*e=bYy}XM4Wqd(QJc&vMH?U;WOCt)}@* z#kFUe>|==@(@}~SA>3BjH)PBeVT$`$Qc^{MOGsxto({v*bCkMZVWKiTMM88hqpjMZs;a1il8Sy?_w$?ueuRQoNqqOg$Q z2QFY=iQgxGgApJ8J-;*wmykMv0tZSX%k%Yd{1lGYQ%W}pXJiYteps6COMXr*s)aFC z|AHA~8i>CHpWN5@mPog)0b{$6F~owgA=ocM{?1f@iWB4@)T?s%v-Sw-1fR-Pc0zfA zFPyiKhW1}zryb;D41aNHepR2!w}2+7mZQ2)@=NOCBqE4zS z616B0N4Y39wJ8drNVGxDJVg>Nl?1*N$D(jlXpaNh)tq(0m6UInJ=!HMr)AyPD6VY* zTua1^_GM^uOGfRJBaZ@%Kv==T*)trYw#bo+S{KW{!x>RnsMi@SYR%Q%3uWYiT08H1R<7=QZGb8XZW^> z(E{o(8P_T?*FHIpJwpj)5>jrBJz7Rm*(4@C?8EhRB=V{1CFu{v$~lPza3zy2gdzS3 zN+(IsKDCzOMxmrvXve2=_*_SW%hl2VrmsmQ1~HMQFb4dwM`ss;(j^!_G)iK*;|fkD z8k!2U!k^Q}K-8~5T3%mCOU9tY-_unZKcuf^I`d_HeTH+TQS=O@)0y+SDn;vPRFR&N zUQ#bne^cAb;%RKj(e5Ce1*Lydnu_El;m(X7>3nZejG&`|ND+b5f^Mm{TdnI~r|Z3- zp)|V%Lf)Uw!JQy$e!NrP(Kru+#E}ZKBE`@Me`6uBs# z^zHL;^BrdPigk@2BMz89`1z|FCmA{BWSR{kArF2IqiqE0peqS4Q@Ya7Y(`^3m_bQq zg8qLxZ}2mg^3~)&SIcRg&#m~eq&tZf3a$CyzkC17zrW?8Zs8x5fR1s{;^G=Wy;{CbGjhre?0?o2Q=Jqoq+()Y)RpnDE7 z&aUQd`ARL~r21uM`FvR#(z&i{J8){tF)@D}Joo^?Q9@Eu47sUQO!0(75v0=NST0Zl1}Kn!ew8&Dtn z`{W`4(owubdh*UNAD9e zhSzskjX+J2h#9R;#fbIrGUm#Yz^5{m%R^En*NJr$|6H;H?_lefKCCjtcSN1=Byc#& zrf2{3zBavcOz#c`bK3~KUn^!^xTlO!Tv>j2;`yp%JM;Uk6k8pA)*CteQ35^H|FpgJ zSZ$g{9IxmwQDsdjAJ9gOgrYSVUQ@y|@-Xr1lEd)v>LurFbt-Y?&>Qff+3q z-)@>(Mvx0#AFwqLj5>=|8)-uzXtgo55+foqh5)_f4E=TBn^Pt=gj3nFsbYb)Gh%YvK~Ww6PB( zg1xu7&Q6YOki7chyVe?~TSYgX@L@vLv!i<6sPi;&PV0MF9=Q)RcV(FMcYXe#c#-AZ zF&jhn^1>o3wm*u0e5ry*y094;{$_NK$*nwQSR4UB_C zN=l%0pU5li%GyVVASWjg<77WHGDxbhv8HW&()kfbZS|+Un6iKJh4DQv9<9?T+9oa8 z!)DcZmftik#G>x?x=*kBoY1MfS2uq3i=y?eAGgdX&j0?A*m%hXouhX>I-Cy4k9Iv6 zHz{k%>a~q@2gXE9T{ZUl&Y}B!FRW^J)~;@v=Puj%HL4}#`Rw!C;vRS*%kZLC=j)FC zmT_z6j2xQVV9_#@J5Ju0-WdDkIuF~Dv@WY;`%&97%X|*UrCUAdtR-{)-aGWZ|B7`s z_j>J5UKh0Ca{cU`yNj=Uz^QzGqG7QMj3?tnrvv)DFe)S{Jjh0A+g&1)1P4WuhUlN^ zUiqll&@F%biqXk=&H;OycJ|+PdduElm`93f#}la+mtW6)aBs5nx!XoLOS>5iuu7?9 zFg@t3b;1vYx^&uJ-$@b>~80$EgDzWXkC8eH~2NWeH>TL8F*WJBf_5G33q|I5g9lJQ(nx!{!Zad@3X`xR% zG{-;n2(9axYV#yL&nd0DdEAQ8U3Rq#NZPx!(Ui16gBgx4MduceO+RPWbz%CAq;-n; znmzj8h?udk@|MZ>%=ZZLZGp0PniN2^({GOK=9x9zY7 zugoq-c$lwgTimX}5!<^9uNs|*2tPAdSFd&V#>G7+%|0ye^eWAL#oQ#r#KBFvRNuYd zuKqmp=yw;>_U?_kwIaf_igl%_j!(MgUd`~mdO_0D;%!PL$C0xQ!*|=BPcSQbIX>UT zXr!pNsjTCNJ;gUq$L`o}yV8Hg=Ha=0;;QVOa`WAKqCrka#zuNER@G714mfm&A z>5wPn3T2+$PtoF^dw>SK7?W4xVi5ER)yola8*xEGaY+USQ#ifNEG}GPI$H_Hs zKhrVnjBvACw-1dSvePI=XUIgqaY33xTRL7Jl5?nquV>eByC+(|ogbMoC|t+HAv1VN z?)db9EnB9f`}!IT7?suRxRvqs5iQ+|`d`$Zpyg-jS&&d{lyt#xLu|9)WyAG7rdsb(`B!?LO@Dx77Wbt3<0ym#lLAL{JOG`)ZJbc5Ub z#ywAIH)iC|j~C86k>peVLyC+2reA#9UD!M%uH@KlpAMrwj`?`=X_KLOF9)3{`FJV# z;D>iOYgXB}ICWyx7xQ!#k6hYE%eLwouW=t{e`50e zXIAgbEiyYhEQ>H|*k;DDxNqWh-o2~WGw|@v43ooc^*m=9#EgnQFTPP_-eR$FQtpwH ztiElRfmU0){BqWiG$hbDk~aZzag4F>wWa_UfF&96(;dlQ)B0??4PPP zduzn~R?!JtgGP8;4&g<)*fShtr~qHddC^(=ZaBBJj1eb(-1ZWtT1pnqg+Er(U#ja9gG>EG2r z_uz_0)f0Vc6}1{rR5EZtCG+ubp7lDt!Fofgb4~yKtA4o>IIga2@IK82Gfy7NeeSg6 zn6upt>!k(-`=bsnloiF<+`Rt$(P*2iEoSKyFBo_%YU38C=NGPw|8bc>Q4K)$5cK28eZ&>2emYQuqw29{d$QxF^A6|&+qB6`mxujH@XY<^piIEsb_3g zw`&Is^uq1ub;@&JnOX1qj(*i18ah_d+qrG@k(Dw@&w0-muD>=+ba~sRLszmU8uUB* z#?@BTFlME@QBvTti@j~OZ=73f?XbV)qAuEp+WQX>ZS>ARblu?mCer`Oy91~&^S zsONmcD{tCdla--I&5j0isMn>}Iy37Z_9gVVb2HD^@`*uQ{h-B-2kod{?b3u67rN$% zEi{@`ZPfGV{L|+zx&@?}Pan8dYf^+HE2m>$YtuHKnTrG4)xWnQ`_h(KCq37$O)XsC zw|{!`SFa|gHCoy+b8PQ%an-IRXHpxR$WLWlE;zO>ukC^=?WSBCuq1xXyZLF?ckT{yJ>p`f zzii{H$v4O39LbK^liqty-`lRQeQHW0s{Odiz-D4_?}+(cZwr&fR}J4>US>JpV0Y)| zGmdQ*eRIyr+@PrAVfmPjS=Az^EV-Q(8ncJCXLpW%P(ab&S`uzA$#*>&G`GR44gVx_AGd2u*FK(dYa_G;?TVd z|B+QQ!2Xt9$OcngmnZW_E;$^&yI{7PpK*`GytaWE!zRs^J3p%xJf~aJ?u{+|np)c} zimckiYhFtB^xnl2wzOWA)c3x{sx=)??#=cr8Z|!k@#w?O4xpGWf z-)^54plaQf<)&X$P_p$@GpbrkWf@IiMt){~D2ZRSBvsR;tfVXDmBbk`s%5AuL0K8u z^ht!0CHFfj;oD6c78HFCt<47G>`&th3A`)U0fv(}Iw(>RDwnxh*jd|Jh=XJS^1x78 zu&YI%-d$R@wh$|#B(gw>R4xm0wTKN;SafJ_P`RDNB|sY4T@oQi0WyV)#ML4sDk{Ro z#zql<21yjw@`xZAjt!SbhD)Nb8yRd97%3Tzg2SaY_O`Z8HsO*`nT6Ot*v{2L8f9l8 zj*3AjFbpC8V0((Qr#OTH!w`}L1YjY96r}+n2FLlB-_ke;F%Ci+Mhh-oFnv=U;R zgcv6aafmcj7KSq-&q6$0F7@Oigph?zdy*dg!blCq@CykB+%L`0B8rm@tM96$-s64bv&4yG$Bb??M}J-?I$bZ^)_?(kgH2VQknjZtKSCzog|b z|7#*8Y{G;Itcbpus>U=5=i-1N(=DV1aD}1ZYD}|`e#oI3(<*Gr#p@ORww}hm;51le zE+4&)r;SKT?+(94X}k#W)cRg%6#XW|K~!MKPE$3ECNEv4rAa5*K~u!lUA>SpaEIaJ zlsVHK-&`=fyUAe5GyJj$maP25))u}8=mdHIAJ7N%1H*s>gaCXbg5@{F3X;Hlum~&# zX2o{5-AO)-i>p=$C26lrz-~c!Tj)6PiA$SCyf)}6&yaSrh0d1fU41f_Z1`R+v z-~l=TZ{P#^f&M@O{6QF?8{OkTJeURk0ak-Fun}wm+rW?D6u1C#!Bs#v#qz-uPyk+n zSKvLseHo^UTNW0e8E6jdfIV;mE`V;Vc>r(F1M~)czyKfvv0x0C2;#v^Fbm8F>0lT5 z0UQKJz$tJVTn0Jd7I*?)fFeMeYY1wCI-ovi02%>j&>nOKKAa0Xlik3c2d ziBO}K0spI7Eiiyv0tFZa(!q963_bv1rgp>3*a^@ht8QRChyz*RENFt6sTq(11rTPy zT?l7_1K=>w$BaRb0S1GiU@`ayxC`iUk1(?|!zgYE?0_TK0JeZvpa{5P6mRH#Xgxt)N*okyae4vK5qb#FYH4kzc~#zAxLS_IjpokDlVC?m3+=-h0opk zhEK*6#nVkeSVWY$63hnrnxDSq8I3K)k~t(eJ{6^=ib}00r7$(?oBGM3=S)LGM^jr% zTSHT;#G2h17{d;cc|(q?2!3zeji+yi=v$^9@JGYu%E))r}qD(Prw z^LkEJQ<=nE#s9IUz8tLSKHkgKrvj(8?PzqvqpocTP}v?+rom*@Ui z%g) zgt`E~-FIXyL1F4l^a|qXawI&@*G#4^{4|#9RK%KVGR{EdilWSF_Xi}9sGX?2gY94w zC)(S7n(Z#e67kPCzBjoNx=pT5{iMs@(@p#Govx=Z9ndSpPc7w>c4kdF{tYUwOP&(+A?0My!&60F-kaRy2wSBz(lG=e2qZqV1T zzjy4DLex9|qy#=tp$m){KFvi|@aX|8y=y=h8ZtVn!S{ww zb<%Q>p0N&sFF2~7betB*f>wTQnCk37cT1$!f%2$ut_-TjPaZCjiM{ZAZbVQt_J#6j zj8M1^=pGsnDObpcM~Qug4-X9p68Dow1|r@K2+oZHg_XVN*C3U{Br5@$ktxj2)d;}R zetGfSLG?y00ks6w5>QJ(EdjLz)DlojKrI2a1k@5xOF%7wKOuqNTmNh1oXttGu4_1N zA=dv^#anDq{$oJvW?F)W09v0%09yBt1GMgs2i3t$K#!ll2XsFu1HK29;CO|im zcK}-V)BOS}I}4PzuBUY|9T(QlP)k590ks6w5>QJ(EdjLz)DlojKrI2a1paFzK#N^k2Gbgvo}be? zo|eP(+@7A<)AM?IMo(*MT6@zvou19px}W~Zf*mO=h|WCA<@8r}WzaUz1lgO;yw{LL`luudScn z9})h0V?Rhg68}Gd{>xJUUc;rg8>t_@)|sMy5+#k>udScTrvKYZP8;t+Qmym`CG~w* z)IOYR6U9W~okjYE_ljN9KOui=FTKk{PW!Vn|6}cGjrwWcqH`z575aq@y~iW;zX%_} z(EFni_yESA``G0RnN<$gfFkoX^IMg}74Ak>c;t^C_%rnjwNN+ETv*=xubv~7CHvnQ z7NPewae=3^Q=PlT(2cV9+~@^2aU18B_>#~;+({lVDjZ)2a<)PDUUUpm+@PYcwQ$_J zHGAD=+eks%KKFm``9pc{A6i0T$^Ia{O#n2PBm>f4dcHvO;5tC_F+EoxJLV7|JLWPV zTjmZRTc!YzJ@Xb&nOZ26>>7Rebd4~APj*c`s!YXEy?^Cg< literal 0 HcmV?d00001 From 8392134ce4b5dba65130ba956231a1602b848b7f Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Fri, 30 Aug 2024 20:03:42 +0200 Subject: [PATCH 210/246] Word2007 Writer: Added support for multiples comment for the same text (#2665) * Adds support for multiple comments on the same text object. * Fix method name. * Fixed some feedbacks --------- Co-authored-by: Rodrigo Queipo --- docs/changes/1.x/1.3.0.md | 1 + samples/Sample_37_Comments.php | 17 +++- src/PhpWord/Collection/AbstractCollection.php | 28 +++--- src/PhpWord/Collection/Bookmarks.php | 3 + src/PhpWord/Collection/Charts.php | 3 + src/PhpWord/Collection/Comments.php | 3 + src/PhpWord/Collection/Endnotes.php | 3 + src/PhpWord/Collection/Footnotes.php | 3 + src/PhpWord/Collection/Titles.php | 3 + src/PhpWord/Element/AbstractElement.php | 90 +++++++++++++++---- src/PhpWord/Element/Comment.php | 8 +- src/PhpWord/PhpWord.php | 1 - src/PhpWord/Writer/Word2007.php | 2 - .../Word2007/Element/AbstractElement.php | 49 +++++----- tests/PhpWordTests/Element/CommentTest.php | 34 +++++++ 15 files changed, 174 insertions(+), 74 deletions(-) diff --git a/docs/changes/1.x/1.3.0.md b/docs/changes/1.x/1.3.0.md index a843c80bb1..a52e16e339 100644 --- a/docs/changes/1.x/1.3.0.md +++ b/docs/changes/1.x/1.3.0.md @@ -12,6 +12,7 @@ - RTF Writer : Support for Table Border Style fixing [#345](https://github.com/PHPOffice/PHPWord/issues/345) by [@Progi1984](https://github.com/Progi1984) in [#2656](https://github.com/PHPOffice/PHPWord/pull/2656) - Word2007 Reader: Support the page break () by [@stanolacko](https://github.com/stanolacko) in [#2662](https://github.com/PHPOffice/PHPWord/pull/2662) - MsDoc Reader: Support for UTF-8 characters by [@Progi1984] fixing [#881](https://github.com/PHPOffice/PHPWord/issues/881), [#1454](https://github.com/PHPOffice/PHPWord/issues/1454), [#1817](https://github.com/PHPOffice/PHPWord/issues/1817), [#1927](https://github.com/PHPOffice/PHPWord/issues/1927), [#2383](https://github.com/PHPOffice/PHPWord/issues/2383), [#2565](https://github.com/PHPOffice/PHPWord/issues/2565) in [#2664](https://github.com/PHPOffice/PHPWord/pull/2664) +- Word2007 Writer: Added support for multiples comment for the same text by [@rodrigoq](https://github.com/rodrigoq) fixing [#2109](https://github.com/PHPOffice/PHPWord/issues/2109) in [#2665](https://github.com/PHPOffice/PHPWord/pull/2665) ### Bug fixes diff --git a/samples/Sample_37_Comments.php b/samples/Sample_37_Comments.php index 79647478e8..8254f35c6d 100644 --- a/samples/Sample_37_Comments.php +++ b/samples/Sample_37_Comments.php @@ -42,7 +42,7 @@ $imageComment->addText('Hey, Mars does look '); $imageComment->addText('red', ['color' => 'FF0000']); $phpWord->addComment($commentOnImage); -$image = $section->addImage('resources/_mars.jpg'); +$image = $section->addImage(__DIR__ . '/resources/_mars.jpg'); $image->setCommentRangeStart($commentOnImage); $section->addTextBreak(2); @@ -56,6 +56,21 @@ $comment1->setEndElement($anotherText); $phpWord->addComment($comment1); +// We can also do things the other way round, link the comment to the element +$lastText = $section->addText('with a last text and two comments'); + +$comment1 = new \PhpOffice\PhpWord\Element\Comment('Authors name', new \DateTime(), 'my_initials'); +$comment1->addText('Comment 1', ['bold' => true]); +$comment1->setStartElement($lastText); +$comment1->setEndElement($lastText); +$phpWord->addComment($comment1); + +$comment2 = new \PhpOffice\PhpWord\Element\Comment('Authors name', new \DateTime(), 'my_initials'); +$comment2->addText('Comment 2', ['bold' => true]); +$comment2->setStartElement($lastText); +$comment2->setEndElement($lastText); +$phpWord->addComment($comment2); + // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); if (!CLI) { diff --git a/src/PhpWord/Collection/AbstractCollection.php b/src/PhpWord/Collection/AbstractCollection.php index 78b5b891b8..646489d886 100644 --- a/src/PhpWord/Collection/AbstractCollection.php +++ b/src/PhpWord/Collection/AbstractCollection.php @@ -21,22 +21,23 @@ * Collection abstract class. * * @since 0.10.0 + * @template T */ abstract class AbstractCollection { /** * Items. * - * @var \PhpOffice\PhpWord\Element\AbstractContainer[] + * @var T[] */ private $items = []; /** * Get items. * - * @return \PhpOffice\PhpWord\Element\AbstractContainer[] + * @return T[] */ - public function getItems() + public function getItems(): array { return $this->items; } @@ -44,11 +45,9 @@ public function getItems() /** * Get item by index. * - * @param int $index - * - * @return ?\PhpOffice\PhpWord\Element\AbstractContainer + * @return ?T */ - public function getItem($index) + public function getItem(int $index) { if (array_key_exists($index, $this->items)) { return $this->items[$index]; @@ -60,10 +59,9 @@ public function getItem($index) /** * Set item. * - * @param int $index - * @param ?\PhpOffice\PhpWord\Element\AbstractContainer $item + * @param ?T $item */ - public function setItem($index, $item): void + public function setItem(int $index, $item): void { if (array_key_exists($index, $this->items)) { $this->items[$index] = $item; @@ -73,11 +71,9 @@ public function setItem($index, $item): void /** * Add new item. * - * @param \PhpOffice\PhpWord\Element\AbstractContainer $item - * - * @return int + * @param T $item */ - public function addItem($item) + public function addItem($item): int { $index = $this->countItems(); $this->items[$index] = $item; @@ -87,10 +83,8 @@ public function addItem($item) /** * Get item count. - * - * @return int */ - public function countItems() + public function countItems(): int { return count($this->items); } diff --git a/src/PhpWord/Collection/Bookmarks.php b/src/PhpWord/Collection/Bookmarks.php index e7d9b4a384..71544c9469 100644 --- a/src/PhpWord/Collection/Bookmarks.php +++ b/src/PhpWord/Collection/Bookmarks.php @@ -17,10 +17,13 @@ namespace PhpOffice\PhpWord\Collection; +use PhpOffice\PhpWord\Element\Bookmark; + /** * Bookmarks collection. * * @since 0.12.0 + * @extends AbstractCollection */ class Bookmarks extends AbstractCollection { diff --git a/src/PhpWord/Collection/Charts.php b/src/PhpWord/Collection/Charts.php index bb63a13962..7c2dfbab94 100644 --- a/src/PhpWord/Collection/Charts.php +++ b/src/PhpWord/Collection/Charts.php @@ -17,10 +17,13 @@ namespace PhpOffice\PhpWord\Collection; +use PhpOffice\PhpWord\Element\Chart; + /** * Charts collection. * * @since 0.12.0 + * @extends AbstractCollection */ class Charts extends AbstractCollection { diff --git a/src/PhpWord/Collection/Comments.php b/src/PhpWord/Collection/Comments.php index 8c6b577d7e..5fa4020a5a 100644 --- a/src/PhpWord/Collection/Comments.php +++ b/src/PhpWord/Collection/Comments.php @@ -17,10 +17,13 @@ namespace PhpOffice\PhpWord\Collection; +use PhpOffice\PhpWord\Element\Comment; + /** * Comments collection. * * @since 0.12.0 + * @extends AbstractCollection */ class Comments extends AbstractCollection { diff --git a/src/PhpWord/Collection/Endnotes.php b/src/PhpWord/Collection/Endnotes.php index 362b25881d..09903b1bf6 100644 --- a/src/PhpWord/Collection/Endnotes.php +++ b/src/PhpWord/Collection/Endnotes.php @@ -17,10 +17,13 @@ namespace PhpOffice\PhpWord\Collection; +use PhpOffice\PhpWord\Element\Endnote; + /** * Endnotes collection. * * @since 0.10.0 + * @extends AbstractCollection */ class Endnotes extends AbstractCollection { diff --git a/src/PhpWord/Collection/Footnotes.php b/src/PhpWord/Collection/Footnotes.php index 76eae3eab3..0387fce3c7 100644 --- a/src/PhpWord/Collection/Footnotes.php +++ b/src/PhpWord/Collection/Footnotes.php @@ -17,10 +17,13 @@ namespace PhpOffice\PhpWord\Collection; +use PhpOffice\PhpWord\Element\Footnote; + /** * Footnotes collection. * * @since 0.10.0 + * @extends AbstractCollection */ class Footnotes extends AbstractCollection { diff --git a/src/PhpWord/Collection/Titles.php b/src/PhpWord/Collection/Titles.php index 7b795771e8..543aabda1d 100644 --- a/src/PhpWord/Collection/Titles.php +++ b/src/PhpWord/Collection/Titles.php @@ -17,10 +17,13 @@ namespace PhpOffice\PhpWord\Collection; +use PhpOffice\PhpWord\Element\Title; + /** * Titles collection. * * @since 0.10.0 + * @extends AbstractCollection */ class Titles extends AbstractCollection { diff --git a/src/PhpWord/Element/AbstractElement.php b/src/PhpWord/Element/AbstractElement.php index 9f9c2e82aa..385e4d3140 100644 --- a/src/PhpWord/Element/AbstractElement.php +++ b/src/PhpWord/Element/AbstractElement.php @@ -19,8 +19,10 @@ use DateTime; use InvalidArgumentException; +use PhpOffice\PhpWord\Collection\Comments; use PhpOffice\PhpWord\Media; use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Style; /** * Element abstract class. @@ -32,7 +34,7 @@ abstract class AbstractElement /** * PhpWord object. * - * @var ?\PhpOffice\PhpWord\PhpWord + * @var ?PhpWord */ protected $phpWord; @@ -131,25 +133,25 @@ abstract class AbstractElement protected $collectionRelation = false; /** - * The start position for the linked comment. + * The start position for the linked comments. * - * @var Comment + * @var Comments */ - protected $commentRangeStart; + protected $commentsRangeStart; /** - * The end position for the linked comment. + * The end position for the linked comments. * - * @var Comment + * @var Comments */ - protected $commentRangeEnd; + protected $commentsRangeEnd; /** * Get PhpWord. * - * @return ?\PhpOffice\PhpWord\PhpWord + * @return ?PhpWord */ - public function getPhpWord() + public function getPhpWord(): ?PhpWord { return $this->phpWord; } @@ -287,14 +289,28 @@ public function getNestedLevel() return $this->nestedLevel; } + /** + * Get comments start. + * + * @return Comments + */ + public function getCommentsRangeStart(): ?Comments + { + return $this->commentsRangeStart; + } + /** * Get comment start. * * @return Comment */ - public function getCommentRangeStart() + public function getCommentRangeStart(): ?Comment { - return $this->commentRangeStart; + if ($this->commentsRangeStart != null) { + return $this->commentsRangeStart->getItem($this->commentsRangeStart->countItems()); + } + + return null; } /** @@ -305,8 +321,30 @@ public function setCommentRangeStart(Comment $value): void if ($this instanceof Comment) { throw new InvalidArgumentException('Cannot set a Comment on a Comment'); } - $this->commentRangeStart = $value; - $this->commentRangeStart->setStartElement($this); + if ($this->commentsRangeStart == null) { + $this->commentsRangeStart = new Comments(); + } + // Set ID early to avoid duplicates. + if ($value->getElementId() == null) { + $value->setElementId(); + } + foreach ($this->commentsRangeStart->getItems() as $comment) { + if ($value->getElementId() == $comment->getElementId()) { + return; + } + } + $idxItem = $this->commentsRangeStart->addItem($value); + $this->commentsRangeStart->getItem($idxItem)->setStartElement($this); + } + + /** + * Get comments end. + * + * @return Comments + */ + public function getCommentsRangeEnd(): ?Comments + { + return $this->commentsRangeEnd; } /** @@ -314,9 +352,13 @@ public function setCommentRangeStart(Comment $value): void * * @return Comment */ - public function getCommentRangeEnd() + public function getCommentRangeEnd(): ?Comment { - return $this->commentRangeEnd; + if ($this->commentsRangeEnd != null) { + return $this->commentsRangeEnd->getItem($this->commentsRangeEnd->countItems()); + } + + return null; } /** @@ -327,8 +369,20 @@ public function setCommentRangeEnd(Comment $value): void if ($this instanceof Comment) { throw new InvalidArgumentException('Cannot set a Comment on a Comment'); } - $this->commentRangeEnd = $value; - $this->commentRangeEnd->setEndElement($this); + if ($this->commentsRangeEnd == null) { + $this->commentsRangeEnd = new Comments(); + } + // Set ID early to avoid duplicates. + if ($value->getElementId() == null) { + $value->setElementId(); + } + foreach ($this->commentsRangeEnd->getItems() as $comment) { + if ($value->getElementId() == $comment->getElementId()) { + return; + } + } + $idxItem = $this->commentsRangeEnd->addItem($value); + $this->commentsRangeEnd->getItem($idxItem)->setEndElement($this); } /** @@ -428,7 +482,7 @@ public function isInSection() * Set new style value. * * @param mixed $styleObject Style object - * @param null|array|\PhpOffice\PhpWord\Style|string $styleValue Style value + * @param null|array|string|Style $styleValue Style value * @param bool $returnObject Always return object * * @return mixed diff --git a/src/PhpWord/Element/Comment.php b/src/PhpWord/Element/Comment.php index 7e7c5241fa..9173c49148 100644 --- a/src/PhpWord/Element/Comment.php +++ b/src/PhpWord/Element/Comment.php @@ -83,9 +83,7 @@ public function getInitials() public function setStartElement(AbstractElement $value): void { $this->startElement = $value; - if ($value->getCommentRangeStart() == null) { - $value->setCommentRangeStart($this); - } + $value->setCommentRangeStart($this); } /** @@ -104,9 +102,7 @@ public function getStartElement() public function setEndElement(AbstractElement $value): void { $this->endElement = $value; - if ($value->getCommentRangeEnd() == null) { - $value->setCommentRangeEnd($this); - } + $value->setCommentRangeEnd($this); } /** diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index a7aa95ce45..cf6f16ae02 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -134,7 +134,6 @@ public function __call($function, $args) if (in_array($function, $addCollection)) { $key = ucfirst(str_replace('add', '', $function) . 's'); - /** @var \PhpOffice\PhpWord\Collection\AbstractCollection $collectionObject */ $collectionObject = $this->collections[$key]; return $collectionObject->addItem($args[0] ?? null); diff --git a/src/PhpWord/Writer/Word2007.php b/src/PhpWord/Writer/Word2007.php index ab4fd1e3eb..e7801c04c2 100644 --- a/src/PhpWord/Writer/Word2007.php +++ b/src/PhpWord/Writer/Word2007.php @@ -227,7 +227,6 @@ private function addNotes(ZipArchive $zip, &$rId, $noteType = 'footnote'): void $collection = $phpWord->$method(); // Add footnotes media files, relations, and contents - /** @var \PhpOffice\PhpWord\Collection\AbstractCollection $collection Type hint */ if ($collection->countItems() > 0) { $media = Media::getElements($noteType); $this->addFilesToPackage($zip, $media); @@ -260,7 +259,6 @@ private function addComments(ZipArchive $zip, &$rId): void $partName = 'comments'; // Add comment relations and contents - /** @var \PhpOffice\PhpWord\Collection\AbstractCollection $collection Type hint */ if ($collection->countItems() > 0) { $this->relationships[] = ['target' => "{$partName}.xml", 'type' => $partName, 'rID' => ++$rId]; diff --git a/src/PhpWord/Writer/Word2007/Element/AbstractElement.php b/src/PhpWord/Writer/Word2007/Element/AbstractElement.php index abd1324aad..b677556d62 100644 --- a/src/PhpWord/Writer/Word2007/Element/AbstractElement.php +++ b/src/PhpWord/Writer/Word2007/Element/AbstractElement.php @@ -126,14 +126,10 @@ protected function endElementP(): void */ protected function writeCommentRangeStart(): void { - if ($this->element->getCommentRangeStart() != null) { - $comment = $this->element->getCommentRangeStart(); - //only set the ID if it is not yet set, otherwise it will overwrite it - if ($comment->getElementId() == null) { - $comment->setElementId(); + if ($this->element->getCommentsRangeStart() != null) { + foreach ($this->element->getCommentsRangeStart()->getItems() as $comment) { + $this->xmlWriter->writeElementBlock('w:commentRangeStart', ['w:id' => $comment->getElementId()]); } - - $this->xmlWriter->writeElementBlock('w:commentRangeStart', ['w:id' => $comment->getElementId()]); } } @@ -142,28 +138,23 @@ protected function writeCommentRangeStart(): void */ protected function writeCommentRangeEnd(): void { - if ($this->element->getCommentRangeEnd() != null) { - $comment = $this->element->getCommentRangeEnd(); - //only set the ID if it is not yet set, otherwise it will overwrite it, this should normally not happen - if ($comment->getElementId() == null) { - $comment->setElementId(); // @codeCoverageIgnore - } // @codeCoverageIgnore - - $this->xmlWriter->writeElementBlock('w:commentRangeEnd', ['w:id' => $comment->getElementId()]); - $this->xmlWriter->startElement('w:r'); - $this->xmlWriter->writeElementBlock('w:commentReference', ['w:id' => $comment->getElementId()]); - $this->xmlWriter->endElement(); - } elseif ($this->element->getCommentRangeStart() != null && $this->element->getCommentRangeStart()->getEndElement() == null) { - $comment = $this->element->getCommentRangeStart(); - //only set the ID if it is not yet set, otherwise it will overwrite it, this should normally not happen - if ($comment->getElementId() == null) { - $comment->setElementId(); // @codeCoverageIgnore - } // @codeCoverageIgnore - - $this->xmlWriter->writeElementBlock('w:commentRangeEnd', ['w:id' => $comment->getElementId()]); - $this->xmlWriter->startElement('w:r'); - $this->xmlWriter->writeElementBlock('w:commentReference', ['w:id' => $comment->getElementId()]); - $this->xmlWriter->endElement(); + if ($this->element->getCommentsRangeEnd() != null) { + foreach ($this->element->getCommentsRangeEnd()->getItems() as $comment) { + $this->xmlWriter->writeElementBlock('w:commentRangeEnd', ['w:id' => $comment->getElementId()]); + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->writeElementBlock('w:commentReference', ['w:id' => $comment->getElementId()]); + $this->xmlWriter->endElement(); + } + } + if ($this->element->getCommentsRangeStart() != null) { + foreach ($this->element->getCommentsRangeStart()->getItems() as $comment) { + if ($comment->getEndElement() == null) { + $this->xmlWriter->writeElementBlock('w:commentRangeEnd', ['w:id' => $comment->getElementId()]); + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->writeElementBlock('w:commentReference', ['w:id' => $comment->getElementId()]); + $this->xmlWriter->endElement(); + } + } } } diff --git a/tests/PhpWordTests/Element/CommentTest.php b/tests/PhpWordTests/Element/CommentTest.php index fe346307c4..b4d9cc6a5d 100644 --- a/tests/PhpWordTests/Element/CommentTest.php +++ b/tests/PhpWordTests/Element/CommentTest.php @@ -20,6 +20,7 @@ use DateTime; use InvalidArgumentException; use PhpOffice\PhpWord\Element\Comment; +use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\Element\Text; /** @@ -51,6 +52,39 @@ public function testConstructDefault(): void self::assertEquals($oText, $oComment->getEndElement()); } + /** + * Two comments on same text. + */ + public function testTwoCommentsOnSameText(): void + { + $section = new Section(0); + $text = $section->addText('Text'); + + $comment1 = new Comment('Author1', new DateTime(), 'A1'); + $comment1->addText('Comment1'); + + $comment2 = new Comment('Author2', new DateTime(), 'A2'); + $comment2->addText('Comment2'); + + $comment1->setStartElement($text); + $comment2->setStartElement($text); + + $text->setCommentRangeStart($comment1); + $text->setCommentRangeEnd($comment1); + + $text->setCommentRangeStart($comment2); + $text->setCommentRangeEnd($comment2); + + self::assertEquals(2, $text->getCommentsRangeStart()->countItems()); + self::assertEquals(2, $text->getCommentsRangeEnd()->countItems()); + + self::assertEquals($text->getCommentsRangeStart()->getItem(0)->getElementId(), $comment1->getElementId()); + self::assertEquals($text->getCommentsRangeEnd()->getItem(0)->getElementId(), $comment1->getElementId()); + + self::assertEquals($text->getCommentsRangeStart()->getItem(1)->getElementId(), $comment2->getElementId()); + self::assertEquals($text->getCommentsRangeEnd()->getItem(1)->getElementId(), $comment2->getElementId()); + } + /** * Add text. */ From 1f2ff44826223cd58fe2cdce27de3dd0ccbec74d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 17:44:57 +0200 Subject: [PATCH 211/246] Bump dompdf/dompdf from 2.0.4 to 3.0.0 (#2666) * Bump dompdf/dompdf from 2.0.4 to 3.0.0 Bumps [dompdf/dompdf](https://github.com/dompdf/dompdf) from 2.0.4 to 3.0.0. - [Release notes](https://github.com/dompdf/dompdf/releases) - [Commits](https://github.com/dompdf/dompdf/compare/v2.0.4...v3.0.0) --- updated-dependencies: - dependency-name: dompdf/dompdf dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Updated changelog --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Progi1984 <progi1984@gmail.com> --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- composer.json | 2 +- composer.lock | 219 ++++++++++++++++--------------- docs/changes/1.x/1.3.0.md | 2 +- docs/changes/1.x/1.4.0.md | 15 +++ mkdocs.yml | 3 +- 6 files changed, 131 insertions(+), 112 deletions(-) create mode 100644 docs/changes/1.x/1.4.0.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ce201f8bb6..7b74162561 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -9,4 +9,4 @@ Fixes # (issue) - [ ] My CI is :green_circle: - [ ] I have covered by unit tests my new code (check build/coverage for coverage report) - [ ] I have updated the [documentation](https://github.com/PHPOffice/PHPWord/tree/master/docs) to describe the changes -- [ ] I have updated the [changelog](https://github.com/PHPOffice/PHPWord/blob/master/docs/changes/2.x/2.0.0.md) +- [ ] I have updated the [changelog](https://github.com/PHPOffice/PHPWord/blob/master/docs/changes/1.x/1.4.0.md) diff --git a/composer.json b/composer.json index bce0f4b8f4..d267f08460 100644 --- a/composer.json +++ b/composer.json @@ -74,7 +74,7 @@ "ext-zip": "*", "ext-gd": "*", "ext-libxml": "*", - "dompdf/dompdf": "^2.0", + "dompdf/dompdf": "^2.0 || ^3.0", "mpdf/mpdf": "^8.1", "phpmd/phpmd": "^2.13", "phpunit/phpunit": ">=7.0", diff --git a/composer.lock b/composer.lock index d6b3ee35d8..4b3473cf0c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "15c1d733e1ddd2f424af0383ceb28dfd", + "content-hash": "d9579858cde1a3c80e4da1ced85b72fd", "packages": [ { "name": "phpoffice/math", @@ -547,32 +547,34 @@ }, { "name": "dompdf/dompdf", - "version": "v2.0.4", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f" + "reference": "fbc7c5ee5d94f7a910b78b43feb7931b7f971b59" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/093f2d9739cec57428e39ddadedfd4f3ae862c0f", - "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/fbc7c5ee5d94f7a910b78b43feb7931b7f971b59", + "reference": "fbc7c5ee5d94f7a910b78b43feb7931b7f971b59", "shasum": "" }, "require": { + "dompdf/php-font-lib": "^1.0.0", + "dompdf/php-svg-lib": "^1.0.0", "ext-dom": "*", "ext-mbstring": "*", "masterminds/html5": "^2.0", - "phenx/php-font-lib": ">=0.5.4 <1.0.0", - "phenx/php-svg-lib": ">=0.3.3 <1.0.0", "php": "^7.1 || ^8.0" }, "require-dev": { + "ext-gd": "*", "ext-json": "*", "ext-zip": "*", "mockery/mockery": "^1.3", - "phpunit/phpunit": "^7.5 || ^8 || ^9", - "squizlabs/php_codesniffer": "^3.5" + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10", + "squizlabs/php_codesniffer": "^3.5", + "symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0" }, "suggest": { "ext-gd": "Needed to process images", @@ -603,9 +605,100 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v2.0.4" + "source": "https://github.com/dompdf/dompdf/tree/v3.0.0" + }, + "time": "2024-04-29T14:01:28+00:00" + }, + { + "name": "dompdf/php-font-lib", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-font-lib.git", + "reference": "991d6a954f6bbd7e41022198f00586b230731441" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/991d6a954f6bbd7e41022198f00586b230731441", + "reference": "991d6a954f6bbd7e41022198f00586b230731441", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "FontLib\\": "src/FontLib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "The FontLib Community", + "homepage": "https://github.com/dompdf/php-font-lib/blob/master/AUTHORS.md" + } + ], + "description": "A library to read, parse, export and make subsets of different types of font files.", + "homepage": "https://github.com/dompdf/php-font-lib", + "support": { + "issues": "https://github.com/dompdf/php-font-lib/issues", + "source": "https://github.com/dompdf/php-font-lib/tree/1.0.0" + }, + "time": "2024-04-29T13:40:38+00:00" + }, + { + "name": "dompdf/php-svg-lib", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-svg-lib.git", + "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/eb045e518185298eb6ff8d80d0d0c6b17aecd9af", + "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0", + "sabberworm/php-css-parser": "^8.4" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Svg\\": "src/Svg" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "The SvgLib Community", + "homepage": "https://github.com/dompdf/php-svg-lib/blob/master/AUTHORS.md" + } + ], + "description": "A library to read, parse and export to PDF SVG files.", + "homepage": "https://github.com/dompdf/php-svg-lib", + "support": { + "issues": "https://github.com/dompdf/php-svg-lib/issues", + "source": "https://github.com/dompdf/php-svg-lib/tree/1.0.0" }, - "time": "2023-12-12T20:19:39+00:00" + "time": "2024-04-29T13:26:35+00:00" }, { "name": "friendsofphp/php-cs-fixer", @@ -698,16 +791,16 @@ }, { "name": "masterminds/html5", - "version": "2.8.1", + "version": "2.9.0", "source": { "type": "git", "url": "https://github.com/Masterminds/html5-php.git", - "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf" + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf", - "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", "shasum": "" }, "require": { @@ -715,7 +808,7 @@ "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8" + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" }, "type": "library", "extra": { @@ -759,9 +852,9 @@ ], "support": { "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.8.1" + "source": "https://github.com/Masterminds/html5-php/tree/2.9.0" }, - "time": "2023-05-10T11:58:31+00:00" + "time": "2024-03-31T07:05:07+00:00" }, { "name": "mpdf/mpdf", @@ -1276,96 +1369,6 @@ }, "time": "2022-02-21T01:04:05+00:00" }, - { - "name": "phenx/php-font-lib", - "version": "0.5.4", - "source": { - "type": "git", - "url": "https://github.com/dompdf/php-font-lib.git", - "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/dd448ad1ce34c63d09baccd05415e361300c35b4", - "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4", - "shasum": "" - }, - "require": { - "ext-mbstring": "*" - }, - "require-dev": { - "symfony/phpunit-bridge": "^3 || ^4 || ^5" - }, - "type": "library", - "autoload": { - "psr-4": { - "FontLib\\": "src/FontLib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0" - ], - "authors": [ - { - "name": "Fabien Ménager", - "email": "fabien.menager@gmail.com" - } - ], - "description": "A library to read, parse, export and make subsets of different types of font files.", - "homepage": "https://github.com/PhenX/php-font-lib", - "support": { - "issues": "https://github.com/dompdf/php-font-lib/issues", - "source": "https://github.com/dompdf/php-font-lib/tree/0.5.4" - }, - "time": "2021-12-17T19:44:54+00:00" - }, - { - "name": "phenx/php-svg-lib", - "version": "0.5.4", - "source": { - "type": "git", - "url": "https://github.com/dompdf/php-svg-lib.git", - "reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/46b25da81613a9cf43c83b2a8c2c1bdab27df691", - "reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": "^7.1 || ^8.0", - "sabberworm/php-css-parser": "^8.4" - }, - "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Svg\\": "src/Svg" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Fabien Ménager", - "email": "fabien.menager@gmail.com" - } - ], - "description": "A library to read, parse and export to PDF SVG files.", - "homepage": "https://github.com/PhenX/php-svg-lib", - "support": { - "issues": "https://github.com/dompdf/php-svg-lib/issues", - "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.4" - }, - "time": "2024-04-08T12:52:34+00:00" - }, { "name": "php-cs-fixer/diff", "version": "v2.0.2", diff --git a/docs/changes/1.x/1.3.0.md b/docs/changes/1.x/1.3.0.md index a52e16e339..4b2e1b25df 100644 --- a/docs/changes/1.x/1.3.0.md +++ b/docs/changes/1.x/1.3.0.md @@ -1,4 +1,4 @@ -# [1.3.0](https://github.com/PHPOffice/PHPWord/tree/1.3.0) (WIP) +# [1.3.0](https://github.com/PHPOffice/PHPWord/tree/1.3.0) [Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.2.0...1.3.0) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md new file mode 100644 index 0000000000..b7673d1ff8 --- /dev/null +++ b/docs/changes/1.x/1.4.0.md @@ -0,0 +1,15 @@ +# [1.4.0](https://github.com/PHPOffice/PHPWord/tree/1.4.0) (WIP) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.3.0...1.4.0) + +## Enhancements + + +### Bug fixes + + +### Miscellaneous + +- Bump dompdf/dompdf from 2.0.4 to 3.0.0 by [@dependabot](https://github.com/dependabot) fixing [#2621](https://github.com/PHPOffice/PHPWord/issues/2621) in [#2666](https://github.com/PHPOffice/PHPWord/pull/2666) + +### BC Breaks diff --git a/mkdocs.yml b/mkdocs.yml index dfabbb195a..6b2c1b7fa6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -87,7 +87,8 @@ nav: - Credits: 'credits.md' - Releases: - '1.x': - - '1.3.0 (WIP)': 'changes/1.x/1.3.0.md' + - '1.4.0 (WIP)': 'changes/1.x/1.4.0.md' + - '1.3.0': 'changes/1.x/1.3.0.md' - '1.2.0': 'changes/1.x/1.2.0.md' - '1.1.0': 'changes/1.x/1.1.0.md' - '1.0.0': 'changes/1.x/1.0.0.md' From a0d00e7d3eb8908a382eec9a49c6b01b65e76ddb Mon Sep 17 00:00:00 2001 From: Progi1984 <progi1984@gmail.com> Date: Tue, 3 Sep 2024 18:48:36 +0200 Subject: [PATCH 212/246] Writer ODText: Support for images inside a textRun (#2668) --- README.md | 10 +++--- docs/changes/1.x/1.4.0.md | 1 + samples/Sample_13_Images.php | 15 ++++---- src/PhpWord/Writer/ODText/Element/Image.php | 17 ++++++--- .../Writer/Word2007/Element/Container.php | 6 +--- .../Writer/ODText/Element/ImageTest.php | 35 +++++++++++++++++-- tests/PhpWordTests/XmlDocument.php | 8 +++++ 7 files changed, 68 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 11bcd1525c..96dd989970 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # ![PHPWord](https://rawgit.com/PHPOffice/PHPWord/develop/docs/images/phpword.svg "PHPWord") -[![Latest Stable Version](https://poser.pugx.org/phpoffice/phpword/v/stable.png)](https://packagist.org/packages/phpoffice/phpword) +[![Latest Stable Version](https://poser.pugx.org/phpoffice/phpword/v)](https://packagist.org/packages/phpoffice/phpword) [![Coverage Status](https://coveralls.io/repos/github/PHPOffice/PHPWord/badge.svg?branch=master)](https://coveralls.io/github/PHPOffice/PHPWord?branch=master) -[![Total Downloads](https://poser.pugx.org/phpoffice/phpword/downloads.png)](https://packagist.org/packages/phpoffice/phpword) -[![License](https://poser.pugx.org/phpoffice/phpword/license.png)](https://packagist.org/packages/phpoffice/phpword) -[![CI](https://github.com/PHPOffice/PHPWord/actions/workflows/ci.yml/badge.svg)](https://github.com/PHPOffice/PHPWord/actions/workflows/ci.yml) -[![Join the chat at https://gitter.im/PHPOffice/PHPWord](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/PHPOffice/PHPWord) +[![Total Downloads](https://poser.pugx.org/phpoffice/phpword/downloads)](https://packagist.org/packages/phpoffice/phpword) +[![License](https://poser.pugx.org/phpoffice/phpword/license)](https://packagist.org/packages/phpoffice/phpword) + +Branch Master : [![PHPWord](https://github.com/PHPOffice/PHPWord/actions/workflows/php.yml/badge.svg?branch=master)](https://github.com/PHPOffice/PHPWord/actions/workflows/php.yml) PHPWord is a library written in pure PHP that provides a set of classes to write to and read from different document file formats. The current version of PHPWord supports Microsoft [Office Open XML](http://en.wikipedia.org/wiki/Office_Open_XML) (OOXML or OpenXML), OASIS [Open Document Format for Office Applications](http://en.wikipedia.org/wiki/OpenDocument) (OpenDocument or ODF), [Rich Text Format](http://en.wikipedia.org/wiki/Rich_Text_Format) (RTF), HTML, and PDF. diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index b7673d1ff8..9bcdf6ccfb 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -7,6 +7,7 @@ ### Bug fixes +- Writer ODText: Support for images inside a textRun by [@Progi1984](https://github.com/Progi1984) fixing [#2240](https://github.com/PHPOffice/PHPWord/issues/2240) in [#2668](https://github.com/PHPOffice/PHPWord/pull/2668) ### Miscellaneous diff --git a/samples/Sample_13_Images.php b/samples/Sample_13_Images.php index 30b9cae949..f351bd91eb 100644 --- a/samples/Sample_13_Images.php +++ b/samples/Sample_13_Images.php @@ -1,22 +1,23 @@ <?php use PhpOffice\PhpWord\Element\Section; +use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Shared\Converter; include_once 'Sample_Header.php'; // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpWord(); // Begin code $section = $phpWord->addSection(); $section->addText('Local image without any styles:'); -$section->addImage('resources/_mars.jpg'); +$section->addImage(__DIR__ . '/resources/_mars.jpg'); printSeparator($section); $section->addText('Local image with styles:'); -$section->addImage('resources/_earth.jpg', ['width' => 210, 'height' => 210, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); +$section->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 210, 'height' => 210, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); // Remote image printSeparator($section); @@ -26,7 +27,7 @@ // Image from string printSeparator($section); -$source = 'resources/_mars.jpg'; +$source = __DIR__ . '/resources/_mars.jpg'; $fileContent = file_get_contents($source); $section->addText('Image from string'); $section->addImage($fileContent); @@ -38,7 +39,7 @@ foreach ($wrappingStyles as $wrappingStyle) { $section->addText("Wrapping style {$wrappingStyle}"); $section->addImage( - 'resources/_earth.jpg', + __DIR__ . '/resources/_earth.jpg', [ 'positioning' => 'relative', 'marginTop' => -1, @@ -57,7 +58,7 @@ //Absolute positioning $section->addText('Absolute positioning: see top right corner of page'); $section->addImage( - 'resources/_mars.jpg', + __DIR__ . '/resources/_mars.jpg', [ 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), @@ -75,7 +76,7 @@ $section->addText('Relative positioning: Horizontal position center relative to column,'); $section->addText('Vertical position top relative to line'); $section->addImage( - 'resources/_mars.jpg', + __DIR__ . '/resources/_mars.jpg', [ 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), diff --git a/src/PhpWord/Writer/ODText/Element/Image.php b/src/PhpWord/Writer/ODText/Element/Image.php index 051c79ce57..e5a7fba284 100644 --- a/src/PhpWord/Writer/ODText/Element/Image.php +++ b/src/PhpWord/Writer/ODText/Element/Image.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWord\Writer\ODText\Element; +use PhpOffice\PhpWord\Element\Image as ElementImage; use PhpOffice\PhpWord\Shared\Converter; /** @@ -31,9 +32,8 @@ class Image extends AbstractElement */ public function write(): void { - $xmlWriter = $this->getXmlWriter(); $element = $this->getElement(); - if (!$element instanceof \PhpOffice\PhpWord\Element\Image) { + if (!$element instanceof ElementImage) { return; } @@ -43,11 +43,16 @@ public function write(): void $width = Converter::pixelToCm($style->getWidth()); $height = Converter::pixelToCm($style->getHeight()); - $xmlWriter->startElement('text:p'); - $xmlWriter->writeAttribute('text:style-name', 'IM' . $mediaIndex); + $xmlWriter = $this->getXmlWriter(); + + if (!$this->withoutP) { + $xmlWriter->startElement('text:p'); + $xmlWriter->writeAttribute('text:style-name', 'IM' . $mediaIndex); + } $xmlWriter->startElement('draw:frame'); $xmlWriter->writeAttribute('draw:style-name', 'fr' . $mediaIndex); + $xmlWriter->writeAttributeIf($this->withoutP, 'draw:text-style-name', 'IM' . $mediaIndex); $xmlWriter->writeAttribute('draw:name', $element->getElementId()); $xmlWriter->writeAttribute('text:anchor-type', 'as-char'); $xmlWriter->writeAttribute('svg:width', $width . 'cm'); @@ -63,6 +68,8 @@ public function write(): void $xmlWriter->endElement(); // draw:frame - $xmlWriter->endElement(); // text:p + if (!$this->withoutP) { + $xmlWriter->endElement(); // text:p + } } } diff --git a/src/PhpWord/Writer/Word2007/Element/Container.php b/src/PhpWord/Writer/Word2007/Element/Container.php index 491e813c9e..f56d1c247e 100644 --- a/src/PhpWord/Writer/Word2007/Element/Container.php +++ b/src/PhpWord/Writer/Word2007/Element/Container.php @@ -70,12 +70,8 @@ public function write(): void /** * Write individual element. - * - * @param bool $withoutP - * - * @return string */ - private function writeElement(XMLWriter $xmlWriter, Element $element, $withoutP) + private function writeElement(XMLWriter $xmlWriter, Element $element, bool $withoutP): string { $elementClass = substr(get_class($element), strrpos(get_class($element), '\\') + 1); $writerClass = $this->namespace . '\\' . $elementClass; diff --git a/tests/PhpWordTests/Writer/ODText/Element/ImageTest.php b/tests/PhpWordTests/Writer/ODText/Element/ImageTest.php index a71615498c..367f9eee75 100644 --- a/tests/PhpWordTests/Writer/ODText/Element/ImageTest.php +++ b/tests/PhpWordTests/Writer/ODText/Element/ImageTest.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWordTests\Writer\ODText\Style; +use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Style\Image; use PhpOffice\PhpWordTests\TestHelperDOCX; @@ -42,7 +43,7 @@ protected function tearDown(): void */ public function testImage1(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $section = $phpWord->addSection(); $section->addImage(__DIR__ . '/../../../_files/images/earth.jpg'); $section->addImage(__DIR__ . '/../../../_files/images/mario.gif', ['align' => 'end']); @@ -59,9 +60,11 @@ public function testImage1(): void $path = '/office:document-content/office:body/office:text/text:section/text:p[2]'; self::assertTrue($doc->elementExists($path)); + self::assertFalse($doc->hasElementAttribute($path, 'draw:text-style-name')); self::assertEquals('IM1', $doc->getElementAttribute($path, 'text:style-name')); $path = '/office:document-content/office:body/office:text/text:section/text:p[3]'; self::assertTrue($doc->elementExists($path)); + self::assertFalse($doc->hasElementAttribute($path, 'draw:text-style-name')); self::assertEquals('IM2', $doc->getElementAttribute($path, 'text:style-name')); } @@ -70,7 +73,7 @@ public function testImage1(): void */ public function testImage2(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); Settings::setDefaultRtl(false); $section = $phpWord->addSection(); $section->addImage(__DIR__ . '/../../../_files/images/earth.jpg'); @@ -89,8 +92,36 @@ public function testImage2(): void $path = '/office:document-content/office:body/office:text/text:section/text:p[2]'; self::assertTrue($doc->elementExists($path)); self::assertEquals('IM1', $doc->getElementAttribute($path, 'text:style-name')); + self::assertFalse($doc->hasElementAttribute($path, 'draw:text-style-name')); $path = '/office:document-content/office:body/office:text/text:section/text:p[3]'; self::assertTrue($doc->elementExists($path)); self::assertEquals('IM2', $doc->getElementAttribute($path, 'text:style-name')); + self::assertFalse($doc->hasElementAttribute($path, 'draw:text-style-name')); + } + + /** + * Test writing image not in a section. + */ + public function testImageInTextRun(): void + { + $phpWord = new PhpWord(); + Settings::setDefaultRtl(false); + $section = $phpWord->addSection(); + $textRun = $section->addTextRun(); + $textRun->addImage(__DIR__ . '/../../../_files/images/earth.jpg'); + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + $s2a = '/office:document-content/office:automatic-styles'; + $element = "$s2a/style:style[4]"; + self::assertEquals('IM1', $doc->getElementAttribute($element, 'style:name')); + $element .= '/style:paragraph-properties'; + self::assertEquals('left', $doc->getElementAttribute($element, 'fo:text-align')); + + $path = '/office:document-content/office:body/office:text/text:section/text:p[2]'; + self::assertTrue($doc->elementExists($path)); + self::assertEquals('P1', $doc->getElementAttribute($path, 'text:style-name')); + $path = '/office:document-content/office:body/office:text/text:section/text:p[2]/draw:frame'; + self::assertTrue($doc->elementExists($path)); + self::assertTrue($doc->hasElementAttribute($path, 'draw:text-style-name')); + self::assertEquals('IM1', $doc->getElementAttribute($path, 'draw:text-style-name')); } } diff --git a/tests/PhpWordTests/XmlDocument.php b/tests/PhpWordTests/XmlDocument.php index 92e19d3bb9..1b309d0c71 100644 --- a/tests/PhpWordTests/XmlDocument.php +++ b/tests/PhpWordTests/XmlDocument.php @@ -175,6 +175,14 @@ public function getElementAttribute(string $path, string $attribute, string $fil return $this->getElement($path, $file)->getAttribute($attribute); } + /** + * Return if element attribute exists. + */ + public function hasElementAttribute(string $path, string $attribute, string $file = ''): bool + { + return $this->getElement($path, $file)->hasAttribute($attribute); + } + /** * Check if element exists. */ From 2e4f3cf3b7ebf50131f5f661da2c9a9788a8dc2c Mon Sep 17 00:00:00 2001 From: Progi1984 <progi1984@gmail.com> Date: Thu, 5 Sep 2024 09:08:06 +0200 Subject: [PATCH 213/246] Writer ODText: Support for ListItemRun (#2669) --- docs/changes/1.x/1.4.0.md | 1 + docs/index.md | 2 +- src/PhpWord/Shared/Html.php | 18 ++-- src/PhpWord/Style/Numbering.php | 28 ++---- .../Writer/ODText/Element/Container.php | 5 ++ .../Writer/ODText/Element/ListItemRun.php | 56 ++++++++++++ src/PhpWord/Writer/ODText/Element/Text.php | 40 ++++----- src/PhpWord/Writer/ODText/Style/Numbering.php | 86 +++++++++++++++++++ .../Word2007/Element/AbstractElement.php | 4 +- .../Writer/Word2007/Element/Container.php | 7 +- .../Writer/ODText/Element/ListItemRunTest.php | 82 ++++++++++++++++++ .../Writer/ODText/Style/NumberingTest.php | 69 +++++++++++++++ 12 files changed, 338 insertions(+), 60 deletions(-) create mode 100644 src/PhpWord/Writer/ODText/Element/ListItemRun.php create mode 100644 src/PhpWord/Writer/ODText/Style/Numbering.php create mode 100644 tests/PhpWordTests/Writer/ODText/Element/ListItemRunTest.php create mode 100644 tests/PhpWordTests/Writer/ODText/Style/NumberingTest.php diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 9bcdf6ccfb..cdab8bdc77 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -4,6 +4,7 @@ ## Enhancements +- Writer ODText: Support for ListItemRun by [@Progi1984](https://github.com/Progi1984) fixing [#2159](https://github.com/PHPOffice/PHPWord/issues/2159), [#2620](https://github.com/PHPOffice/PHPWord/issues/2620) in [#2669](https://github.com/PHPOffice/PHPWord/pull/2669) ### Bug fixes diff --git a/docs/index.md b/docs/index.md index dd600689d7..211fc31a79 100644 --- a/docs/index.md +++ b/docs/index.md @@ -52,7 +52,7 @@ Below are the supported features for each file formats. | | Preserve Text | :material-check: | | | | | | | Text Break | :material-check: | :material-check: | :material-check: | :material-check: | :material-check: | | | Page Break | :material-check: | | :material-check: | | | -| | List | :material-check: | | | | | +| | List | :material-check: | :material-check: | | | | | | Table | :material-check: | :material-check: | :material-check: | :material-check: | :material-check: | | | Image | :material-check: | :material-check: | :material-check: | :material-check: | | | | Object | :material-check: | | | | | diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index f65c67435b..334f5c269e 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -627,15 +627,15 @@ protected static function getListStyle($isOrderedList) return [ 'type' => 'hybridMultilevel', 'levels' => [ - ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 720, 'left' => 720, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 1440, 'left' => 1440, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2160, 'left' => 2160, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2880, 'left' => 2880, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 3600, 'left' => 3600, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 4320, 'left' => 4320, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 5040, 'left' => 5040, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 5760, 'left' => 5760, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 6480, 'left' => 6480, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 720, 'left' => 720, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '◦', 'alignment' => 'left', 'tabPos' => 1440, 'left' => 1440, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 2160, 'left' => 2160, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 2880, 'left' => 2880, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '◦', 'alignment' => 'left', 'tabPos' => 3600, 'left' => 3600, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 4320, 'left' => 4320, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 5040, 'left' => 5040, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '◦', 'alignment' => 'left', 'tabPos' => 5760, 'left' => 5760, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 6480, 'left' => 6480, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'], ], ]; } diff --git a/src/PhpWord/Style/Numbering.php b/src/PhpWord/Style/Numbering.php index 0efb088dd4..c3af1fc352 100644 --- a/src/PhpWord/Style/Numbering.php +++ b/src/PhpWord/Style/Numbering.php @@ -54,22 +54,16 @@ class Numbering extends AbstractStyle /** * Get Id. - * - * @return int */ - public function getNumId() + public function getNumId(): ?int { return $this->numId; } /** * Set Id. - * - * @param int $value - * - * @return self */ - public function setNumId($value) + public function setNumId(int $value): self { $this->numId = $this->setIntVal($value, $this->numId); @@ -78,22 +72,16 @@ public function setNumId($value) /** * Get multilevel type. - * - * @return string */ - public function getType() + public function getType(): ?string { return $this->type; } /** * Set multilevel type. - * - * @param string $value - * - * @return self */ - public function setType($value) + public function setType(string $value): self { $enum = ['singleLevel', 'multilevel', 'hybridMultilevel']; $this->type = $this->setEnumVal($value, $enum, $this->type); @@ -106,19 +94,15 @@ public function setType($value) * * @return NumberingLevel[] */ - public function getLevels() + public function getLevels(): array { return $this->levels; } /** * Set multilevel type. - * - * @param array $values - * - * @return self */ - public function setLevels($values) + public function setLevels(array $values): self { if (is_array($values)) { foreach ($values as $key => $value) { diff --git a/src/PhpWord/Writer/ODText/Element/Container.php b/src/PhpWord/Writer/ODText/Element/Container.php index 6e6b88eabc..6262ad227e 100644 --- a/src/PhpWord/Writer/ODText/Element/Container.php +++ b/src/PhpWord/Writer/ODText/Element/Container.php @@ -32,4 +32,9 @@ class Container extends Word2007Container * @var string */ protected $namespace = 'PhpOffice\\PhpWord\\Writer\\ODText\\Element'; + + /** + * @var array<string> + */ + protected $containerWithoutP = ['TextRun', 'Footnote', 'Endnote']; } diff --git a/src/PhpWord/Writer/ODText/Element/ListItemRun.php b/src/PhpWord/Writer/ODText/Element/ListItemRun.php new file mode 100644 index 0000000000..89352bbbd2 --- /dev/null +++ b/src/PhpWord/Writer/ODText/Element/ListItemRun.php @@ -0,0 +1,56 @@ +<?php +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\ODText\Element; + +use PhpOffice\PhpWord\Element\ListItemRun as ListItemRunElement; + +/** + * ListItemRun element writer. + * + * @since 0.10.0 + */ +class ListItemRun extends AbstractElement +{ + /** + * Write list item element. + */ + public function write(): void + { + $element = $this->getElement(); + if (!$element instanceof ListItemRunElement) { + return; + } + $depth = $element->getDepth() + 1; + + $xmlWriter = $this->getXmlWriter(); + + for ($iDepth = 1; $iDepth <= $depth; ++$iDepth) { + $xmlWriter->startElement('text:list'); + $xmlWriter->writeAttribute('text:style-name', $element->getStyle()->getNumStyle()); + $xmlWriter->startElement('text:list-item'); + } + + $containerWriter = new Container($xmlWriter, $element, false); + $containerWriter->write(); + + for ($iDepth = 1; $iDepth <= $depth; ++$iDepth) { + $xmlWriter->endElement(); // text:list-item + $xmlWriter->endElement(); // text:list + } + } +} diff --git a/src/PhpWord/Writer/ODText/Element/Text.php b/src/PhpWord/Writer/ODText/Element/Text.php index 75fb930856..7d54071471 100644 --- a/src/PhpWord/Writer/ODText/Element/Text.php +++ b/src/PhpWord/Writer/ODText/Element/Text.php @@ -57,37 +57,29 @@ public function write(): void $xmlWriter->writeAttribute('text:change-id', $element->getTrackChange()->getElementId()); $xmlWriter->endElement(); } else { - if (empty($fontStyle)) { - if (empty($paragraphStyle)) { - if (!$this->withoutP) { - $xmlWriter->writeAttribute('text:style-name', 'Normal'); - } - } elseif (is_string($paragraphStyle)) { - if (!$this->withoutP) { - $xmlWriter->writeAttribute('text:style-name', $paragraphStyle); - } + if (empty($paragraphStyle)) { + if (!$this->withoutP) { + $xmlWriter->writeAttribute('text:style-name', 'Normal'); } - $this->writeChangeInsertion(true, $element->getTrackChange()); - $this->replaceTabs($element->getText(), $xmlWriter); - $this->writeChangeInsertion(false, $element->getTrackChange()); - } else { - if (empty($paragraphStyle)) { - if (!$this->withoutP) { - $xmlWriter->writeAttribute('text:style-name', 'Normal'); - } - } elseif (is_string($paragraphStyle)) { - if (!$this->withoutP) { - $xmlWriter->writeAttribute('text:style-name', $paragraphStyle); - } + } elseif (is_string($paragraphStyle)) { + if (!$this->withoutP) { + $xmlWriter->writeAttribute('text:style-name', $paragraphStyle); } + } + + if (!empty($fontStyle)) { // text:span $xmlWriter->startElement('text:span'); if (is_string($fontStyle)) { $xmlWriter->writeAttribute('text:style-name', $fontStyle); } - $this->writeChangeInsertion(true, $element->getTrackChange()); - $this->replaceTabs($element->getText(), $xmlWriter); - $this->writeChangeInsertion(false, $element->getTrackChange()); + } + + $this->writeChangeInsertion(true, $element->getTrackChange()); + $this->replaceTabs($element->getText(), $xmlWriter); + $this->writeChangeInsertion(false, $element->getTrackChange()); + + if (!empty($fontStyle)) { $xmlWriter->endElement(); } } diff --git a/src/PhpWord/Writer/ODText/Style/Numbering.php b/src/PhpWord/Writer/ODText/Style/Numbering.php new file mode 100644 index 0000000000..83a1c9a750 --- /dev/null +++ b/src/PhpWord/Writer/ODText/Style/Numbering.php @@ -0,0 +1,86 @@ +<?php +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\ODText\Style; + +use PhpOffice\PhpWord\Shared\Converter; +use PhpOffice\PhpWord\Style\Numbering as StyleNumbering; + +/** + * Numbering style writer. + */ +class Numbering extends AbstractStyle +{ + /** + * Write style. + */ + public function write(): void + { + /** @var StyleNumbering $style Type hint */ + $style = $this->getStyle(); + if (!$style instanceof StyleNumbering) { + return; + } + $xmlWriter = $this->getXmlWriter(); + + $xmlWriter->startElement('text:list-style'); + $xmlWriter->writeAttribute('style:name', $style->getStyleName()); + + foreach ($style->getLevels() as $styleLevel) { + $numLevel = $styleLevel->getLevel() + 1; + + // In Twips + $tabPos = $styleLevel->getTabPos(); + // In Inches + $tabPos /= Converter::INCH_TO_TWIP; + // In Centimeters + $tabPos *= Converter::INCH_TO_CM; + + // In Twips + $hanging = $styleLevel->getHanging(); + // In Inches + $hanging /= Converter::INCH_TO_TWIP; + // In Centimeters + $hanging *= Converter::INCH_TO_CM; + + $xmlWriter->startElement('text:list-level-style-bullet'); + $xmlWriter->writeAttribute('text:level', $numLevel); + $xmlWriter->writeAttribute('text:style-name', $style->getStyleName() . '_' . $numLevel); + $xmlWriter->writeAttribute('text:bullet-char', $styleLevel->getText()); + + $xmlWriter->startElement('style:list-level-properties'); + $xmlWriter->writeAttribute('text:list-level-position-and-space-mode', 'label-alignment'); + + $xmlWriter->startElement('style:list-level-label-alignment'); + $xmlWriter->writeAttribute('text:label-followed-by', 'listtab'); + $xmlWriter->writeAttribute('text:list-tab-stop-position', number_format($tabPos, 2, '.', '') . 'cm'); + $xmlWriter->writeAttribute('fo:text-indent', '-' . number_format($hanging, 2, '.', '') . 'cm'); + $xmlWriter->writeAttribute('fo:margin-left', number_format($tabPos, 2, '.', '') . 'cm'); + + $xmlWriter->endElement(); // style:list-level-label-alignment + $xmlWriter->endElement(); // style:list-level-properties + + $xmlWriter->startElement('style:text-properties'); + $xmlWriter->writeAttribute('style:font-name', $styleLevel->getFont()); + $xmlWriter->endElement(); // style:text-properties + + $xmlWriter->endElement(); // text:list-level-style-bullet + } + + $xmlWriter->endElement(); // text:list-style + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/AbstractElement.php b/src/PhpWord/Writer/Word2007/Element/AbstractElement.php index b677556d62..a71ec6f95e 100644 --- a/src/PhpWord/Writer/Word2007/Element/AbstractElement.php +++ b/src/PhpWord/Writer/Word2007/Element/AbstractElement.php @@ -63,10 +63,8 @@ abstract public function write(); /** * Create new instance. - * - * @param bool $withoutP */ - public function __construct(XMLWriter $xmlWriter, Element $element, $withoutP = false) + public function __construct(XMLWriter $xmlWriter, Element $element, bool $withoutP = false) { $this->xmlWriter = $xmlWriter; $this->element = $element; diff --git a/src/PhpWord/Writer/Word2007/Element/Container.php b/src/PhpWord/Writer/Word2007/Element/Container.php index f56d1c247e..919954c152 100644 --- a/src/PhpWord/Writer/Word2007/Element/Container.php +++ b/src/PhpWord/Writer/Word2007/Element/Container.php @@ -36,6 +36,11 @@ class Container extends AbstractElement */ protected $namespace = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element'; + /** + * @var array<string> + */ + protected $containerWithoutP = ['TextRun', 'Footnote', 'Endnote', 'ListItemRun']; + /** * Write element. */ @@ -46,7 +51,7 @@ public function write(): void return; } $containerClass = substr(get_class($container), strrpos(get_class($container), '\\') + 1); - $withoutP = in_array($containerClass, ['TextRun', 'Footnote', 'Endnote', 'ListItemRun']); + $withoutP = in_array($containerClass, $this->containerWithoutP); $xmlWriter = $this->getXmlWriter(); // Loop through elements diff --git a/tests/PhpWordTests/Writer/ODText/Element/ListItemRunTest.php b/tests/PhpWordTests/Writer/ODText/Element/ListItemRunTest.php new file mode 100644 index 0000000000..d0509035cc --- /dev/null +++ b/tests/PhpWordTests/Writer/ODText/Element/ListItemRunTest.php @@ -0,0 +1,82 @@ +<?php +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWordTests\Writer\ODText\Element; + +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWordTests\TestHelperDOCX; +use PHPUnit\Framework\TestCase; + +class ListItemRunTest extends TestCase +{ + /** + * Executed after each method of the class. + */ + protected function tearDown(): void + { + TestHelperDOCX::clear(); + } + + public function testAddListItemRun(): void + { + $expected = 'List item run 1'; + + $phpWord = new PhpWord(); + $phpWord + ->addSection() + ->addListItemRun() + ->addText($expected); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + + $xPath = '/office:document-content/office:body/office:text/text:section/text:list'; + + self::assertTrue($doc->elementExists($xPath)); + self::assertTrue($doc->hasElementAttribute($xPath, 'text:style-name')); + self::assertEquals('PHPWordListType3', $doc->getElementAttribute($xPath, 'text:style-name')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item/text:p')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item/text:p/text:span')); + self::assertEquals($expected, $doc->getElement($xPath . '/text:list-item/text:p/text:span')->nodeValue); + } + + public function testAddListItemRunLevels(): void + { + $expected = 'List item run : '; + + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $section->addListItemRun(0)->addText($expected . '1'); + $section->addListItemRun(1)->addText($expected . '2'); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + + $xPath = '/office:document-content/office:body/office:text/text:section/text:list'; + + self::assertTrue($doc->elementExists($xPath)); + self::assertTrue($doc->hasElementAttribute($xPath, 'text:style-name')); + self::assertEquals('PHPWordListType3', $doc->getElementAttribute($xPath, 'text:style-name')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item/text:p')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item/text:p/text:span')); + self::assertEquals($expected . '1', $doc->getElement($xPath . '/text:list-item/text:p/text:span')->nodeValue); + self::assertTrue($doc->elementExists($xPath . '/text:list-item/text:list/text:list-item')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item/text:list/text:list-item/text:p')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item/text:list/text:list-item/text:p/text:span')); + self::assertEquals($expected . '2', $doc->getElement($xPath . '/text:list-item/text:list/text:list-item/text:p/text:span')->nodeValue); + } +} diff --git a/tests/PhpWordTests/Writer/ODText/Style/NumberingTest.php b/tests/PhpWordTests/Writer/ODText/Style/NumberingTest.php new file mode 100644 index 0000000000..4b46637045 --- /dev/null +++ b/tests/PhpWordTests/Writer/ODText/Style/NumberingTest.php @@ -0,0 +1,69 @@ +<?php +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWordTests\Writer\ODText\Style; + +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\SimpleType\Jc; +use PhpOffice\PhpWordTests\TestHelperDOCX; + +class NumberingTest extends \PHPUnit\Framework\TestCase +{ + /** + * Executed after each method of the class. + */ + protected function tearDown(): void + { + TestHelperDOCX::clear(); + } + + public function testAddListItemRun(): void + { + $expected = 'MyOwnNumberingStyle'; + + $phpWord = new PhpWord(); + $phpWord->addNumberingStyle($expected, [ + 'type' => 'multilevel', + 'levels' => [ + [ + 'start' => 1, + 'format' => 'decimal', + 'restart' => 1, + 'suffix' => 'space', + 'text' => '%1.', + 'alignment' => Jc::START, + ], + ], + ]); + $phpWord->addSection() + ->addListItemRun(0, $expected) + ->addText('List item run 1'); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + $doc->setDefaultFile('styles.xml'); + + $xPath = '/office:document-styles/office:styles'; + self::assertTrue($doc->elementExists($xPath)); + self::assertTrue($doc->elementExists($xPath . '/text:list-style')); + self::assertTrue($doc->hasElementAttribute($xPath . '/text:list-style', 'style:name')); + self::assertEquals($expected, $doc->getElementAttribute($xPath . '/text:list-style', 'style:name')); + self::assertTrue($doc->elementExists($xPath . '/text:list-style/text:list-level-style-bullet')); + self::assertTrue($doc->elementExists($xPath . '/text:list-style/text:list-level-style-bullet/style:list-level-properties')); + self::assertTrue($doc->elementExists($xPath . '/text:list-style/text:list-level-style-bullet/style:list-level-properties/style:list-level-label-alignment')); + self::assertTrue($doc->elementExists($xPath . '/text:list-style/text:list-level-style-bullet/style:text-properties')); + } +} From fa0cea023638aa24f9c81f7a36a827dcf55c2815 Mon Sep 17 00:00:00 2001 From: Christian Koop <sprax2013@gmail.com> Date: Fri, 13 Sep 2024 12:23:37 +0200 Subject: [PATCH 214/246] feat: Add support for vAlign styles in the HTML Writer (Table) (#2675) * feat: Add support for vAlign styles in the HTML Writer * docs(changelog): Add note about supporting table vAlign in HTML Writer --- docs/changes/1.x/1.4.0.md | 1 + src/PhpWord/Writer/HTML/Style/Table.php | 3 +++ .../Writer/HTML/Element/TableTest.php | 27 ++++++++++++++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index cdab8bdc77..ebd3ad4029 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -5,6 +5,7 @@ ## Enhancements - Writer ODText: Support for ListItemRun by [@Progi1984](https://github.com/Progi1984) fixing [#2159](https://github.com/PHPOffice/PHPWord/issues/2159), [#2620](https://github.com/PHPOffice/PHPWord/issues/2620) in [#2669](https://github.com/PHPOffice/PHPWord/pull/2669) +- Writer HTML: Support for vAlign in Tables by [@SpraxDev](https://github.com/SpraxDev) in [#2675](https://github.com/PHPOffice/PHPWord/pull/2675) ### Bug fixes diff --git a/src/PhpWord/Writer/HTML/Style/Table.php b/src/PhpWord/Writer/HTML/Style/Table.php index d2c318a69f..53eea0e96f 100644 --- a/src/PhpWord/Writer/HTML/Style/Table.php +++ b/src/PhpWord/Writer/HTML/Style/Table.php @@ -46,6 +46,9 @@ public function write() $css['direction'] = 'rtl'; } } + if (is_object($style) && method_exists($style, 'getVAlign')) { + $css['vertical-align'] = $style->getVAlign(); + } foreach (['Top', 'Left', 'Bottom', 'Right'] as $direction) { $method = 'getBorder' . $direction . 'Style'; diff --git a/tests/PhpWordTests/Writer/HTML/Element/TableTest.php b/tests/PhpWordTests/Writer/HTML/Element/TableTest.php index 032b7b69cd..88b12e7204 100644 --- a/tests/PhpWordTests/Writer/HTML/Element/TableTest.php +++ b/tests/PhpWordTests/Writer/HTML/Element/TableTest.php @@ -19,7 +19,7 @@ use DOMXPath; use PhpOffice\PhpWord\PhpWord; -use PhpOffice\PhpWord\Writer\HTML\Element\Table; +use PhpOffice\PhpWord\SimpleType\VerticalJc; use PhpOffice\PhpWordTests\Writer\HTML\Helper; use PHPUnit\Framework\TestCase; @@ -162,4 +162,29 @@ public function testWriteTableBorders(): void self::assertNotFalse(preg_match('/^[.]tstyle[^\\r\\n]*/m', $style, $matches)); self::assertEquals(".tstyle {table-layout: auto; $cssnone}", $matches[0]); } + + public function testWriteTableCellVAlign(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + + $table = $section->addTable(); + $row = $table->addRow(); + + $cell = $row->addCell(); + $cell->addText('top text'); + $cell->getStyle()->setVAlign(VerticalJc::TOP); + + $cell = $row->addCell(); + $cell->addText('bottom text'); + $cell->getStyle()->setVAlign(VerticalJc::BOTTOM); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + $cell1Style = Helper::getTextContent($xpath, '//table/tr/td[1]', 'style'); + $cell2Style = Helper::getTextContent($xpath, '//table/tr/td[2]', 'style'); + self::assertSame('vertical-align: top;', $cell1Style); + self::assertSame('vertical-align: bottom;', $cell2Style); + } } From f0ec497cfc6a2880f755c4f761f784b5ef3078fe Mon Sep 17 00:00:00 2001 From: Christian Koop <c.koop@ryze-digital.de> Date: Fri, 13 Sep 2024 16:19:48 +0200 Subject: [PATCH 215/246] fix: Allow vAlign and vMerge on Style\Cell to be set to null (#2676) * fix: Allow vAlign and vMerge on Style\Cell to be set to null (#2673) vAlign and vMerge are initialized as `null` in every style until it is explicitly set. Right now, it is not possible to unset them, after it has been set once. I've added a null-check to skip the validation, based on the default parameter value of `null`, which indicates to me that it once was intended to work like this. I've also fixed the type-hints, which were wrong from the start. * docs(changelog): Add note about supporting vAlign and vMerge to be unset * test: Extend existing table test case to check if unsetting vAlign works * test: Add test case to check if unsetting vMerge works This should fix the reduction in test coverage because of the new null checking code in the Setter --- docs/changes/1.x/1.4.0.md | 1 + src/PhpWord/Style/Cell.php | 24 +++++++--- .../Writer/HTML/Element/TableTest.php | 44 +++++++++++++++++++ 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index ebd3ad4029..13d9bc0937 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -10,6 +10,7 @@ ### Bug fixes - Writer ODText: Support for images inside a textRun by [@Progi1984](https://github.com/Progi1984) fixing [#2240](https://github.com/PHPOffice/PHPWord/issues/2240) in [#2668](https://github.com/PHPOffice/PHPWord/pull/2668) +- Allow vAlign and vMerge on Style\Cell to be set to null by [@SpraxDev](https://github.com/SpraxDev) fixing [#2673](https://github.com/PHPOffice/PHPWord/issues/2673) in [#2676](https://github.com/PHPOffice/PHPWord/pull/2676) ### Miscellaneous diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index 3246471fd5..0888d52083 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -69,7 +69,7 @@ class Cell extends Border /** * Vertical align (top, center, both, bottom). * - * @var string + * @var null|string */ private $vAlign; @@ -93,7 +93,7 @@ class Cell extends Border * - restart: Start/restart merged region * - continue: Continue merged region * - * @var string + * @var null|string */ private $vMerge; @@ -128,7 +128,7 @@ class Cell extends Border /** * Get vertical align. * - * @return string + * @return null|string */ public function getVAlign() { @@ -138,12 +138,18 @@ public function getVAlign() /** * Set vertical align. * - * @param string $value + * @param null|string $value * * @return self */ public function setVAlign($value = null) { + if ($value === null) { + $this->vAlign = null; + + return $this; + } + VerticalJc::validate($value); $this->vAlign = $this->setEnumVal($value, VerticalJc::values(), $this->vAlign); @@ -235,7 +241,7 @@ public function setGridSpan($value = null) /** * Get vertical merge (rowspan). * - * @return string + * @return null|string */ public function getVMerge() { @@ -245,12 +251,18 @@ public function getVMerge() /** * Set vertical merge (rowspan). * - * @param string $value + * @param null|string $value * * @return self */ public function setVMerge($value = null) { + if ($value === null) { + $this->vMerge = null; + + return $this; + } + $enum = [self::VMERGE_RESTART, self::VMERGE_CONTINUE]; $this->vMerge = $this->setEnumVal($value, $enum, $this->vMerge); diff --git a/tests/PhpWordTests/Writer/HTML/Element/TableTest.php b/tests/PhpWordTests/Writer/HTML/Element/TableTest.php index 88b12e7204..8dec922108 100644 --- a/tests/PhpWordTests/Writer/HTML/Element/TableTest.php +++ b/tests/PhpWordTests/Writer/HTML/Element/TableTest.php @@ -20,6 +20,7 @@ use DOMXPath; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\SimpleType\VerticalJc; +use PhpOffice\PhpWord\Style; use PhpOffice\PhpWordTests\Writer\HTML\Helper; use PHPUnit\Framework\TestCase; @@ -179,6 +180,11 @@ public function testWriteTableCellVAlign(): void $cell->addText('bottom text'); $cell->getStyle()->setVAlign(VerticalJc::BOTTOM); + $cell = $row->addCell(); + $cell->addText('no vAlign'); + $cell->getStyle()->setVAlign(VerticalJc::BOTTOM); + $cell->getStyle()->setVAlign(); + $dom = Helper::getAsHTML($phpWord); $xpath = new DOMXPath($dom); @@ -186,5 +192,43 @@ public function testWriteTableCellVAlign(): void $cell2Style = Helper::getTextContent($xpath, '//table/tr/td[2]', 'style'); self::assertSame('vertical-align: top;', $cell1Style); self::assertSame('vertical-align: bottom;', $cell2Style); + + $cell3Query = $xpath->query('//table/tr/td[3]'); + self::assertNotFalse($cell3Query); + self::assertCount(1, $cell3Query); + + $cell3Style = $cell3Query->item(0)->attributes->getNamedItem('style'); + self::assertNull($cell3Style); + } + + public function testWriteTableCellVMerge(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + + $table = $section->addTable(); + + $cell = $table->addRow()->addCell(); + $cell->addText('text'); + $cell->getStyle()->setVMerge(Style\Cell::VMERGE_RESTART); + + $cell = $table->addRow()->addCell(); + $cell->getStyle()->setVMerge(Style\Cell::VMERGE_CONTINUE); + + $cell = $table->addRow()->addCell(); + $cell->addText('no vMerge'); + $cell->getStyle()->setVMerge(Style\Cell::VMERGE_CONTINUE); + $cell->getStyle()->setVMerge(); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + $cell1Style = Helper::getTextContent($xpath, '//table/tr[1]/td[1]', 'rowspan'); + self::assertSame('2', $cell1Style); + + $cell3Query = $xpath->query('//table/tr[3]/td[1]'); + self::assertNotFalse($cell3Query); + self::assertCount(1, $cell3Query); + self::assertNull($cell3Query->item(0)->attributes->getNamedItem('rowspan')); } } From 43785fe76b35d5a5c9338ed943383a2529e30deb Mon Sep 17 00:00:00 2001 From: Christian Koop <c.koop@ryze-digital.de> Date: Fri, 13 Sep 2024 19:58:26 +0200 Subject: [PATCH 216/246] test: Add test case for vMerge's default value of continue (#2677) * test: Add test case for vMerge's default value of continue This new test case essentially covers the changes in b457ff5f7fadf28f4d62d1fcd5b9ee3424392835. It ensures the new behavior works as intended and doesn't break/change by accident in the future. * docs(changelog): Add note about added test case for vMerge default value --- docs/changes/1.x/1.4.0.md | 1 + .../Reader/Word2007/StyleTest.php | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 13d9bc0937..8db845337d 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -15,5 +15,6 @@ ### Miscellaneous - Bump dompdf/dompdf from 2.0.4 to 3.0.0 by [@dependabot](https://github.com/dependabot) fixing [#2621](https://github.com/PHPOffice/PHPWord/issues/2621) in [#2666](https://github.com/PHPOffice/PHPWord/pull/2666) +- Add test case to make sure vMerge defaults to 'continue' by [@SpraxDev](https://github.com/SpraxDev) in [#2677](https://github.com/PHPOffice/PHPWord/pull/2677) ### BC Breaks diff --git a/tests/PhpWordTests/Reader/Word2007/StyleTest.php b/tests/PhpWordTests/Reader/Word2007/StyleTest.php index 015a3cfcb7..f622c57e90 100644 --- a/tests/PhpWordTests/Reader/Word2007/StyleTest.php +++ b/tests/PhpWordTests/Reader/Word2007/StyleTest.php @@ -165,6 +165,44 @@ public function testReadTableCellStyle(): void self::assertEquals('auto', $styleCell->getBorderBottomColor()); } + public function testReadTableCellsWithVerticalMerge(): void + { + $documentXml = '<w:tbl> + <w:tr> + <w:tc> + <w:tcPr> + <w:vMerge w:val="restart" /> + </w:tcPr> + </w:tc> + </w:tr> + <w:tr> + <w:tc> + <w:tcPr> + <w:vMerge /> + </w:tcPr> + </w:tc> + </w:tr> + <w:tr> + <w:tc /> + </w:tr> + </w:tbl>'; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $table = $phpWord->getSection(0)->getElements()[0]; + self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $table); + + $rows = $table->getRows(); + self::assertCount(3, $rows); + foreach ($rows as $row) { + self::assertCount(1, $row->getCells()); + } + + self::assertSame('restart', $rows[0]->getCells()[0]->getStyle()->getVMerge()); + self::assertSame('continue', $rows[1]->getCells()[0]->getStyle()->getVMerge()); + self::assertNull($rows[2]->getCells()[0]->getStyle()->getVMerge()); + } + /** * Test reading of position. */ From feadceb1f8ac977497ea7a4a80d0cfd9cffb13ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BCrk?= <stefan@buerk.tech> Date: Sat, 12 Oct 2024 08:45:12 +0200 Subject: [PATCH 217/246] [BUGFIX] Remove invalid tool call from composer `check` script (#2600) With commit [1] development dependencies have been removed from the `composer.json`, but not from the `composer.lock`. This indicates a inproper use of `composer` and should be taken care in review of pull-requests. A good practice here is to etablish a rule that composer commands needs to be added to the commit message and the pull-request. Other removed dependency and downgraded dependencies have been fixed or readded meanwhile, still missing the `phpcs` tool for the `check composer script`. The `CONTRIBUTION.md` states to execute `composer check` before creating a pull-request, which is literally broken due to the missing dependency. This change removes the php sniffer call from the check script. Additionally, the composer scripts are enhanced to use the same php binary used to invoke composer itself to mitigate issues using the wrong php version on systems with multiple php version binaries. Further consideration should be to use the check command in the Github Action workflow to have a border if development toolchain is gonna be broken with a change. [1] https://github.com/PHPOffice/PHPWord/commit/c3e34a0d24070d7f52014c9ca6229d3f252f73c8 --- composer.json | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index d267f08460..9633fe01da 100644 --- a/composer.json +++ b/composer.json @@ -36,20 +36,19 @@ ], "scripts": { "test": [ - "phpunit --color=always" + "@php vendor/bin/phpunit --color=always" ], "test-no-coverage": [ - "phpunit --color=always --no-coverage" + "@php vendor/bin/phpunit --color=always --no-coverage" ], "check": [ - "php-cs-fixer fix --ansi --dry-run --diff", - "phpcs --report-width=200 --report-summary --report-full samples/ src/ tests/ --ignore=src/PhpWord/Shared/PCLZip --standard=PSR2 -n", - "phpmd src/,tests/ text ./phpmd.xml.dist --exclude pclzip.lib.php", + "@php vendor/bin/php-cs-fixer fix --ansi --dry-run --diff", + "@php vendor/bin/phpmd src/,tests/ text ./phpmd.xml.dist --exclude pclzip.lib.php", "@test-no-coverage", - "phpstan analyse --ansi" + "@php vendor/bin/phpstan analyse --ansi" ], "fix": [ - "php-cs-fixer fix --ansi" + "@php vendor/bin/php-cs-fixer fix --ansi" ] }, "scripts-descriptions": { From f24aabca176858b5b549d7425e33fa5cde30e0a9 Mon Sep 17 00:00:00 2001 From: "Jason N. White" <sufssl04@gmail.com> Date: Wed, 1 Jan 2025 04:15:53 -0500 Subject: [PATCH 218/246] Update LICENSE, fix license year (#2719) Signed-off-by: JasonnnW3000 <sufssl04@gmail.com> --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 8a1acaeaba..aebd12b0ed 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ PHPWord, a pure PHP library for reading and writing word processing documents. -Copyright (c) 2010-2016 PHPWord. +Copyright (c) 2010-2025 PHPWord. PHPWord is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3 as published by From b28557852c65977f97002720d4bf5c1a3a2083d6 Mon Sep 17 00:00:00 2001 From: Progi1984 <progi1984@gmail.com> Date: Tue, 7 Jan 2025 21:00:36 +0100 Subject: [PATCH 219/246] Added support for PHP 8.4 (#2660) --- .github/workflows/php.yml | 237 +- .gitignore | 3 + composer.json | 69 +- composer.lock | 5093 ----------------- docs/changes/1.x/1.4.0.md | 1 + docs/howto.md | 2 +- phpstan-baseline.neon | 120 +- phpstan.neon | 19 - phpstan.neon.dist | 44 + samples/Sample_01_SimpleText.php | 10 +- samples/Sample_02_TabStops.php | 12 +- samples/Sample_03_Sections.php | 2 +- samples/Sample_04_Textrun.php | 8 +- samples/Sample_05_Multicolumn.php | 2 +- samples/Sample_06_Footnote.php | 10 +- samples/Sample_07_TemplateCloneRow.php | 6 +- samples/Sample_08_ParagraphPagination.php | 6 +- samples/Sample_09_Tables.php | 12 +- samples/Sample_10_EastAsianFontStyle.php | 2 +- samples/Sample_11_ReadWord2007.php | 2 +- samples/Sample_11_ReadWord97.php | 4 +- samples/Sample_12_HeaderFooter.php | 8 +- samples/Sample_13_Images.php | 32 +- samples/Sample_14_ListItem.php | 4 +- samples/Sample_15_Link.php | 4 +- samples/Sample_16_Object.php | 4 +- samples/Sample_17_TitleTOC.php | 2 +- samples/Sample_18_Watermark.php | 4 +- samples/Sample_19_TextBreak.php | 2 +- samples/Sample_20_BGColor.php | 4 +- samples/Sample_21_TableRowRules.php | 6 +- samples/Sample_22_CheckBox.php | 2 +- samples/Sample_23_TemplateBlock.php | 6 +- samples/Sample_24_ReadODText.php | 2 +- samples/Sample_25_TextBox.php | 6 +- samples/Sample_26_Html.php | 4 +- samples/Sample_27_Field.php | 4 +- samples/Sample_28_ReadRTF.php | 2 +- samples/Sample_29_Line.php | 30 +- samples/Sample_30_ReadHTML.php | 2 +- samples/Sample_31_Shape.php | 2 +- samples/Sample_32_Chart.php | 2 +- samples/Sample_33_FormField.php | 2 +- samples/Sample_34_SDT.php | 2 +- samples/Sample_35_InternalLink.php | 2 +- samples/Sample_36_RTL.php | 12 +- samples/Sample_37_Comments.php | 14 +- samples/Sample_38_Protection.php | 2 +- samples/Sample_39_TrackChanges.php | 4 +- samples/Sample_40_TemplateSetComplexValue.php | 6 +- samples/Sample_41_TemplateSetChart.php | 6 +- ..._44_ExtractVariablesFromReaderWord2007.php | 2 +- samples/Sample_Header.php | 2 +- src/PhpWord/Collection/AbstractCollection.php | 2 + src/PhpWord/Collection/Bookmarks.php | 2 + src/PhpWord/Collection/Charts.php | 2 + src/PhpWord/Collection/Comments.php | 2 + src/PhpWord/Collection/Endnotes.php | 2 + src/PhpWord/Collection/Footnotes.php | 2 + src/PhpWord/Collection/Titles.php | 2 + .../ComplexType/FootnoteProperties.php | 1 + src/PhpWord/ComplexType/ProofState.php | 1 + src/PhpWord/ComplexType/TblWidth.php | 1 + src/PhpWord/ComplexType/TrackChangesView.php | 1 + src/PhpWord/Element/AbstractContainer.php | 17 +- src/PhpWord/Element/AbstractElement.php | 13 +- src/PhpWord/Element/Bookmark.php | 1 + src/PhpWord/Element/Cell.php | 7 +- src/PhpWord/Element/Chart.php | 5 +- src/PhpWord/Element/CheckBox.php | 1 + src/PhpWord/Element/Comment.php | 5 +- src/PhpWord/Element/Endnote.php | 1 + src/PhpWord/Element/Field.php | 11 +- src/PhpWord/Element/Footer.php | 1 + src/PhpWord/Element/Footnote.php | 7 +- src/PhpWord/Element/FormField.php | 1 + src/PhpWord/Element/Formula.php | 1 + src/PhpWord/Element/Header.php | 1 + src/PhpWord/Element/Image.php | 1 + src/PhpWord/Element/Line.php | 5 +- src/PhpWord/Element/Link.php | 9 +- src/PhpWord/Element/ListItem.php | 9 +- src/PhpWord/Element/ListItemRun.php | 5 +- src/PhpWord/Element/OLEObject.php | 5 +- src/PhpWord/Element/PageBreak.php | 1 + src/PhpWord/Element/PreserveText.php | 9 +- src/PhpWord/Element/Row.php | 11 +- src/PhpWord/Element/SDT.php | 1 + src/PhpWord/Element/Section.php | 9 +- src/PhpWord/Element/Shape.php | 5 +- src/PhpWord/Element/TOC.php | 11 +- src/PhpWord/Element/Table.php | 15 +- src/PhpWord/Element/Text.php | 19 +- src/PhpWord/Element/TextBox.php | 5 +- src/PhpWord/Element/TextBreak.php | 15 +- src/PhpWord/Element/TextRun.php | 1 + src/PhpWord/Element/Title.php | 1 + src/PhpWord/Element/TrackChange.php | 1 + src/PhpWord/Escaper/AbstractEscaper.php | 1 + src/PhpWord/Escaper/EscaperInterface.php | 1 + src/PhpWord/Escaper/RegExp.php | 1 + src/PhpWord/Escaper/Rtf.php | 1 + src/PhpWord/Escaper/Xml.php | 1 + src/PhpWord/Exception/CopyFileException.php | 1 + .../CreateTemporaryFileException.php | 1 + src/PhpWord/Exception/Exception.php | 1 + .../Exception/InvalidImageException.php | 1 + .../Exception/InvalidObjectException.php | 1 + .../Exception/InvalidStyleException.php | 1 + .../UnsupportedImageTypeException.php | 1 + src/PhpWord/IOFactory.php | 11 +- src/PhpWord/Media.php | 1 + src/PhpWord/Metadata/Compatibility.php | 1 + src/PhpWord/Metadata/DocInfo.php | 1 + src/PhpWord/Metadata/Protection.php | 1 + src/PhpWord/Metadata/Settings.php | 7 +- src/PhpWord/PhpWord.php | 23 +- src/PhpWord/Reader/AbstractReader.php | 1 + src/PhpWord/Reader/HTML.php | 3 +- src/PhpWord/Reader/MsDoc.php | 1 + src/PhpWord/Reader/ODText.php | 5 +- src/PhpWord/Reader/ODText/AbstractPart.php | 1 + src/PhpWord/Reader/ODText/Content.php | 1 + src/PhpWord/Reader/ODText/Meta.php | 1 + src/PhpWord/Reader/RTF.php | 3 +- src/PhpWord/Reader/RTF/Document.php | 3 +- src/PhpWord/Reader/ReaderInterface.php | 1 + src/PhpWord/Reader/Word2007.php | 3 +- src/PhpWord/Reader/Word2007/AbstractPart.php | 5 +- src/PhpWord/Reader/Word2007/DocPropsApp.php | 1 + src/PhpWord/Reader/Word2007/DocPropsCore.php | 1 + .../Reader/Word2007/DocPropsCustom.php | 1 + src/PhpWord/Reader/Word2007/Document.php | 3 +- src/PhpWord/Reader/Word2007/Endnotes.php | 1 + src/PhpWord/Reader/Word2007/Footnotes.php | 1 + src/PhpWord/Reader/Word2007/Numbering.php | 1 + src/PhpWord/Reader/Word2007/Settings.php | 1 + src/PhpWord/Reader/Word2007/Styles.php | 1 + src/PhpWord/Settings.php | 3 +- src/PhpWord/Shared/AbstractEnum.php | 1 + src/PhpWord/Shared/Converter.php | 1 + src/PhpWord/Shared/Css.php | 5 +- src/PhpWord/Shared/Drawing.php | 1 + src/PhpWord/Shared/Html.php | 46 +- .../Shared/Microsoft/PasswordEncoder.php | 1 + src/PhpWord/Shared/Text.php | 1 + src/PhpWord/Shared/Validate.php | 1 + src/PhpWord/Shared/XMLReader.php | 1 + src/PhpWord/Shared/XMLWriter.php | 1 + src/PhpWord/Shared/ZipArchive.php | 7 +- src/PhpWord/SimpleType/Border.php | 1 + src/PhpWord/SimpleType/DocProtect.php | 1 + src/PhpWord/SimpleType/Jc.php | 3 +- src/PhpWord/SimpleType/JcTable.php | 1 + src/PhpWord/SimpleType/LineSpacingRule.php | 1 + src/PhpWord/SimpleType/NumberFormat.php | 1 + src/PhpWord/SimpleType/TblWidth.php | 1 + src/PhpWord/SimpleType/TextAlignment.php | 1 + src/PhpWord/SimpleType/VerticalJc.php | 1 + src/PhpWord/SimpleType/Zoom.php | 1 + src/PhpWord/Style.php | 15 +- src/PhpWord/Style/AbstractStyle.php | 7 +- src/PhpWord/Style/Border.php | 1 + src/PhpWord/Style/Cell.php | 5 +- src/PhpWord/Style/Chart.php | 1 + src/PhpWord/Style/Extrusion.php | 1 + src/PhpWord/Style/Fill.php | 1 + src/PhpWord/Style/Font.php | 17 +- src/PhpWord/Style/Frame.php | 1 + src/PhpWord/Style/Image.php | 1 + src/PhpWord/Style/Indentation.php | 1 + src/PhpWord/Style/Language.php | 1 + src/PhpWord/Style/Line.php | 1 + src/PhpWord/Style/LineNumbering.php | 1 + src/PhpWord/Style/ListItem.php | 1 + src/PhpWord/Style/Numbering.php | 1 + src/PhpWord/Style/NumberingLevel.php | 1 + src/PhpWord/Style/Outline.php | 1 + src/PhpWord/Style/Paper.php | 1 + src/PhpWord/Style/Paragraph.php | 19 +- src/PhpWord/Style/Row.php | 1 + src/PhpWord/Style/Section.php | 11 +- src/PhpWord/Style/Shading.php | 1 + src/PhpWord/Style/Shadow.php | 1 + src/PhpWord/Style/Shape.php | 21 +- src/PhpWord/Style/Spacing.php | 1 + src/PhpWord/Style/TOC.php | 1 + src/PhpWord/Style/Tab.php | 1 + src/PhpWord/Style/Table.php | 13 +- src/PhpWord/Style/TablePosition.php | 1 + src/PhpWord/Style/TextBox.php | 1 + src/PhpWord/TemplateProcessor.php | 20 +- src/PhpWord/Writer/AbstractWriter.php | 11 +- src/PhpWord/Writer/HTML.php | 3 +- .../Writer/HTML/Element/AbstractElement.php | 3 +- src/PhpWord/Writer/HTML/Element/Bookmark.php | 1 + src/PhpWord/Writer/HTML/Element/Container.php | 3 +- src/PhpWord/Writer/HTML/Element/Endnote.php | 1 + src/PhpWord/Writer/HTML/Element/Footnote.php | 1 + src/PhpWord/Writer/HTML/Element/Image.php | 1 + src/PhpWord/Writer/HTML/Element/Link.php | 1 + src/PhpWord/Writer/HTML/Element/ListItem.php | 1 + .../Writer/HTML/Element/ListItemRun.php | 1 + src/PhpWord/Writer/HTML/Element/PageBreak.php | 1 + src/PhpWord/Writer/HTML/Element/Table.php | 1 + src/PhpWord/Writer/HTML/Element/Text.php | 1 + src/PhpWord/Writer/HTML/Element/TextBreak.php | 1 + src/PhpWord/Writer/HTML/Element/TextRun.php | 1 + src/PhpWord/Writer/HTML/Element/Title.php | 1 + src/PhpWord/Writer/HTML/Part/AbstractPart.php | 1 + src/PhpWord/Writer/HTML/Part/Body.php | 1 + src/PhpWord/Writer/HTML/Part/Head.php | 1 + .../Writer/HTML/Style/AbstractStyle.php | 1 + src/PhpWord/Writer/HTML/Style/Font.php | 1 + src/PhpWord/Writer/HTML/Style/Generic.php | 1 + src/PhpWord/Writer/HTML/Style/Image.php | 1 + src/PhpWord/Writer/HTML/Style/Paragraph.php | 1 + src/PhpWord/Writer/HTML/Style/Table.php | 1 + src/PhpWord/Writer/ODText.php | 3 +- .../Writer/ODText/Element/AbstractElement.php | 1 + .../Writer/ODText/Element/Container.php | 1 + src/PhpWord/Writer/ODText/Element/Field.php | 1 + src/PhpWord/Writer/ODText/Element/Formula.php | 1 + src/PhpWord/Writer/ODText/Element/Image.php | 1 + src/PhpWord/Writer/ODText/Element/Link.php | 1 + .../Writer/ODText/Element/ListItemRun.php | 1 + .../Writer/ODText/Element/PageBreak.php | 1 + src/PhpWord/Writer/ODText/Element/Table.php | 5 +- src/PhpWord/Writer/ODText/Element/Text.php | 1 + .../Writer/ODText/Element/TextBreak.php | 1 + src/PhpWord/Writer/ODText/Element/TextRun.php | 1 + src/PhpWord/Writer/ODText/Element/Title.php | 1 + .../Writer/ODText/Part/AbstractPart.php | 1 + src/PhpWord/Writer/ODText/Part/Content.php | 13 +- src/PhpWord/Writer/ODText/Part/Manifest.php | 1 + src/PhpWord/Writer/ODText/Part/Meta.php | 1 + src/PhpWord/Writer/ODText/Part/Mimetype.php | 1 + src/PhpWord/Writer/ODText/Part/Styles.php | 1 + .../Writer/ODText/Style/AbstractStyle.php | 1 + src/PhpWord/Writer/ODText/Style/Font.php | 3 +- src/PhpWord/Writer/ODText/Style/Image.php | 1 + src/PhpWord/Writer/ODText/Style/Numbering.php | 5 +- src/PhpWord/Writer/ODText/Style/Paragraph.php | 9 +- src/PhpWord/Writer/ODText/Style/Section.php | 1 + src/PhpWord/Writer/ODText/Style/Table.php | 1 + src/PhpWord/Writer/PDF.php | 3 +- src/PhpWord/Writer/PDF/AbstractRenderer.php | 1 + src/PhpWord/Writer/PDF/DomPDF.php | 1 + src/PhpWord/Writer/PDF/MPDF.php | 1 + src/PhpWord/Writer/PDF/TCPDF.php | 1 + src/PhpWord/Writer/RTF.php | 3 +- .../Writer/RTF/Element/AbstractElement.php | 11 +- src/PhpWord/Writer/RTF/Element/Container.php | 1 + src/PhpWord/Writer/RTF/Element/Field.php | 1 + src/PhpWord/Writer/RTF/Element/Image.php | 1 + src/PhpWord/Writer/RTF/Element/Link.php | 1 + src/PhpWord/Writer/RTF/Element/ListItem.php | 1 + src/PhpWord/Writer/RTF/Element/PageBreak.php | 1 + src/PhpWord/Writer/RTF/Element/Table.php | 1 + src/PhpWord/Writer/RTF/Element/Text.php | 1 + src/PhpWord/Writer/RTF/Element/TextBreak.php | 1 + src/PhpWord/Writer/RTF/Element/TextRun.php | 1 + src/PhpWord/Writer/RTF/Element/Title.php | 1 + src/PhpWord/Writer/RTF/Part/AbstractPart.php | 1 + src/PhpWord/Writer/RTF/Part/Document.php | 9 +- src/PhpWord/Writer/RTF/Part/Header.php | 5 +- .../Writer/RTF/Style/AbstractStyle.php | 1 + src/PhpWord/Writer/RTF/Style/Border.php | 1 + src/PhpWord/Writer/RTF/Style/Font.php | 1 + src/PhpWord/Writer/RTF/Style/Indentation.php | 1 + src/PhpWord/Writer/RTF/Style/Paragraph.php | 1 + src/PhpWord/Writer/RTF/Style/Section.php | 1 + src/PhpWord/Writer/RTF/Style/Tab.php | 1 + src/PhpWord/Writer/Word2007.php | 11 +- .../Word2007/Element/AbstractElement.php | 9 +- .../Writer/Word2007/Element/Bookmark.php | 1 + src/PhpWord/Writer/Word2007/Element/Chart.php | 1 + .../Writer/Word2007/Element/CheckBox.php | 1 + .../Writer/Word2007/Element/Container.php | 5 +- .../Writer/Word2007/Element/Endnote.php | 1 + src/PhpWord/Writer/Word2007/Element/Field.php | 5 +- .../Writer/Word2007/Element/Footnote.php | 1 + .../Writer/Word2007/Element/FormField.php | 1 + .../Writer/Word2007/Element/Formula.php | 1 + src/PhpWord/Writer/Word2007/Element/Image.php | 1 + src/PhpWord/Writer/Word2007/Element/Line.php | 1 + src/PhpWord/Writer/Word2007/Element/Link.php | 1 + .../Writer/Word2007/Element/ListItem.php | 1 + .../Writer/Word2007/Element/ListItemRun.php | 1 + .../Writer/Word2007/Element/OLEObject.php | 1 + .../Writer/Word2007/Element/PageBreak.php | 1 + .../Word2007/Element/ParagraphAlignment.php | 1 + .../Writer/Word2007/Element/PreserveText.php | 1 + src/PhpWord/Writer/Word2007/Element/SDT.php | 1 + src/PhpWord/Writer/Word2007/Element/Shape.php | 1 + src/PhpWord/Writer/Word2007/Element/TOC.php | 1 + src/PhpWord/Writer/Word2007/Element/Table.php | 1 + .../Word2007/Element/TableAlignment.php | 1 + src/PhpWord/Writer/Word2007/Element/Text.php | 1 + .../Writer/Word2007/Element/TextBox.php | 1 + .../Writer/Word2007/Element/TextBreak.php | 1 + .../Writer/Word2007/Element/TextRun.php | 1 + src/PhpWord/Writer/Word2007/Element/Title.php | 1 + .../Writer/Word2007/Part/AbstractPart.php | 7 +- src/PhpWord/Writer/Word2007/Part/Chart.php | 3 +- src/PhpWord/Writer/Word2007/Part/Comments.php | 5 +- .../Writer/Word2007/Part/ContentTypes.php | 3 +- .../Writer/Word2007/Part/DocPropsApp.php | 1 + .../Writer/Word2007/Part/DocPropsCore.php | 1 + .../Writer/Word2007/Part/DocPropsCustom.php | 1 + src/PhpWord/Writer/Word2007/Part/Document.php | 1 + src/PhpWord/Writer/Word2007/Part/Endnotes.php | 1 + .../Writer/Word2007/Part/FontTable.php | 1 + src/PhpWord/Writer/Word2007/Part/Footer.php | 1 + .../Writer/Word2007/Part/Footnotes.php | 3 +- src/PhpWord/Writer/Word2007/Part/Header.php | 1 + .../Writer/Word2007/Part/Numbering.php | 3 +- src/PhpWord/Writer/Word2007/Part/Rels.php | 1 + .../Writer/Word2007/Part/RelsDocument.php | 1 + src/PhpWord/Writer/Word2007/Part/RelsPart.php | 1 + src/PhpWord/Writer/Word2007/Part/Settings.php | 3 +- src/PhpWord/Writer/Word2007/Part/Styles.php | 5 +- src/PhpWord/Writer/Word2007/Part/Theme.php | 1 + .../Writer/Word2007/Part/WebSettings.php | 1 + .../Writer/Word2007/Style/AbstractStyle.php | 7 +- src/PhpWord/Writer/Word2007/Style/Cell.php | 1 + .../Writer/Word2007/Style/Extrusion.php | 1 + src/PhpWord/Writer/Word2007/Style/Fill.php | 1 + src/PhpWord/Writer/Word2007/Style/Font.php | 1 + src/PhpWord/Writer/Word2007/Style/Frame.php | 1 + src/PhpWord/Writer/Word2007/Style/Image.php | 1 + .../Writer/Word2007/Style/Indentation.php | 1 + src/PhpWord/Writer/Word2007/Style/Line.php | 1 + .../Writer/Word2007/Style/LineNumbering.php | 1 + .../Writer/Word2007/Style/MarginBorder.php | 1 + src/PhpWord/Writer/Word2007/Style/Outline.php | 1 + .../Writer/Word2007/Style/Paragraph.php | 5 +- src/PhpWord/Writer/Word2007/Style/Row.php | 1 + src/PhpWord/Writer/Word2007/Style/Section.php | 1 + src/PhpWord/Writer/Word2007/Style/Shading.php | 1 + src/PhpWord/Writer/Word2007/Style/Shadow.php | 1 + src/PhpWord/Writer/Word2007/Style/Shape.php | 1 + src/PhpWord/Writer/Word2007/Style/Spacing.php | 1 + src/PhpWord/Writer/Word2007/Style/Tab.php | 1 + src/PhpWord/Writer/Word2007/Style/Table.php | 1 + .../Writer/Word2007/Style/TablePosition.php | 1 + src/PhpWord/Writer/Word2007/Style/TextBox.php | 1 + src/PhpWord/Writer/WriterInterface.php | 1 + tests/PhpWordTests/AbstractTestReader.php | 3 +- ...Test.php => AbstractWebServerEmbedded.php} | 3 +- .../Collection/CollectionTest.php | 1 + .../ComplexType/FootnotePropertiesTest.php | 1 + .../ComplexType/ProofStateTest.php | 1 + .../Element/AbstractElementTest.php | 1 + tests/PhpWordTests/Element/BookmarkTest.php | 1 + tests/PhpWordTests/Element/CellTest.php | 5 +- tests/PhpWordTests/Element/CheckBoxTest.php | 1 + tests/PhpWordTests/Element/CommentTest.php | 1 + tests/PhpWordTests/Element/FieldTest.php | 1 + tests/PhpWordTests/Element/FooterTest.php | 5 +- tests/PhpWordTests/Element/FootnoteTest.php | 1 + tests/PhpWordTests/Element/FormulaTest.php | 5 +- tests/PhpWordTests/Element/HeaderTest.php | 5 +- tests/PhpWordTests/Element/ImageTest.php | 9 +- tests/PhpWordTests/Element/LineTest.php | 1 + tests/PhpWordTests/Element/LinkTest.php | 1 + .../PhpWordTests/Element/ListItemRunTest.php | 1 + tests/PhpWordTests/Element/ListItemTest.php | 1 + tests/PhpWordTests/Element/ObjectTest.php | 1 + tests/PhpWordTests/Element/PageBreakTest.php | 1 + .../PhpWordTests/Element/PreserveTextTest.php | 1 + tests/PhpWordTests/Element/RowTest.php | 1 + tests/PhpWordTests/Element/SDTTest.php | 1 + tests/PhpWordTests/Element/SectionTest.php | 1 + tests/PhpWordTests/Element/TOCTest.php | 1 + tests/PhpWordTests/Element/TableTest.php | 1 + tests/PhpWordTests/Element/TextBoxTest.php | 1 + tests/PhpWordTests/Element/TextBreakTest.php | 1 + tests/PhpWordTests/Element/TextRunTest.php | 1 + tests/PhpWordTests/Element/TextTest.php | 1 + tests/PhpWordTests/Element/TitleTest.php | 1 + .../PhpWordTests/Element/TrackChangeTest.php | 1 + .../PhpWordTests/Escaper/RtfEscaper2Test.php | 1 + .../PhpWordTests/Escaper/RtfEscaper3Test.php | 3 +- .../Exception/CopyFileExceptionTest.php | 3 +- .../CreateTemporaryFileExceptionTest.php | 3 +- .../PhpWordTests/Exception/ExceptionTest.php | 1 + .../Exception/InvalidImageExceptionTest.php | 3 +- .../Exception/InvalidStyleExceptionTest.php | 3 +- .../UnsupportedImageTypeExceptionTest.php | 3 +- tests/PhpWordTests/IOFactoryTest.php | 1 + tests/PhpWordTests/MediaTest.php | 3 +- tests/PhpWordTests/Metadata/DocInfoTest.php | 1 + tests/PhpWordTests/Metadata/SettingsTest.php | 1 + tests/PhpWordTests/PhpWordTest.php | 1 + tests/PhpWordTests/Reader/HTMLTest.php | 1 + tests/PhpWordTests/Reader/MsDocTest.php | 1 + .../Reader/ODText/ODTextSectionTest.php | 1 + tests/PhpWordTests/Reader/ODTextTest.php | 1 + tests/PhpWordTests/Reader/RTFTest.php | 1 + .../Reader/Word2007/ElementTest.php | 5 +- .../PhpWordTests/Reader/Word2007/PartTest.php | 1 + .../Reader/Word2007/StyleTest.php | 13 +- tests/PhpWordTests/Reader/Word2007Test.php | 39 +- tests/PhpWordTests/SettingsTest.php | 1 + tests/PhpWordTests/Shared/ConverterTest.php | 1 + tests/PhpWordTests/Shared/CssTest.php | 1 + tests/PhpWordTests/Shared/DrawingTest.php | 1 + tests/PhpWordTests/Shared/HtmlTest.php | 9 +- .../Shared/Microsoft/PasswordEncoderTest.php | 1 + tests/PhpWordTests/Shared/TextTest.php | 1 + tests/PhpWordTests/Shared/ValidateTest.php | 1 + tests/PhpWordTests/Shared/XMLReaderTest.php | 1 + tests/PhpWordTests/Shared/XMLWriterTest.php | 1 + tests/PhpWordTests/Shared/ZipArchiveTest.php | 5 +- .../PhpWordTests/Style/AbstractStyleTest.php | 1 + tests/PhpWordTests/Style/CellTest.php | 1 + tests/PhpWordTests/Style/ChartTest.php | 1 + tests/PhpWordTests/Style/FontTest.php | 1 + tests/PhpWordTests/Style/ImageTest.php | 11 +- tests/PhpWordTests/Style/IndentationTest.php | 1 + tests/PhpWordTests/Style/LanguageTest.php | 1 + .../PhpWordTests/Style/LineNumberingTest.php | 1 + tests/PhpWordTests/Style/LineTest.php | 25 +- tests/PhpWordTests/Style/ListItemTest.php | 1 + .../PhpWordTests/Style/NumberingLevelTest.php | 1 + tests/PhpWordTests/Style/NumberingTest.php | 1 + tests/PhpWordTests/Style/PaperTest.php | 1 + tests/PhpWordTests/Style/ParagraphTest.php | 1 + tests/PhpWordTests/Style/RowTest.php | 1 + tests/PhpWordTests/Style/SectionTest.php | 1 + tests/PhpWordTests/Style/ShadingTest.php | 1 + tests/PhpWordTests/Style/SpacingTest.php | 1 + tests/PhpWordTests/Style/TOCTest.php | 1 + tests/PhpWordTests/Style/TabTest.php | 1 + .../PhpWordTests/Style/TablePositionTest.php | 1 + tests/PhpWordTests/Style/TableTest.php | 1 + tests/PhpWordTests/Style/TextBoxTest.php | 1 + tests/PhpWordTests/StyleTest.php | 1 + tests/PhpWordTests/TemplateProcessorTest.php | 11 +- tests/PhpWordTests/TestHelperDOCX.php | 3 +- .../PhpWordTests/TestableTemplateProcesor.php | 1 + .../Writer/HTML/DirectionTest.php | 1 + .../Writer/HTML/Element/PageBreakTest.php | 1 + .../Writer/HTML/Element/TableTest.php | 1 + .../PhpWordTests/Writer/HTML/ElementTest.php | 1 + tests/PhpWordTests/Writer/HTML/FontTest.php | 21 + tests/PhpWordTests/Writer/HTML/Helper.php | 1 + .../Writer/HTML/ParagraphTest.php | 1 + tests/PhpWordTests/Writer/HTML/PartTest.php | 1 + tests/PhpWordTests/Writer/HTML/StyleTest.php | 1 + tests/PhpWordTests/Writer/HTMLTest.php | 5 +- .../Writer/ODText/Element/FieldTest.php | 1 + .../Writer/ODText/Element/FormulaTest.php | 1 + .../Writer/ODText/Element/ImageTest.php | 1 + .../Writer/ODText/Element/ListItemRunTest.php | 1 + .../Writer/ODText/ElementTest.php | 5 +- .../Writer/ODText/Part/AbstractPartTest.php | 5 +- .../Writer/ODText/Part/ContentTest.php | 1 + .../Writer/ODText/Part/ManifestTest.php | 1 + .../Writer/ODText/Style/FontTest.php | 5 +- .../Writer/ODText/Style/NumberingTest.php | 1 + .../Writer/ODText/Style/Paragraph2Test.php | 1 + .../Writer/ODText/Style/ParagraphTest.php | 7 +- .../Writer/ODText/Style/SectionTest.php | 3 +- .../PhpWordTests/Writer/ODText/StyleTest.php | 1 + tests/PhpWordTests/Writer/ODTextTest.php | 1 + tests/PhpWordTests/Writer/PDF/DomPDFTest.php | 1 + tests/PhpWordTests/Writer/PDF/MPDFTest.php | 1 + tests/PhpWordTests/Writer/PDF/TCPDFTest.php | 1 + tests/PhpWordTests/Writer/PDFTest.php | 1 + .../Writer/RTF/Element/TableTest.php | 3 +- .../PhpWordTests/Writer/RTF/Element2Test.php | 1 + tests/PhpWordTests/Writer/RTF/ElementTest.php | 21 +- .../Writer/RTF/HeaderFooterTest.php | 1 + tests/PhpWordTests/Writer/RTF/StyleTest.php | 19 +- tests/PhpWordTests/Writer/RTFTest.php | 1 + .../Writer/Word2007/Element/ChartTest.php | 1 + .../Writer/Word2007/Element/FieldTest.php | 1 + .../Writer/Word2007/Element/FormFieldTest.php | 1 + .../Writer/Word2007/Element/FormulaTest.php | 1 + .../Writer/Word2007/Element/TOCTest.php | 1 + .../Writer/Word2007/Element/TableTest.php | 1 + .../Writer/Word2007/Element/TitleTest.php | 1 + .../Writer/Word2007/ElementTest.php | 1 + .../Writer/Word2007/Part/AbstractPartTest.php | 5 +- .../Writer/Word2007/Part/CommentsTest.php | 1 + .../Writer/Word2007/Part/DocumentTest.php | 1 + .../Writer/Word2007/Part/FooterTest.php | 1 + .../Writer/Word2007/Part/FootnotesTest.php | 1 + .../Writer/Word2007/Part/HeaderTest.php | 1 + .../Writer/Word2007/Part/NumberingTest.php | 1 + .../Writer/Word2007/Part/SettingsTest.php | 1 + .../Writer/Word2007/Part/StylesTest.php | 1 + .../PhpWordTests/Writer/Word2007/PartTest.php | 1 + .../Writer/Word2007/Style/DirectionTest.php | 1 + .../Writer/Word2007/Style/FontTest.php | 13 +- .../Writer/Word2007/Style/ImageTest.php | 1 + .../Writer/Word2007/Style/ParagraphTest.php | 1 + .../Writer/Word2007/Style/SectionTest.php | 3 +- .../Writer/Word2007/Style/TableTest.php | 1 + .../Writer/Word2007/StyleTest.php | 1 + tests/PhpWordTests/Writer/Word2007Test.php | 5 +- tests/PhpWordTests/XmlDocument.php | 1 + tests/bootstrap.php | 5 +- 505 files changed, 1207 insertions(+), 5910 deletions(-) delete mode 100644 composer.lock delete mode 100644 phpstan.neon create mode 100644 phpstan.neon.dist rename tests/PhpWordTests/{AbstractWebServerEmbeddedTest.php => AbstractWebServerEmbedded.php} (96%) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index ed772171e7..0e2e9ea96d 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -1,165 +1,124 @@ -name: CI -on: - pull_request: - push: - branches: - - master +name: PHPWord +on: [push, pull_request] jobs: - test: + php-cs-fixer: + name: PHP CS Fixer runs-on: ubuntu-latest - strategy: - matrix: - php-version: - - "7.1.3" - - "7.2" - - "7.3" - - "7.4" - - "8.0" - - "8.1" - - "8.2" - - "8.3" - - name: PHP ${{ matrix.php-version }} - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup PHP, with composer and extensions + - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: ${{ matrix.php-version }} - extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: none - - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Cache composer dependencies - uses: actions/cache@v3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Remove lock for old EOL PHP versions - if: matrix.php-version == '7.1.3' || matrix.php-version == '7.2' || matrix.php-version == '7.3' || matrix.php-version == '7.4' - run: rm composer.lock && composer config platform.php ${{ matrix.php-version }} + php-version: '8.3' + extensions: mbstring, intl, gd, xml, dom, json, fileinfo, curl, zip, iconv + - uses: actions/checkout@v2 - - name: Install dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader + - name: Validate composer config + run: composer validate --strict - - name: Setup problem matchers for PHP - run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" + - name: Composer Install + run: composer global require friendsofphp/php-cs-fixer - - name: Setup problem matchers for PHPUnit - run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + - name: Add environment path + run: export PATH="$PATH:$HOME/.composer/vendor/bin" - - name: Configure matchers - uses: mheap/phpunit-matcher-action@v1 + - name: Run PHPCSFixer + run: php-cs-fixer fix --dry-run --diff - - name: Test with PHPUnit - run: ./vendor/bin/phpunit --no-coverage - - php-cs-fixer: + phpmd: + name: PHP Mess Detector runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v3 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.4' + extensions: gd, xml, zip + - uses: actions/checkout@v2 - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: 8.0 - extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: none - tools: cs2pr + - name: Composer Install + run: composer install --ansi --prefer-dist --no-interaction --no-progress - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Cache composer dependencies - uses: actions/cache@v3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Code style with PHP-CS-Fixer - run: ./vendor/bin/php-cs-fixer fix --dry-run --diff + - name: Run phpmd + run: ./vendor/bin/phpmd src/,tests/ text ./phpmd.xml.dist --exclude "src/PhpWord/Shared/PCLZip/*" phpstan: + name: PHP Static Analysis runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # Disabled PHPStan in '7.1' + php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] steps: - - name: Checkout - uses: actions/checkout@v3 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: gd, xml, zip + - uses: actions/checkout@v2 - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: 8.0 - extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: none - tools: cs2pr + - name: Composer Install + run: composer install --ansi --prefer-dist --no-interaction --no-progress - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Cache composer dependencies - uses: actions/cache@v3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- + - name: Run phpstan + run: ./vendor/bin/phpstan analyse -c phpstan.neon.dist - - name: Install dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Static analysis with PHPStan - run: ./vendor/bin/phpstan analyse - - coverage: + phpunit: + name: PHPUnit ${{ matrix.php }} runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: ['7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] steps: - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: gd, xml, zip + coverage: ${{ (matrix.php == '7.3') && 'xdebug' || 'none' }} + + - uses: actions/checkout@v2 + + - name: Composer Install + run: composer install --ansi --prefer-dist --no-interaction --no-progress + + - name: Run phpunit + if: matrix.php != '7.3' + run: ./vendor/bin/phpunit -c phpunit.xml.dist --no-coverage + + - name: Run phpunit + if: matrix.php == '7.3' + run: ./vendor/bin/phpunit -c phpunit.xml.dist --coverage-clover build/clover.xml + + - name: Upload coverage results to Coveralls + if: matrix.php == '7.3' + env: + COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + wget https://github.com/php-coveralls/php-coveralls/releases/download/v2.4.3/php-coveralls.phar + chmod +x php-coveralls.phar + php php-coveralls.phar --coverage_clover=build/clover.xml --json_path=build/coveralls-upload.json -vvv + + samples: + name: Check samples + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: ['7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: gd, xml, zip + coverage: xdebug - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: 8.1 - extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: xdebug + - uses: actions/checkout@v2 - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" + - name: Composer Install + run: composer install --ansi --prefer-dist --no-interaction --no-progress - - name: Cache composer dependencies - uses: actions/cache@v3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Run phpunit - run: ./vendor/bin/phpunit -c phpunit.xml.dist --coverage-clover build/clover.xml - - - name: Upload coverage results to Coveralls - env: - COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - wget https://github.com/php-coveralls/php-coveralls/releases/download/v2.4.3/php-coveralls.phar - chmod +x php-coveralls.phar - php php-coveralls.phar --coverage_clover=build/clover.xml --json_path=build/coveralls-upload.json -vvv + - name: Generate samples files + run: composer run samples diff --git a/.gitignore b/.gitignore index 3695438057..0b9d0608d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +/composer.lock + + .DS_Store ._* .Spotlight-V100 diff --git a/composer.json b/composer.json index 9633fe01da..eb4c83f1a3 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ ], "homepage": "https://phpoffice.github.io/PHPWord/", "type": "library", - "license": "LGPL-3.0", + "license": "LGPL-3.0-only", "authors": [ { "name": "Mark Baker" @@ -49,6 +49,53 @@ ], "fix": [ "@php vendor/bin/php-cs-fixer fix --ansi" + ], + "samples": [ + "php samples/Sample_01_SimpleText.php", + "php samples/Sample_02_TabStops.php", + "php samples/Sample_03_Sections.php", + "php samples/Sample_04_Textrun.php", + "php samples/Sample_05_Multicolumn.php", + "php samples/Sample_06_Footnote.php", + "php samples/Sample_07_TemplateCloneRow.php", + "php samples/Sample_08_ParagraphPagination.php", + "php samples/Sample_09_Tables.php", + "php samples/Sample_10_EastAsianFontStyle.php", + "php samples/Sample_11_ReadWord97.php", + "php samples/Sample_11_ReadWord2007.php", + "php samples/Sample_12_HeaderFooter.php", + "php samples/Sample_13_Images.php", + "php samples/Sample_14_ListItem.php", + "php samples/Sample_15_Link.php", + "php samples/Sample_16_Object.php", + "php samples/Sample_17_TitleTOC.php", + "php samples/Sample_18_Watermark.php", + "php samples/Sample_19_TextBreak.php", + "php samples/Sample_20_BGColor.php", + "php samples/Sample_21_TableRowRules.php", + "php samples/Sample_22_CheckBox.php", + "php samples/Sample_23_TemplateBlock.php", + "php samples/Sample_24_ReadODText.php", + "php samples/Sample_25_TextBox.php", + "php samples/Sample_26_Html.php", + "php samples/Sample_27_Field.php", + "php samples/Sample_28_ReadRTF.php", + "php samples/Sample_29_Line.php", + "php samples/Sample_30_ReadHTML.php", + "php samples/Sample_31_Shape.php", + "php samples/Sample_32_Chart.php", + "php samples/Sample_33_FormField.php", + "php samples/Sample_34_SDT.php", + "php samples/Sample_35_InternalLink.php", + "php samples/Sample_36_RTL.php", + "php samples/Sample_37_Comments.php", + "php samples/Sample_38_Protection.php", + "php samples/Sample_39_TrackChanges.php", + "php samples/Sample_40_TemplateSetComplexValue.php", + "php samples/Sample_41_TemplateSetChart.php", + "php samples/Sample_42_TemplateSetCheckbox.php", + "php samples/Sample_43_RTLDefault.php", + "php samples/Sample_44_ExtractVariablesFromReaderWord2007.php" ] }, "scripts-descriptions": { @@ -57,34 +104,28 @@ "check": "Runs PHP CheckStyle and PHP Mess detector", "fix": "Fixes issues found by PHP-CS" }, - "config": { - "platform": { - "php": "8.0" - } - }, "require": { "php": "^7.1|^8.0", "ext-dom": "*", + "ext-gd": "*", "ext-json": "*", "ext-xml": "*", + "ext-zip": "*", "phpoffice/math": "^0.2" }, "require-dev": { - "ext-zip": "*", - "ext-gd": "*", "ext-libxml": "*", "dompdf/dompdf": "^2.0 || ^3.0", - "mpdf/mpdf": "^8.1", + "friendsofphp/php-cs-fixer": "^3.3", + "mpdf/mpdf": "^7.0 || ^8.0", "phpmd/phpmd": "^2.13", + "phpstan/phpstan": "^0.12.88 || ^1.0.0", + "phpstan/phpstan-phpunit": "^1.0 || ^2.0", "phpunit/phpunit": ">=7.0", - "tecnickcom/tcpdf": "^6.5", "symfony/process": "^4.4 || ^5.0", - "friendsofphp/php-cs-fixer": "^3.3", - "phpstan/phpstan-phpunit": "@stable" + "tecnickcom/tcpdf": "^6.5" }, "suggest": { - "ext-zip": "Allows writing OOXML and ODF", - "ext-gd2": "Allows adding images", "ext-xmlwriter": "Allows writing OOXML and ODF", "ext-xsl": "Allows applying XSL style sheet to headers, to main document part, and to footers of an OOXML template", "dompdf/dompdf": "Allows writing PDF" diff --git a/composer.lock b/composer.lock deleted file mode 100644 index 4b3473cf0c..0000000000 --- a/composer.lock +++ /dev/null @@ -1,5093 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "d9579858cde1a3c80e4da1ced85b72fd", - "packages": [ - { - "name": "phpoffice/math", - "version": "0.2.0", - "source": { - "type": "git", - "url": "https://github.com/PHPOffice/Math.git", - "reference": "fc2eb6d1a61b058d5dac77197059db30ee3c8329" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/Math/zipball/fc2eb6d1a61b058d5dac77197059db30ee3c8329", - "reference": "fc2eb6d1a61b058d5dac77197059db30ee3c8329", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-xml": "*", - "php": "^7.1|^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^0.12.88 || ^1.0.0", - "phpunit/phpunit": "^7.0 || ^9.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "PhpOffice\\Math\\": "src/Math/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Progi1984", - "homepage": "https://lefevre.dev/" - } - ], - "description": "Math - Manipulate Math Formula", - "homepage": "https://phpoffice.github.io/Math/", - "keywords": [ - "MathML", - "officemathml", - "php" - ], - "support": { - "issues": "https://github.com/PHPOffice/Math/issues", - "source": "https://github.com/PHPOffice/Math/tree/0.2.0" - }, - "time": "2024-08-12T07:30:45+00:00" - } - ], - "packages-dev": [ - { - "name": "composer/pcre", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560", - "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.3", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be/" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/1.0.1" - }, - "funding": [ - { - "url": "https://packagist.com/", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-01-21T20:24:37+00:00" - }, - { - "name": "composer/semver", - "version": "3.3.2", - "source": { - "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de/" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be/" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl/" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.3.2" - }, - "funding": [ - { - "url": "https://packagist.com/", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-04-01T19:23:25+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "2.0.5", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/9e36aeed4616366d2b690bdce11f71e9178c579a", - "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a", - "shasum": "" - }, - "require": { - "composer/pcre": "^1", - "php": "^5.3.2 || ^7.0 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/2.0.5" - }, - "funding": [ - { - "url": "https://packagist.com/", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-02-24T20:20:32+00:00" - }, - { - "name": "doctrine/annotations", - "version": "1.14.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", - "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", - "shasum": "" - }, - "require": { - "doctrine/lexer": "^1 || ^2", - "ext-tokenizer": "*", - "php": "^7.1 || ^8.0", - "psr/cache": "^1 || ^2 || ^3" - }, - "require-dev": { - "doctrine/cache": "^1.11 || ^2.0", - "doctrine/coding-standard": "^9 || ^10", - "phpstan/phpstan": "~1.4.10 || ^1.8.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "symfony/cache": "^4.4 || ^5.4 || ^6", - "vimeo/psalm": "^4.10" - }, - "suggest": { - "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "https://www.doctrine-project.org/projects/annotations.html", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "support": { - "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/1.14.3" - }, - "time": "2023-02-01T09:20:38+00:00" - }, - { - "name": "doctrine/deprecations", - "version": "v1.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/deprecations.git", - "reference": "8cffffb2218e01f3b370bf763e00e81697725259" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/8cffffb2218e01f3b370bf763e00e81697725259", - "reference": "8cffffb2218e01f3b370bf763e00e81697725259", - "shasum": "" - }, - "require": { - "php": "^7.1|^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9", - "phpunit/phpunit": "^7.5|^8.5|^9.5", - "psr/log": "^1|^2|^3" - }, - "suggest": { - "psr/log": "Allows logging deprecations via PSR-3 logger implementation" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "homepage": "https://www.doctrine-project.org/", - "support": { - "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/v1.1.0" - }, - "time": "2023-05-29T18:55:17+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "1.5.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^11", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-12-30T00:15:36+00:00" - }, - { - "name": "doctrine/lexer", - "version": "2.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", - "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^10", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^4.11 || ^5.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/2.1.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", - "type": "tidelift" - } - ], - "time": "2022-12-14T08:49:07+00:00" - }, - { - "name": "dompdf/dompdf", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/dompdf/dompdf.git", - "reference": "fbc7c5ee5d94f7a910b78b43feb7931b7f971b59" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/fbc7c5ee5d94f7a910b78b43feb7931b7f971b59", - "reference": "fbc7c5ee5d94f7a910b78b43feb7931b7f971b59", - "shasum": "" - }, - "require": { - "dompdf/php-font-lib": "^1.0.0", - "dompdf/php-svg-lib": "^1.0.0", - "ext-dom": "*", - "ext-mbstring": "*", - "masterminds/html5": "^2.0", - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "ext-gd": "*", - "ext-json": "*", - "ext-zip": "*", - "mockery/mockery": "^1.3", - "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10", - "squizlabs/php_codesniffer": "^3.5", - "symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0" - }, - "suggest": { - "ext-gd": "Needed to process images", - "ext-gmagick": "Improves image processing performance", - "ext-imagick": "Improves image processing performance", - "ext-zlib": "Needed for pdf stream compression" - }, - "type": "library", - "autoload": { - "psr-4": { - "Dompdf\\": "src/" - }, - "classmap": [ - "lib/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-2.1" - ], - "authors": [ - { - "name": "The Dompdf Community", - "homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md" - } - ], - "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", - "homepage": "https://github.com/dompdf/dompdf", - "support": { - "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v3.0.0" - }, - "time": "2024-04-29T14:01:28+00:00" - }, - { - "name": "dompdf/php-font-lib", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/dompdf/php-font-lib.git", - "reference": "991d6a954f6bbd7e41022198f00586b230731441" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/991d6a954f6bbd7e41022198f00586b230731441", - "reference": "991d6a954f6bbd7e41022198f00586b230731441", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6" - }, - "type": "library", - "autoload": { - "psr-4": { - "FontLib\\": "src/FontLib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-2.1-or-later" - ], - "authors": [ - { - "name": "The FontLib Community", - "homepage": "https://github.com/dompdf/php-font-lib/blob/master/AUTHORS.md" - } - ], - "description": "A library to read, parse, export and make subsets of different types of font files.", - "homepage": "https://github.com/dompdf/php-font-lib", - "support": { - "issues": "https://github.com/dompdf/php-font-lib/issues", - "source": "https://github.com/dompdf/php-font-lib/tree/1.0.0" - }, - "time": "2024-04-29T13:40:38+00:00" - }, - { - "name": "dompdf/php-svg-lib", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/dompdf/php-svg-lib.git", - "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/eb045e518185298eb6ff8d80d0d0c6b17aecd9af", - "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": "^7.1 || ^8.0", - "sabberworm/php-css-parser": "^8.4" - }, - "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Svg\\": "src/Svg" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-or-later" - ], - "authors": [ - { - "name": "The SvgLib Community", - "homepage": "https://github.com/dompdf/php-svg-lib/blob/master/AUTHORS.md" - } - ], - "description": "A library to read, parse and export to PDF SVG files.", - "homepage": "https://github.com/dompdf/php-svg-lib", - "support": { - "issues": "https://github.com/dompdf/php-svg-lib/issues", - "source": "https://github.com/dompdf/php-svg-lib/tree/1.0.0" - }, - "time": "2024-04-29T13:26:35+00:00" - }, - { - "name": "friendsofphp/php-cs-fixer", - "version": "v3.4.0", - "source": { - "type": "git", - "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "47177af1cfb9dab5d1cc4daf91b7179c2efe7fad" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/47177af1cfb9dab5d1cc4daf91b7179c2efe7fad", - "reference": "47177af1cfb9dab5d1cc4daf91b7179c2efe7fad", - "shasum": "" - }, - "require": { - "composer/semver": "^3.2", - "composer/xdebug-handler": "^2.0", - "doctrine/annotations": "^1.12", - "ext-json": "*", - "ext-tokenizer": "*", - "php": "^7.2.5 || ^8.0", - "php-cs-fixer/diff": "^2.0", - "symfony/console": "^4.4.20 || ^5.1.3 || ^6.0", - "symfony/event-dispatcher": "^4.4.20 || ^5.0 || ^6.0", - "symfony/filesystem": "^4.4.20 || ^5.0 || ^6.0", - "symfony/finder": "^4.4.20 || ^5.0 || ^6.0", - "symfony/options-resolver": "^4.4.20 || ^5.0 || ^6.0", - "symfony/polyfill-mbstring": "^1.23", - "symfony/polyfill-php80": "^1.23", - "symfony/polyfill-php81": "^1.23", - "symfony/process": "^4.4.20 || ^5.0 || ^6.0", - "symfony/stopwatch": "^4.4.20 || ^5.0 || ^6.0" - }, - "require-dev": { - "justinrainbow/json-schema": "^5.2", - "keradus/cli-executor": "^1.5", - "mikey179/vfsstream": "^1.6.8", - "php-coveralls/php-coveralls": "^2.5.2", - "php-cs-fixer/accessible-object": "^1.1", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", - "phpspec/prophecy": "^1.15", - "phpspec/prophecy-phpunit": "^1.1 || ^2.0", - "phpunit/phpunit": "^8.5.21 || ^9.5", - "phpunitgoodpractices/polyfill": "^1.5", - "phpunitgoodpractices/traits": "^1.9.1", - "symfony/phpunit-bridge": "^5.2.4 || ^6.0", - "symfony/yaml": "^4.4.20 || ^5.0 || ^6.0" - }, - "suggest": { - "ext-dom": "For handling output formats in XML", - "ext-mbstring": "For handling non-UTF8 characters." - }, - "bin": [ - "php-cs-fixer" - ], - "type": "application", - "autoload": { - "psr-4": { - "PhpCsFixer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" - } - ], - "description": "A tool to automatically fix PHP code style", - "support": { - "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", - "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.4.0" - }, - "funding": [ - { - "url": "https://github.com/keradus", - "type": "github" - } - ], - "time": "2021-12-11T16:25:08+00:00" - }, - { - "name": "masterminds/html5", - "version": "2.9.0", - "source": { - "type": "git", - "url": "https://github.com/Masterminds/html5-php.git", - "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", - "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7-dev" - } - }, - "autoload": { - "psr-4": { - "Masterminds\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matt Butcher", - "email": "technosophos@gmail.com" - }, - { - "name": "Matt Farina", - "email": "matt@mattfarina.com" - }, - { - "name": "Asmir Mustafic", - "email": "goetas@gmail.com" - } - ], - "description": "An HTML5 parser and serializer.", - "homepage": "http://masterminds.github.io/html5-php", - "keywords": [ - "HTML5", - "dom", - "html", - "parser", - "querypath", - "serializer", - "xml" - ], - "support": { - "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.9.0" - }, - "time": "2024-03-31T07:05:07+00:00" - }, - { - "name": "mpdf/mpdf", - "version": "v8.2.4", - "source": { - "type": "git", - "url": "https://github.com/mpdf/mpdf.git", - "reference": "9e3ff91606fed11cd58a130eabaaf60e56fdda88" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mpdf/mpdf/zipball/9e3ff91606fed11cd58a130eabaaf60e56fdda88", - "reference": "9e3ff91606fed11cd58a130eabaaf60e56fdda88", - "shasum": "" - }, - "require": { - "ext-gd": "*", - "ext-mbstring": "*", - "mpdf/psr-http-message-shim": "^1.0 || ^2.0", - "mpdf/psr-log-aware-trait": "^2.0 || ^3.0", - "myclabs/deep-copy": "^1.7", - "paragonie/random_compat": "^1.4|^2.0|^9.99.99", - "php": "^5.6 || ^7.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", - "psr/http-message": "^1.0 || ^2.0", - "psr/log": "^1.0 || ^2.0 || ^3.0", - "setasign/fpdi": "^2.1" - }, - "require-dev": { - "mockery/mockery": "^1.3.0", - "mpdf/qrcode": "^1.1.0", - "squizlabs/php_codesniffer": "^3.5.0", - "tracy/tracy": "~2.5", - "yoast/phpunit-polyfills": "^1.0" - }, - "suggest": { - "ext-bcmath": "Needed for generation of some types of barcodes", - "ext-xml": "Needed mainly for SVG manipulation", - "ext-zlib": "Needed for compression of embedded resources, such as fonts" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Mpdf\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-2.0-only" - ], - "authors": [ - { - "name": "Matěj Humpál", - "role": "Developer, maintainer" - }, - { - "name": "Ian Back", - "role": "Developer (retired)" - } - ], - "description": "PHP library generating PDF files from UTF-8 encoded HTML", - "homepage": "https://mpdf.github.io/", - "keywords": [ - "pdf", - "php", - "utf-8" - ], - "support": { - "docs": "http://mpdf.github.io/", - "issues": "https://github.com/mpdf/mpdf/issues", - "source": "https://github.com/mpdf/mpdf" - }, - "funding": [ - { - "url": "https://www.paypal.me/mpdf", - "type": "custom" - } - ], - "time": "2024-06-14T16:06:41+00:00" - }, - { - "name": "mpdf/psr-http-message-shim", - "version": "v2.0.1", - "source": { - "type": "git", - "url": "https://github.com/mpdf/psr-http-message-shim.git", - "reference": "f25a0153d645e234f9db42e5433b16d9b113920f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mpdf/psr-http-message-shim/zipball/f25a0153d645e234f9db42e5433b16d9b113920f", - "reference": "f25a0153d645e234f9db42e5433b16d9b113920f", - "shasum": "" - }, - "require": { - "psr/http-message": "^2.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Mpdf\\PsrHttpMessageShim\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mark Dorison", - "email": "mark@chromatichq.com" - }, - { - "name": "Kristofer Widholm", - "email": "kristofer@chromatichq.com" - }, - { - "name": "Nigel Cunningham", - "email": "nigel.cunningham@technocrat.com.au" - } - ], - "description": "Shim to allow support of different psr/message versions.", - "support": { - "issues": "https://github.com/mpdf/psr-http-message-shim/issues", - "source": "https://github.com/mpdf/psr-http-message-shim/tree/v2.0.1" - }, - "time": "2023-10-02T14:34:03+00:00" - }, - { - "name": "mpdf/psr-log-aware-trait", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/mpdf/psr-log-aware-trait.git", - "reference": "a633da6065e946cc491e1c962850344bb0bf3e78" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mpdf/psr-log-aware-trait/zipball/a633da6065e946cc491e1c962850344bb0bf3e78", - "reference": "a633da6065e946cc491e1c962850344bb0bf3e78", - "shasum": "" - }, - "require": { - "psr/log": "^3.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Mpdf\\PsrLogAwareTrait\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mark Dorison", - "email": "mark@chromatichq.com" - }, - { - "name": "Kristofer Widholm", - "email": "kristofer@chromatichq.com" - } - ], - "description": "Trait to allow support of different psr/log versions.", - "support": { - "issues": "https://github.com/mpdf/psr-log-aware-trait/issues", - "source": "https://github.com/mpdf/psr-log-aware-trait/tree/v3.0.0" - }, - "time": "2023-05-03T06:19:36+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.12.0", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3 <3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpspec/prophecy": "^1.10", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2024-06-12T14:39:25+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.18.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", - "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" - }, - "time": "2023-12-10T21:03:43+00:00" - }, - { - "name": "paragonie/random_compat", - "version": "v9.99.100", - "source": { - "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", - "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", - "shasum": "" - }, - "require": { - "php": ">= 7" - }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*", - "vimeo/psalm": "^1" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." - }, - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com/" - } - ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "polyfill", - "pseudorandom", - "random" - ], - "support": { - "email": "info@paragonie.com", - "issues": "https://github.com/paragonie/random_compat/issues", - "source": "https://github.com/paragonie/random_compat" - }, - "time": "2020-10-15T08:29:30+00:00" - }, - { - "name": "pdepend/pdepend", - "version": "2.16.2", - "source": { - "type": "git", - "url": "https://github.com/pdepend/pdepend.git", - "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pdepend/pdepend/zipball/f942b208dc2a0868454d01b29f0c75bbcfc6ed58", - "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58", - "shasum": "" - }, - "require": { - "php": ">=5.3.7", - "symfony/config": "^2.3.0|^3|^4|^5|^6.0|^7.0", - "symfony/dependency-injection": "^2.3.0|^3|^4|^5|^6.0|^7.0", - "symfony/filesystem": "^2.3.0|^3|^4|^5|^6.0|^7.0", - "symfony/polyfill-mbstring": "^1.19" - }, - "require-dev": { - "easy-doc/easy-doc": "0.0.0|^1.2.3", - "gregwar/rst": "^1.0", - "squizlabs/php_codesniffer": "^2.0.0" - }, - "bin": [ - "src/bin/pdepend" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "PDepend\\": "src/main/php/PDepend" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Official version of pdepend to be handled with Composer", - "keywords": [ - "PHP Depend", - "PHP_Depend", - "dev", - "pdepend" - ], - "support": { - "issues": "https://github.com/pdepend/pdepend/issues", - "source": "https://github.com/pdepend/pdepend/tree/2.16.2" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/pdepend/pdepend", - "type": "tidelift" - } - ], - "time": "2023-12-17T18:09:59+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" - }, - "time": "2021-07-20T11:28:43+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "php-cs-fixer/diff", - "version": "v2.0.2", - "source": { - "type": "git", - "url": "https://github.com/PHP-CS-Fixer/diff.git", - "reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/29dc0d507e838c4580d018bd8b5cb412474f7ec3", - "reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0", - "symfony/process": "^3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "sebastian/diff v3 backport support for PHP 5.6+", - "homepage": "https://github.com/PHP-CS-Fixer", - "keywords": [ - "diff" - ], - "support": { - "issues": "https://github.com/PHP-CS-Fixer/diff/issues", - "source": "https://github.com/PHP-CS-Fixer/diff/tree/v2.0.2" - }, - "abandoned": true, - "time": "2020-10-14T08:32:19+00:00" - }, - { - "name": "phpmd/phpmd", - "version": "2.15.0", - "source": { - "type": "git", - "url": "https://github.com/phpmd/phpmd.git", - "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpmd/phpmd/zipball/74a1f56e33afad4128b886e334093e98e1b5e7c0", - "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0", - "shasum": "" - }, - "require": { - "composer/xdebug-handler": "^1.0 || ^2.0 || ^3.0", - "ext-xml": "*", - "pdepend/pdepend": "^2.16.1", - "php": ">=5.3.9" - }, - "require-dev": { - "easy-doc/easy-doc": "0.0.0 || ^1.3.2", - "ext-json": "*", - "ext-simplexml": "*", - "gregwar/rst": "^1.0", - "mikey179/vfsstream": "^1.6.8", - "squizlabs/php_codesniffer": "^2.9.2 || ^3.7.2" - }, - "bin": [ - "src/bin/phpmd" - ], - "type": "library", - "autoload": { - "psr-0": { - "PHPMD\\": "src/main/php" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Manuel Pichler", - "email": "github@manuel-pichler.de", - "homepage": "https://github.com/manuelpichler", - "role": "Project Founder" - }, - { - "name": "Marc Würth", - "email": "ravage@bluewin.ch", - "homepage": "https://github.com/ravage84", - "role": "Project Maintainer" - }, - { - "name": "Other contributors", - "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", - "role": "Contributors" - } - ], - "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", - "homepage": "https://phpmd.org/", - "keywords": [ - "dev", - "mess detection", - "mess detector", - "pdepend", - "phpmd", - "pmd" - ], - "support": { - "irc": "irc://irc.freenode.org/phpmd", - "issues": "https://github.com/phpmd/phpmd/issues", - "source": "https://github.com/phpmd/phpmd/tree/2.15.0" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/phpmd/phpmd", - "type": "tidelift" - } - ], - "time": "2023-12-11T08:22:20+00:00" - }, - { - "name": "phpstan/phpstan", - "version": "1.11.10", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "640410b32995914bde3eed26fa89552f9c2c082f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/640410b32995914bde3eed26fa89552f9c2c082f", - "reference": "640410b32995914bde3eed26fa89552f9c2c082f", - "shasum": "" - }, - "require": { - "php": "^7.2|^8.0" - }, - "conflict": { - "phpstan/phpstan-shim": "*" - }, - "bin": [ - "phpstan", - "phpstan.phar" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan - PHP Static Analysis Tool", - "keywords": [ - "dev", - "static analysis" - ], - "support": { - "docs": "https://phpstan.org/user-guide/getting-started", - "forum": "https://github.com/phpstan/phpstan/discussions", - "issues": "https://github.com/phpstan/phpstan/issues", - "security": "https://github.com/phpstan/phpstan/security/policy", - "source": "https://github.com/phpstan/phpstan-src" - }, - "funding": [ - { - "url": "https://github.com/ondrejmirtes", - "type": "github" - }, - { - "url": "https://github.com/phpstan", - "type": "github" - } - ], - "time": "2024-08-08T09:02:50+00:00" - }, - { - "name": "phpstan/phpstan-phpunit", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "f3ea021866f4263f07ca3636bf22c64be9610c11" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/f3ea021866f4263f07ca3636bf22c64be9610c11", - "reference": "f3ea021866f4263f07ca3636bf22c64be9610c11", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.11" - }, - "conflict": { - "phpunit/phpunit": "<7.0" - }, - "require-dev": { - "nikic/php-parser": "^4.13.0", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-strict-rules": "^1.5.1", - "phpunit/phpunit": "^9.5" - }, - "type": "phpstan-extension", - "extra": { - "phpstan": { - "includes": [ - "extension.neon", - "rules.neon" - ] - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPUnit extensions and rules for PHPStan", - "support": { - "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.4.0" - }, - "time": "2024-04-20T06:39:00+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "9.2.30", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-22T06:47:57+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "3.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-12-02T12:48:52+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:58:55+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T05:33:50+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "9.6.15", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/05017b80304e0eb3f31d90194a563fd53a6021f1", - "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.3.1 || ^2", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.28", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.5", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.2", - "sebastian/version": "^3.0.2" - }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.6-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.15" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" - } - ], - "time": "2023-12-01T16:55:19+00:00" - }, - { - "name": "psr/cache", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "support": { - "source": "https://github.com/php-fig/cache/tree/3.0.0" - }, - "time": "2021-02-03T23:26:27+00:00" - }, - { - "name": "psr/container", - "version": "1.1.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" - }, - "time": "2021-11-05T16:50:12+00:00" - }, - { - "name": "psr/event-dispatcher", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", - "shasum": "" - }, - "require": { - "php": ">=7.2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], - "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" - }, - "time": "2019-01-08T18:20:26+00:00" - }, - { - "name": "psr/http-message", - "version": "2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-message/tree/2.0" - }, - "time": "2023-04-04T09:54:51+00:00" - }, - { - "name": "psr/log", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" - }, - "time": "2021-07-14T16:46:02+00:00" - }, - { - "name": "sabberworm/php-css-parser", - "version": "v8.6.0", - "source": { - "type": "git", - "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", - "reference": "d2fb94a9641be84d79c7548c6d39bbebba6e9a70" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/d2fb94a9641be84d79c7548c6d39bbebba6e9a70", - "reference": "d2fb94a9641be84d79c7548c6d39bbebba6e9a70", - "shasum": "" - }, - "require": { - "ext-iconv": "*", - "php": ">=5.6.20" - }, - "require-dev": { - "phpunit/phpunit": "^5.7.27" - }, - "suggest": { - "ext-mbstring": "for parsing UTF-8 CSS" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "9.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Sabberworm\\CSS\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Raphael Schweikert" - }, - { - "name": "Oliver Klee", - "email": "github@oliverklee.de" - }, - { - "name": "Jake Hotson", - "email": "jake.github@qzdesign.co.uk" - } - ], - "description": "Parser for CSS Files written in PHP", - "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser", - "keywords": [ - "css", - "parser", - "stylesheet" - ], - "support": { - "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", - "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.6.0" - }, - "time": "2024-07-01T07:33:21+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:08:49+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:08:54+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:30:19+00:00" - }, - { - "name": "sebastian/comparator", - "version": "4.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-09-14T12:41:17+00:00" - }, - { - "name": "sebastian/complexity", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-22T06:19:30+00:00" - }, - { - "name": "sebastian/diff", - "version": "4.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-05-07T05:35:17+00:00" - }, - { - "name": "sebastian/environment", - "version": "5.1.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:03:51+00:00" - }, - { - "name": "sebastian/exporter", - "version": "4.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-09-14T06:03:37+00:00" - }, - { - "name": "sebastian/global-state", - "version": "5.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bde739e7565280bda77be70044ac1047bc007e34" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", - "reference": "bde739e7565280bda77be70044ac1047bc007e34", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-02T09:26:13+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "1.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-22T06:20:34+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:12:34+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:14:26+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "4.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:07:39+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:45:17+00:00" - }, - { - "name": "sebastian/type", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:13:03+00:00" - }, - { - "name": "sebastian/version", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:39:44+00:00" - }, - { - "name": "setasign/fpdi", - "version": "v2.6.0", - "source": { - "type": "git", - "url": "https://github.com/Setasign/FPDI.git", - "reference": "a6db878129ec6c7e141316ee71872923e7f1b7ad" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Setasign/FPDI/zipball/a6db878129ec6c7e141316ee71872923e7f1b7ad", - "reference": "a6db878129ec6c7e141316ee71872923e7f1b7ad", - "shasum": "" - }, - "require": { - "ext-zlib": "*", - "php": "^5.6 || ^7.0 || ^8.0" - }, - "conflict": { - "setasign/tfpdf": "<1.31" - }, - "require-dev": { - "phpunit/phpunit": "~5.7", - "setasign/fpdf": "~1.8.6", - "setasign/tfpdf": "~1.33", - "squizlabs/php_codesniffer": "^3.5", - "tecnickcom/tcpdf": "~6.2" - }, - "suggest": { - "setasign/fpdf": "FPDI will extend this class but as it is also possible to use TCPDF or tFPDF as an alternative. There's no fixed dependency configured." - }, - "type": "library", - "autoload": { - "psr-4": { - "setasign\\Fpdi\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jan Slabon", - "email": "jan.slabon@setasign.com", - "homepage": "https://www.setasign.com/" - }, - { - "name": "Maximilian Kresse", - "email": "maximilian.kresse@setasign.com", - "homepage": "https://www.setasign.com/" - } - ], - "description": "FPDI is a collection of PHP classes facilitating developers to read pages from existing PDF documents and use them as templates in FPDF. Because it is also possible to use FPDI with TCPDF, there are no fixed dependencies defined. Please see suggestions for packages which evaluates the dependencies automatically.", - "homepage": "https://www.setasign.com/fpdi", - "keywords": [ - "fpdf", - "fpdi", - "pdf" - ], - "support": { - "issues": "https://github.com/Setasign/FPDI/issues", - "source": "https://github.com/Setasign/FPDI/tree/v2.6.0" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/setasign/fpdi", - "type": "tidelift" - } - ], - "time": "2023-12-11T16:03:32+00:00" - }, - { - "name": "symfony/config", - "version": "v5.4.31", - "source": { - "type": "git", - "url": "https://github.com/symfony/config.git", - "reference": "dd5ea39de228813aba0c23c3a4153da2a4cf3cd9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/dd5ea39de228813aba0c23c3a4153da2a4cf3cd9", - "reference": "dd5ea39de228813aba0c23c3a4153da2a4cf3cd9", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/filesystem": "^4.4|^5.0|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22" - }, - "conflict": { - "symfony/finder": "<4.4" - }, - "require-dev": { - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/messenger": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/yaml": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Config\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", - "homepage": "https://symfony.com/", - "support": { - "source": "https://github.com/symfony/config/tree/v5.4.31" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-09T08:22:43+00:00" - }, - { - "name": "symfony/console", - "version": "v5.3.16", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "2e322c76cdccb302af6b275ea2207169c8355328" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/2e322c76cdccb302af6b275ea2207169c8355328", - "reference": "2e322c76cdccb302af6b275ea2207169c8355328", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.8", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2", - "symfony/string": "^5.1" - }, - "conflict": { - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0" - }, - "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/event-dispatcher": "^4.4|^5.0", - "symfony/lock": "^4.4|^5.0", - "symfony/process": "^4.4|^5.0", - "symfony/var-dumper": "^4.4|^5.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com/", - "keywords": [ - "cli", - "command line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v5.3.16" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-03-01T08:24:05+00:00" - }, - { - "name": "symfony/dependency-injection", - "version": "v5.4.34", - "source": { - "type": "git", - "url": "https://github.com/symfony/dependency-injection.git", - "reference": "75d568165a65fa7d8124869ec7c3a90424352e6c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/75d568165a65fa7d8124869ec7c3a90424352e6c", - "reference": "75d568165a65fa7d8124869ec7c3a90424352e6c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1.1", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22", - "symfony/service-contracts": "^1.1.6|^2" - }, - "conflict": { - "ext-psr": "<1.1|>=2", - "symfony/config": "<5.3", - "symfony/finder": "<4.4", - "symfony/proxy-manager-bridge": "<4.4", - "symfony/yaml": "<4.4.26" - }, - "provide": { - "psr/container-implementation": "1.0", - "symfony/service-implementation": "1.0|2.0" - }, - "require-dev": { - "symfony/config": "^5.3|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/yaml": "^4.4.26|^5.0|^6.0" - }, - "suggest": { - "symfony/config": "", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\DependencyInjection\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Allows you to standardize and centralize the way objects are constructed in your application", - "homepage": "https://symfony.com/", - "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v5.4.34" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-12-28T09:31:38+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com/", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-02T09:53:40+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v5.4.22", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1df20e45d56da29a4b1d8259dd6e950acbf1b13f", - "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" - }, - "conflict": { - "symfony/dependency-injection": "<4.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", - "homepage": "https://symfony.com/", - "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.22" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-03-17T11:31:58+00:00" - }, - { - "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/event-dispatcher": "^1" - }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com/", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-02T09:53:40+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v5.4.25", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", - "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com/", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.25" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-05-31T13:04:02+00:00" - }, - { - "name": "symfony/finder", - "version": "v5.4.21", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "078e9a5e1871fcfe6a5ce421b539344c21afef19" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/078e9a5e1871fcfe6a5ce421b539344c21afef19", - "reference": "078e9a5e1871fcfe6a5ce421b539344c21afef19", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com/", - "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.21" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-02-16T09:33:00+00:00" - }, - { - "name": "symfony/options-resolver", - "version": "v5.4.21", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", - "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com/", - "keywords": [ - "config", - "configuration", - "options" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.21" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-02-14T08:03:56+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com/", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com/", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com/", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com/", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-28T09:04:16+00:00" - }, - { - "name": "symfony/polyfill-php73", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com/", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com/", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-php81", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", - "homepage": "https://symfony.com/", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/process", - "version": "v5.4.34", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "8fa22178dfc368911dbd513b431cd9b06f9afe7a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/8fa22178dfc368911dbd513b431cd9b06f9afe7a", - "reference": "8fa22178dfc368911dbd513b431cd9b06f9afe7a", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com/", - "support": { - "source": "https://github.com/symfony/process/tree/v5.4.34" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-12-02T08:41:43+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com/", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-30T19:17:29+00:00" - }, - { - "name": "symfony/stopwatch", - "version": "v5.4.21", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/f83692cd869a6f2391691d40a01e8acb89e76fee", - "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/service-contracts": "^1|^2|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a way to profile code", - "homepage": "https://symfony.com/", - "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.4.21" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-02-14T08:03:56+00:00" - }, - { - "name": "symfony/string", - "version": "v5.4.22", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", - "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" - }, - "conflict": { - "symfony/translation-contracts": ">=3.0" - }, - "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com/", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v5.4.22" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-03-14T06:11:53+00:00" - }, - { - "name": "tecnickcom/tcpdf", - "version": "6.7.5", - "source": { - "type": "git", - "url": "https://github.com/tecnickcom/TCPDF.git", - "reference": "951eabf0338ec2522bd0d5d9c79b08a3a3d36b36" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/951eabf0338ec2522bd0d5d9c79b08a3a3d36b36", - "reference": "951eabf0338ec2522bd0d5d9c79b08a3a3d36b36", - "shasum": "" - }, - "require": { - "php": ">=5.5.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "config", - "include", - "tcpdf.php", - "tcpdf_parser.php", - "tcpdf_import.php", - "tcpdf_barcodes_1d.php", - "tcpdf_barcodes_2d.php", - "include/tcpdf_colors.php", - "include/tcpdf_filters.php", - "include/tcpdf_font_data.php", - "include/tcpdf_fonts.php", - "include/tcpdf_images.php", - "include/tcpdf_static.php", - "include/barcodes/datamatrix.php", - "include/barcodes/pdf417.php", - "include/barcodes/qrcode.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Nicola Asuni", - "email": "info@tecnick.com", - "role": "lead" - } - ], - "description": "TCPDF is a PHP class for generating PDF documents and barcodes.", - "homepage": "http://www.tcpdf.org/", - "keywords": [ - "PDFD32000-2008", - "TCPDF", - "barcodes", - "datamatrix", - "pdf", - "pdf417", - "qrcode" - ], - "support": { - "issues": "https://github.com/tecnickcom/TCPDF/issues", - "source": "https://github.com/tecnickcom/TCPDF/tree/6.7.5" - }, - "funding": [ - { - "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_donations¤cy_code=GBP&business=paypal@tecnick.com&item_name=donation%20for%20tcpdf%20project", - "type": "custom" - } - ], - "time": "2024-04-20T17:25:10+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.2", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.2" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2023-11-20T00:12:19+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": { - "phpstan/phpstan-phpunit": 0 - }, - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^7.1|^8.0", - "ext-dom": "*", - "ext-json": "*", - "ext-xml": "*" - }, - "platform-dev": { - "ext-zip": "*", - "ext-gd": "*", - "ext-libxml": "*" - }, - "platform-overrides": { - "php": "8.0" - }, - "plugin-api-version": "2.6.0" -} diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 8db845337d..a6461fba14 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -6,6 +6,7 @@ - Writer ODText: Support for ListItemRun by [@Progi1984](https://github.com/Progi1984) fixing [#2159](https://github.com/PHPOffice/PHPWord/issues/2159), [#2620](https://github.com/PHPOffice/PHPWord/issues/2620) in [#2669](https://github.com/PHPOffice/PHPWord/pull/2669) - Writer HTML: Support for vAlign in Tables by [@SpraxDev](https://github.com/SpraxDev) in [#2675](https://github.com/PHPOffice/PHPWord/pull/2675) +- Added support for PHP 8.4 by [@Progi1984](https://github.com/Progi1984) in [#2660](https://github.com/PHPOffice/PHPWord/pull/2660) ### Bug fixes diff --git a/docs/howto.md b/docs/howto.md index f53217f869..fd4c860682 100644 --- a/docs/howto.md +++ b/docs/howto.md @@ -15,7 +15,7 @@ $imageStyle = array( 'posHorizontalRel' => 'margin', 'posVerticalRel' => 'line', ); -$textrun->addImage('resources/_earth.jpg', $imageStyle); +$textrun->addImage(__DIR__ . '/resources/_earth.jpg', $imageStyle); ``` ## Download the produced file automatically diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 909718b83b..901888024d 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -375,11 +375,6 @@ parameters: count: 1 path: src/PhpWord/Shared/Drawing.php - - - message: "#^Binary operation \"\\*\" between string and 50 results in an error\\.$#" - count: 1 - path: src/PhpWord/Shared/Html.php - - message: "#^Call to an undefined method DOMNode\\:\\:getAttribute\\(\\)\\.$#" count: 1 @@ -685,11 +680,6 @@ parameters: count: 1 path: src/PhpWord/Style/Cell.php - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Cell\\:\\:\\$shading is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Cell.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Chart\\:\\:getMajorTickPosition\\(\\) has no return type specified\\.$#" count: 1 @@ -760,41 +750,6 @@ parameters: count: 1 path: src/PhpWord/Style/Font.php - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$allCaps is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Font.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$doubleStrikethrough is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Font.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$lang is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Font.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$paragraph is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Font.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$shading is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Font.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$smallCaps is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Font.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$strikethrough is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Font.php - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Line\\:\\:\\$weight \\(int\\) does not accept float\\|int\\|null\\.$#" count: 1 @@ -815,21 +770,6 @@ parameters: count: 1 path: src/PhpWord/Style/Paragraph.php - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\:\\:\\$indentation is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Paragraph.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\:\\:\\$shading is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Paragraph.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\:\\:\\$spacing is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Paragraph.php - - message: "#^Result of && is always false\\.$#" count: 1 @@ -840,36 +780,6 @@ parameters: count: 1 path: src/PhpWord/Style/Section.php - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Section\\:\\:\\$lineNumbering is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Section.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Shape\\:\\:\\$extrusion is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Shape.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Shape\\:\\:\\$fill is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Shape.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Shape\\:\\:\\$frame is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Shape.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Shape\\:\\:\\$outline is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Shape.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Shape\\:\\:\\$shadow is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Shape.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\TOC\\:\\:setTabLeader\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\TOC but returns PhpOffice\\\\PhpWord\\\\Style\\\\Tab\\.$#" count: 1 @@ -1120,11 +1030,6 @@ parameters: count: 1 path: src/PhpWord/Writer/AbstractWriter.php - - - message: "#^PHPDoc tag @param has invalid value \\(\\\\PhpOffice\\\\PhpWord\\\\PhpWord\\)\\: Unexpected token \"\\\\n \\*\", expected variable at offset 78$#" - count: 1 - path: src/PhpWord/Writer/AbstractWriter.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\HTML\\\\Element\\\\AbstractElement\\:\\:write\\(\\) has no return type specified\\.$#" count: 1 @@ -1315,11 +1220,6 @@ parameters: count: 1 path: src/PhpWord/Writer/RTF/Style/Border.php - - - message: "#^PHPDoc tag @param has invalid value \\(\\\\PhpOffice\\\\PhpWord\\\\PhpWord\\)\\: Unexpected token \"\\\\n \", expected variable at offset 86$#" - count: 1 - path: src/PhpWord/Writer/Word2007.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Element\\\\AbstractElement\\:\\:write\\(\\) has no return type specified\\.$#" count: 1 @@ -1426,29 +1326,29 @@ parameters: path: tests/PhpWordTests/AbstractTestReader.php - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbeddedTest\\:\\:getBaseUrl\\(\\) has no return type specified\\.$#" + message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbedded\\:\\:getBaseUrl\\(\\) has no return type specified\\.$#" count: 1 - path: tests/PhpWordTests/AbstractWebServerEmbeddedTest.php + path: tests/PhpWordTests/AbstractWebServerEmbedded.php - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbeddedTest\\:\\:getRemoteBmpImageUrl\\(\\) has no return type specified\\.$#" + message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbedded\\:\\:getRemoteBmpImageUrl\\(\\) has no return type specified\\.$#" count: 1 - path: tests/PhpWordTests/AbstractWebServerEmbeddedTest.php + path: tests/PhpWordTests/AbstractWebServerEmbedded.php - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbeddedTest\\:\\:getRemoteGifImageUrl\\(\\) has no return type specified\\.$#" + message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbedded\\:\\:getRemoteGifImageUrl\\(\\) has no return type specified\\.$#" count: 1 - path: tests/PhpWordTests/AbstractWebServerEmbeddedTest.php + path: tests/PhpWordTests/AbstractWebServerEmbedded.php - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbeddedTest\\:\\:getRemoteImageUrl\\(\\) has no return type specified\\.$#" + message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbedded\\:\\:getRemoteImageUrl\\(\\) has no return type specified\\.$#" count: 1 - path: tests/PhpWordTests/AbstractWebServerEmbeddedTest.php + path: tests/PhpWordTests/AbstractWebServerEmbedded.php - - message: "#^Property PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbeddedTest\\:\\:\\$httpServer has no type specified\\.$#" + message: "#^Property PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbedded\\:\\:\\$httpServer has no type specified\\.$#" count: 1 - path: tests/PhpWordTests/AbstractWebServerEmbeddedTest.php + path: tests/PhpWordTests/AbstractWebServerEmbedded.php - message: "#^Parameter \\#1 \\$width of class PhpOffice\\\\PhpWord\\\\Element\\\\Cell constructor expects int\\|null, string given\\.$#" diff --git a/phpstan.neon b/phpstan.neon deleted file mode 100644 index aac94077bd..0000000000 --- a/phpstan.neon +++ /dev/null @@ -1,19 +0,0 @@ -includes: - - phpstan-baseline.neon - - vendor/phpstan/phpstan-phpunit/extension.neon - - vendor/phpstan/phpstan-phpunit/rules.neon -parameters: - level: 7 - paths: - - src/ - - tests/ - excludePaths: - - */pclzip.lib.php - - src/PhpWord/Shared/OLERead.php - - src/PhpWord/Reader/MsDoc.php - - src/PhpWord/Writer/PDF/MPDF.php - bootstrapFiles: - - tests/bootstrap.php - ignoreErrors: - - - identifier: missingType.iterableValue diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000000..0cdf25ef21 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,44 @@ +includes: + - phpstan-baseline.neon + - vendor/phpstan/phpstan-phpunit/extension.neon + - vendor/phpstan/phpstan-phpunit/rules.neon +parameters: + level: 7 + paths: + - src/ + - tests/ + excludePaths: + - */pclzip.lib.php + - src/PhpWord/Shared/OLERead.php + - src/PhpWord/Reader/MsDoc.php + - src/PhpWord/Writer/PDF/MPDF.php + bootstrapFiles: + - tests/bootstrap.php + ## <=PHP7.4 + reportUnmatchedIgnoredErrors: false + ignoreErrors: + - + identifier: missingType.iterableValue + + ## <=PHP7.4 + - + message: '#Parameter \#1 \$argument of class ReflectionClass constructor expects class-string<T of object>\|T of object, string given.#' + path: src/PhpWord/Element/AbstractContainer.php + - + message: '#Parameter \#1 \$function of function call_user_func expects callable\(\): mixed, string given.#' + path: src/PhpWord/Element/Image.php + - + message: '#Parameter \#1 \$argument of class ReflectionClass constructor expects class-string<T of object>\|T of object, string given.#' + path: src/PhpWord/IOFactory.php + - + message: '#Parameter \#1 \$function of function forward_static_call_array expects callable\(\): mixed, array{.+, string} given.#' + path: src/PhpWord/PhpWord.php + - + message: '#Parameter \#1 \$function of function call_user_func_array expects callable\(\): mixed, array{\$this\(PhpOffice\\PhpWord\\Shared\\ZipArchive\)\|PclZip\|ZipArchive, mixed} given.#' + path: src/PhpWord/Shared/ZipArchive.php + - + message: '#Parameter \#1 \$function of function call_user_func_array expects callable\(\): mixed, array{PhpOffice\\PhpWord\\Writer\\PDF\\AbstractRenderer, string} given.#' + path: src/PhpWord/Writer/PDF.php + - + message: '#Parameter \#1 \$argument of class ReflectionClass constructor expects class-string<object>\|object, class-string\|false given.#' + path: tests/PhpWordTests/Style/AbstractStyleTest.php diff --git a/samples/Sample_01_SimpleText.php b/samples/Sample_01_SimpleText.php index e89f7323ba..07e0d05aa5 100644 --- a/samples/Sample_01_SimpleText.php +++ b/samples/Sample_01_SimpleText.php @@ -7,16 +7,16 @@ // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; -$languageEnGb = new \PhpOffice\PhpWord\Style\Language(\PhpOffice\PhpWord\Style\Language::EN_GB); +$languageEnGb = new PhpOffice\PhpWord\Style\Language(PhpOffice\PhpWord\Style\Language::EN_GB); -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $phpWord->getSettings()->setThemeFontLang($languageEnGb); $fontStyleName = 'rStyle'; $phpWord->addFontStyle($fontStyleName, ['bold' => true, 'italic' => true, 'size' => 16, 'allCaps' => true, 'doubleStrikethrough' => true]); $paragraphStyleName = 'pStyle'; -$phpWord->addParagraphStyle($paragraphStyleName, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER, 'spaceAfter' => 100]); +$phpWord->addParagraphStyle($paragraphStyleName, ['alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER, 'spaceAfter' => 100]); $phpWord->addTitleStyle(1, ['bold' => true], ['spaceAfter' => 240]); @@ -29,7 +29,7 @@ // $pStyle = new Font(); // $pStyle->setLang() -$section->addText('Ce texte-ci est en français.', ['lang' => \PhpOffice\PhpWord\Style\Language::FR_BE]); +$section->addText('Ce texte-ci est en français.', ['lang' => PhpOffice\PhpWord\Style\Language::FR_BE]); // Two text break $section->addTextBreak(2); @@ -82,7 +82,7 @@ $section->addTextBreak(); // Image -$section->addImage('resources/_earth.jpg', ['width' => 18, 'height' => 18]); +$section->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 18, 'height' => 18]); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_02_TabStops.php b/samples/Sample_02_TabStops.php index 74a0ed1fa3..ad99fe83f5 100644 --- a/samples/Sample_02_TabStops.php +++ b/samples/Sample_02_TabStops.php @@ -4,7 +4,7 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Define styles $multipleTabsStyleName = 'multipleTab'; @@ -12,18 +12,18 @@ $multipleTabsStyleName, [ 'tabs' => [ - new \PhpOffice\PhpWord\Style\Tab('left', 1550), - new \PhpOffice\PhpWord\Style\Tab('center', 3200), - new \PhpOffice\PhpWord\Style\Tab('right', 5300), + new PhpOffice\PhpWord\Style\Tab('left', 1550), + new PhpOffice\PhpWord\Style\Tab('center', 3200), + new PhpOffice\PhpWord\Style\Tab('right', 5300), ], ] ); $rightTabStyleName = 'rightTab'; -$phpWord->addParagraphStyle($rightTabStyleName, ['tabs' => [new \PhpOffice\PhpWord\Style\Tab('right', 9090)]]); +$phpWord->addParagraphStyle($rightTabStyleName, ['tabs' => [new PhpOffice\PhpWord\Style\Tab('right', 9090)]]); $leftTabStyleName = 'centerTab'; -$phpWord->addParagraphStyle($leftTabStyleName, ['tabs' => [new \PhpOffice\PhpWord\Style\Tab('center', 4680)]]); +$phpWord->addParagraphStyle($leftTabStyleName, ['tabs' => [new PhpOffice\PhpWord\Style\Tab('center', 4680)]]); // New portrait section $section = $phpWord->addSection(); diff --git a/samples/Sample_03_Sections.php b/samples/Sample_03_Sections.php index b02a277c43..b01726d81c 100644 --- a/samples/Sample_03_Sections.php +++ b/samples/Sample_03_Sections.php @@ -6,7 +6,7 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New portrait section $section = $phpWord->addSection(['borderColor' => '00FF00', 'borderSize' => 12]); diff --git a/samples/Sample_04_Textrun.php b/samples/Sample_04_Textrun.php index 33af08a5b4..6d50e285ec 100644 --- a/samples/Sample_04_Textrun.php +++ b/samples/Sample_04_Textrun.php @@ -4,7 +4,7 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Define styles $paragraphStyleName = 'pStyle'; @@ -17,7 +17,7 @@ $phpWord->addFontStyle($coloredFontStyleName, ['color' => 'FF8080', 'bgColor' => 'FFFFCC']); $linkFontStyleName = 'NLink'; -$phpWord->addLinkStyle($linkFontStyleName, ['color' => '0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE]); +$phpWord->addLinkStyle($linkFontStyleName, ['color' => '0000FF', 'underline' => PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE]); // New portrait section $section = $phpWord->addSection(); @@ -35,9 +35,9 @@ $textrun->addText(' Sample Link: '); $textrun->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub', $linkFontStyleName); $textrun->addText(' Sample Image: '); -$textrun->addImage('resources/_earth.jpg', ['width' => 18, 'height' => 18]); +$textrun->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 18, 'height' => 18]); $textrun->addText(' Sample Object: '); -$textrun->addObject('resources/_sheet.xls'); +$textrun->addObject(__DIR__ . '/resources/_sheet.xls'); $textrun->addText(' Here is some more text. '); $textrun = $section->addTextRun(); diff --git a/samples/Sample_05_Multicolumn.php b/samples/Sample_05_Multicolumn.php index 093dd60424..c4d1dd7280 100644 --- a/samples/Sample_05_Multicolumn.php +++ b/samples/Sample_05_Multicolumn.php @@ -4,7 +4,7 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $filler = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. ' . 'Nulla fermentum, tortor id adipiscing adipiscing, tortor turpis commodo. ' . 'Donec vulputate iaculis metus, vel luctus dolor hendrerit ac. ' diff --git a/samples/Sample_06_Footnote.php b/samples/Sample_06_Footnote.php index f3c369b342..035916ee09 100644 --- a/samples/Sample_06_Footnote.php +++ b/samples/Sample_06_Footnote.php @@ -7,8 +7,8 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); -\PhpOffice\PhpWord\Settings::setCompatibility(false); +$phpWord = new PhpOffice\PhpWord\PhpWord(); +PhpOffice\PhpWord\Settings::setCompatibility(false); // Define styles $paragraphStyleName = 'pStyle'; @@ -21,7 +21,7 @@ $phpWord->addFontStyle($coloredFontStyleName, ['color' => 'FF8080', 'bgColor' => 'FFFFCC']); $linkFontStyleName = 'NLink'; -$phpWord->addLinkStyle($linkFontStyleName, ['color' => '0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE]); +$phpWord->addLinkStyle($linkFontStyleName, ['color' => '0000FF', 'underline' => PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE]); // New portrait section $section = $phpWord->addSection(); @@ -39,9 +39,9 @@ $footnote->addText('links like '); $footnote->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub', $linkFontStyleName); $footnote->addText(', image like '); -$footnote->addImage('resources/_earth.jpg', ['width' => 18, 'height' => 18]); +$footnote->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 18, 'height' => 18]); $footnote->addText(', or object like '); -$footnote->addObject('resources/_sheet.xls'); +$footnote->addObject(__DIR__ . '/resources/_sheet.xls'); $footnote->addText('But you can only put footnote in section, not in header or footer.'); $section->addText( diff --git a/samples/Sample_07_TemplateCloneRow.php b/samples/Sample_07_TemplateCloneRow.php index a921569f64..0f1d165f19 100644 --- a/samples/Sample_07_TemplateCloneRow.php +++ b/samples/Sample_07_TemplateCloneRow.php @@ -4,7 +4,7 @@ // Template processor instance creation echo date('H:i:s'), ' Creating new TemplateProcessor instance...', EOL; -$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('resources/Sample_07_TemplateCloneRow.docx'); +$templateProcessor = new PhpOffice\PhpWord\TemplateProcessor(__DIR__ . '/resources/Sample_07_TemplateCloneRow.docx'); // Variables on different parts of document $templateProcessor->setValue('weekday', date('l')); // On section/content @@ -79,9 +79,9 @@ // $templateProcessor->setValue('userPhone#3', '+1 428 889 775'); echo date('H:i:s'), ' Saving the result document...', EOL; -$templateProcessor->saveAs('results/Sample_07_TemplateCloneRow.docx'); +$templateProcessor->saveAs(__DIR__ . '/results/Sample_07_TemplateCloneRow.docx'); -echo getEndingNotes(['Word2007' => 'docx'], 'results/Sample_07_TemplateCloneRow.docx'); +echo getEndingNotes(['Word2007' => 'docx'], __DIR__ . '/results/Sample_07_TemplateCloneRow.docx'); if (!CLI) { include_once 'Sample_Footer.php'; } diff --git a/samples/Sample_08_ParagraphPagination.php b/samples/Sample_08_ParagraphPagination.php index f343366a84..cac52e3baf 100644 --- a/samples/Sample_08_ParagraphPagination.php +++ b/samples/Sample_08_ParagraphPagination.php @@ -4,11 +4,11 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $phpWord->setDefaultParagraphStyle( [ - 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::BOTH, - 'spaceAfter' => \PhpOffice\PhpWord\Shared\Converter::pointToTwip(12), + 'alignment' => PhpOffice\PhpWord\SimpleType\Jc::BOTH, + 'spaceAfter' => PhpOffice\PhpWord\Shared\Converter::pointToTwip(12), 'spacing' => 120, ] ); diff --git a/samples/Sample_09_Tables.php b/samples/Sample_09_Tables.php index 877072d898..3a887468b0 100644 --- a/samples/Sample_09_Tables.php +++ b/samples/Sample_09_Tables.php @@ -7,7 +7,7 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); $header = ['size' => 16, 'bold' => true]; @@ -31,10 +31,10 @@ $section->addText('Fancy table', $header); $fancyTableStyleName = 'Fancy Table'; -$fancyTableStyle = ['borderSize' => 6, 'borderColor' => '006699', 'cellMargin' => 80, 'alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER, 'cellSpacing' => 50]; +$fancyTableStyle = ['borderSize' => 6, 'borderColor' => '006699', 'cellMargin' => 80, 'alignment' => PhpOffice\PhpWord\SimpleType\JcTable::CENTER, 'cellSpacing' => 50]; $fancyTableFirstRowStyle = ['borderBottomSize' => 18, 'borderBottomColor' => '0000FF', 'bgColor' => '66BBFF']; $fancyTableCellStyle = ['valign' => 'center']; -$fancyTableCellBtlrStyle = ['valign' => 'center', 'textDirection' => \PhpOffice\PhpWord\Style\Cell::TEXT_DIR_BTLR]; +$fancyTableCellBtlrStyle = ['valign' => 'center', 'textDirection' => PhpOffice\PhpWord\Style\Cell::TEXT_DIR_BTLR]; $fancyTableFontStyle = ['bold' => true]; $phpWord->addTableStyle($fancyTableStyleName, $fancyTableStyle, $fancyTableFirstRowStyle); $table = $section->addTable($fancyTableStyleName); @@ -72,7 +72,7 @@ $cellRowSpan = ['vMerge' => 'restart', 'valign' => 'center', 'bgColor' => 'FFFF00']; $cellRowContinue = ['vMerge' => 'continue']; $cellColSpan = ['gridSpan' => 2, 'valign' => 'center']; -$cellHCentered = ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]; +$cellHCentered = ['alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER]; $cellVCentered = ['valign' => 'center']; $spanTableStyleName = 'Colspan Rowspan'; @@ -134,10 +134,10 @@ $section->addTextBreak(2); $section->addText('Nested table in a centered and 50% width table.', $header); -$table = $section->addTable(['width' => 50 * 50, 'unit' => 'pct', 'alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER]); +$table = $section->addTable(['width' => 50 * 50, 'unit' => 'pct', 'alignment' => PhpOffice\PhpWord\SimpleType\JcTable::CENTER]); $cell = $table->addRow()->addCell(); $cell->addText('This cell contains nested table.'); -$innerCell = $cell->addTable(['alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER])->addRow()->addCell(); +$innerCell = $cell->addTable(['alignment' => PhpOffice\PhpWord\SimpleType\JcTable::CENTER])->addRow()->addCell(); $innerCell->addText('Inside nested table'); // 6. Table with floating position diff --git a/samples/Sample_10_EastAsianFontStyle.php b/samples/Sample_10_EastAsianFontStyle.php index c8a6ec3a5e..f730ab510f 100644 --- a/samples/Sample_10_EastAsianFontStyle.php +++ b/samples/Sample_10_EastAsianFontStyle.php @@ -4,7 +4,7 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); $header = ['size' => 16, 'bold' => true]; //1.Use EastAisa FontStyle diff --git a/samples/Sample_11_ReadWord2007.php b/samples/Sample_11_ReadWord2007.php index 313cc00797..72cdfac625 100644 --- a/samples/Sample_11_ReadWord2007.php +++ b/samples/Sample_11_ReadWord2007.php @@ -7,7 +7,7 @@ $source = __DIR__ . "/resources/{$name}.docx"; echo date('H:i:s'), " Reading contents from `{$source}`", EOL; -$phpWord = \PhpOffice\PhpWord\IOFactory::load($source); +$phpWord = PhpOffice\PhpWord\IOFactory::load($source); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_11_ReadWord97.php b/samples/Sample_11_ReadWord97.php index 4187baaef7..728df6210b 100644 --- a/samples/Sample_11_ReadWord97.php +++ b/samples/Sample_11_ReadWord97.php @@ -4,9 +4,9 @@ // Read contents $name = basename(__FILE__, '.php'); -$source = "resources/{$name}.doc"; +$source = __DIR__ . "/resources/{$name}.doc"; echo date('H:i:s'), " Reading contents from `{$source}`", EOL; -$phpWord = \PhpOffice\PhpWord\IOFactory::load($source, 'MsDoc'); +$phpWord = PhpOffice\PhpWord\IOFactory::load($source, 'MsDoc'); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_12_HeaderFooter.php b/samples/Sample_12_HeaderFooter.php index 081371863a..393e9d1032 100644 --- a/samples/Sample_12_HeaderFooter.php +++ b/samples/Sample_12_HeaderFooter.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New portrait section $section = $phpWord->addSection(); @@ -18,16 +18,16 @@ $textrun = $cell->addTextRun(); $textrun->addText('This is the header with '); $textrun->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub'); -$table->addCell(4500)->addImage('resources/PhpWord.png', ['width' => 80, 'height' => 80, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::END]); +$table->addCell(4500)->addImage(__DIR__ . '/resources/PhpWord.png', ['width' => 80, 'height' => 80, 'alignment' => PhpOffice\PhpWord\SimpleType\Jc::END]); // Add header for all other pages $subsequent = $section->addHeader(); $subsequent->addText('Subsequent pages in Section 1 will Have this!'); -$subsequent->addImage('resources/_mars.jpg', ['width' => 80, 'height' => 80]); +$subsequent->addImage(__DIR__ . '/resources/_mars.jpg', ['width' => 80, 'height' => 80]); // Add footer $footer = $section->addFooter(); -$footer->addPreserveText('Page {PAGE} of {NUMPAGES}.', null, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); +$footer->addPreserveText('Page {PAGE} of {NUMPAGES}.', null, ['alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $footer->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub'); // Write some text diff --git a/samples/Sample_13_Images.php b/samples/Sample_13_Images.php index f351bd91eb..a8ab87ce8c 100644 --- a/samples/Sample_13_Images.php +++ b/samples/Sample_13_Images.php @@ -17,7 +17,7 @@ printSeparator($section); $section->addText('Local image with styles:'); -$section->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 210, 'height' => 210, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); +$section->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 210, 'height' => 210, 'alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER]); // Remote image printSeparator($section); @@ -60,14 +60,14 @@ $section->addImage( __DIR__ . '/resources/_mars.jpg', [ - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), - 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_ABSOLUTE, - 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_RIGHT, - 'posHorizontalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_PAGE, - 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_PAGE, - 'marginLeft' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(15.5), - 'marginTop' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(1.55), + 'width' => Converter::cmToPixel(3), + 'height' => Converter::cmToPixel(3), + 'positioning' => PhpOffice\PhpWord\Style\Image::POSITION_ABSOLUTE, + 'posHorizontal' => PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_RIGHT, + 'posHorizontalRel' => PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_PAGE, + 'posVerticalRel' => PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_PAGE, + 'marginLeft' => Converter::cmToPixel(15.5), + 'marginTop' => Converter::cmToPixel(1.55), ] ); @@ -78,13 +78,13 @@ $section->addImage( __DIR__ . '/resources/_mars.jpg', [ - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), - 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE, - 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_CENTER, - 'posHorizontalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_COLUMN, - 'posVertical' => \PhpOffice\PhpWord\Style\Image::POSITION_VERTICAL_TOP, - 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_LINE, + 'width' => Converter::cmToPixel(3), + 'height' => Converter::cmToPixel(3), + 'positioning' => PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE, + 'posHorizontal' => PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_CENTER, + 'posHorizontalRel' => PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_COLUMN, + 'posVertical' => PhpOffice\PhpWord\Style\Image::POSITION_VERTICAL_TOP, + 'posVerticalRel' => PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_LINE, ] ); diff --git a/samples/Sample_14_ListItem.php b/samples/Sample_14_ListItem.php index 3b509f3577..f82c3ec064 100644 --- a/samples/Sample_14_ListItem.php +++ b/samples/Sample_14_ListItem.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Define styles $fontStyleName = 'myOwnStyle'; @@ -25,7 +25,7 @@ ] ); -$predefinedMultilevelStyle = ['listType' => \PhpOffice\PhpWord\Style\ListItem::TYPE_NUMBER_NESTED]; +$predefinedMultilevelStyle = ['listType' => PhpOffice\PhpWord\Style\ListItem::TYPE_NUMBER_NESTED]; // New section $section = $phpWord->addSection(); diff --git a/samples/Sample_15_Link.php b/samples/Sample_15_Link.php index faef305962..43994deaa2 100644 --- a/samples/Sample_15_Link.php +++ b/samples/Sample_15_Link.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Define styles $linkFontStyleName = 'myOwnLinStyle'; @@ -17,7 +17,7 @@ $section->addLink( 'https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub', - ['color' => '0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE] + ['color' => '0000FF', 'underline' => PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE] ); $section->addTextBreak(2); $section->addLink('http://www.bing.com/', null, $linkFontStyleName); diff --git a/samples/Sample_16_Object.php b/samples/Sample_16_Object.php index b68fb1675b..d3912a6c50 100644 --- a/samples/Sample_16_Object.php +++ b/samples/Sample_16_Object.php @@ -4,13 +4,13 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Begin code $section = $phpWord->addSection(); $section->addText('You can open this OLE object by double clicking on the icon:'); $section->addTextBreak(2); -$section->addOLEObject('resources/_sheet.xls'); +$section->addOLEObject(__DIR__ . '/resources/_sheet.xls'); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_17_TitleTOC.php b/samples/Sample_17_TitleTOC.php index dcf060b0e6..3102ebda83 100644 --- a/samples/Sample_17_TitleTOC.php +++ b/samples/Sample_17_TitleTOC.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $phpWord->getSettings()->setUpdateFields(true); // New section diff --git a/samples/Sample_18_Watermark.php b/samples/Sample_18_Watermark.php index aebb369023..0b3ae34f83 100644 --- a/samples/Sample_18_Watermark.php +++ b/samples/Sample_18_Watermark.php @@ -4,12 +4,12 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Begin code $section = $phpWord->addSection(); $header = $section->addHeader(); -$header->addWatermark('resources/_earth.jpg', ['marginTop' => 200, 'marginLeft' => 55]); +$header->addWatermark(__DIR__ . '/resources/_earth.jpg', ['marginTop' => 200, 'marginLeft' => 55]); $section->addText('The header reference to the current section includes a watermark image.'); // Save file diff --git a/samples/Sample_19_TextBreak.php b/samples/Sample_19_TextBreak.php index 45c79beeb6..0b41110b18 100644 --- a/samples/Sample_19_TextBreak.php +++ b/samples/Sample_19_TextBreak.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Define styles $fontStyle24 = ['size' => 24]; diff --git a/samples/Sample_20_BGColor.php b/samples/Sample_20_BGColor.php index 915a824171..e0ce4d6436 100644 --- a/samples/Sample_20_BGColor.php +++ b/samples/Sample_20_BGColor.php @@ -4,14 +4,14 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New section $section = $phpWord->addSection(); $section->addText( 'This is some text highlighted using fgColor (limited to 15 colors)', - ['fgColor' => \PhpOffice\PhpWord\Style\Font::FGCOLOR_YELLOW] + ['fgColor' => PhpOffice\PhpWord\Style\Font::FGCOLOR_YELLOW] ); $section->addText('This one uses bgColor and is using hex value (0xfbbb10)', ['bgColor' => 'fbbb10']); $section->addText('Compatible with font colors', ['color' => '0000ff', 'bgColor' => 'fbbb10']); diff --git a/samples/Sample_21_TableRowRules.php b/samples/Sample_21_TableRowRules.php index 42fc2d92a5..0ddaa08faf 100644 --- a/samples/Sample_21_TableRowRules.php +++ b/samples/Sample_21_TableRowRules.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New section $section = $phpWord->addSection(); @@ -19,7 +19,7 @@ $table1 = $section->addTable(['cellMargin' => 0, 'cellMarginRight' => 0, 'cellMarginBottom' => 0, 'cellMarginLeft' => 0]); $table1->addRow(3750); $cell1 = $table1->addCell(null, ['valign' => 'top', 'borderSize' => 30, 'borderColor' => 'ff0000']); -$cell1->addImage('./resources/_earth.jpg', ['width' => 250, 'height' => 250, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); +$cell1->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 250, 'height' => 250, 'alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $section->addTextBreak(); $section->addText("But if we set the rowStyle 'exactHeight' to true, the real row height is used, removing the textbreak:"); @@ -34,7 +34,7 @@ ); $table2->addRow(3750, ['exactHeight' => true]); $cell2 = $table2->addCell(null, ['valign' => 'top', 'borderSize' => 30, 'borderColor' => '00ff00']); -$cell2->addImage('./resources/_earth.jpg', ['width' => 250, 'height' => 250, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); +$cell2->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 250, 'height' => 250, 'alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $section->addTextBreak(); $section->addText('In this example, image is 250px height. Rows are calculated in twips, and 1px = 15twips.'); diff --git a/samples/Sample_22_CheckBox.php b/samples/Sample_22_CheckBox.php index 33d4e39c66..91685924b0 100644 --- a/samples/Sample_22_CheckBox.php +++ b/samples/Sample_22_CheckBox.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New section $section = $phpWord->addSection(); diff --git a/samples/Sample_23_TemplateBlock.php b/samples/Sample_23_TemplateBlock.php index 6da66a72d4..4cc541ab3a 100644 --- a/samples/Sample_23_TemplateBlock.php +++ b/samples/Sample_23_TemplateBlock.php @@ -4,7 +4,7 @@ // Template processor instance creation echo date('H:i:s') , ' Creating new TemplateProcessor instance...' , EOL; -$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('resources/Sample_23_TemplateBlock.docx'); +$templateProcessor = new PhpOffice\PhpWord\TemplateProcessor(__DIR__ . '/resources/Sample_23_TemplateBlock.docx'); // Will clone everything between ${tag} and ${/tag}, the number of times. By default, 1. $templateProcessor->cloneBlock('CLONEME', 3); @@ -13,9 +13,9 @@ $templateProcessor->deleteBlock('DELETEME'); echo date('H:i:s'), ' Saving the result document...', EOL; -$templateProcessor->saveAs('results/Sample_23_TemplateBlock.docx'); +$templateProcessor->saveAs(__DIR__ . '/results/Sample_23_TemplateBlock.docx'); -echo getEndingNotes(['Word2007' => 'docx'], 'Sample_23_TemplateBlock'); +echo getEndingNotes(['Word2007' => 'docx'], __DIR__ . '/results/Sample_23_TemplateBlock.docx'); if (!CLI) { include_once 'Sample_Footer.php'; } diff --git a/samples/Sample_24_ReadODText.php b/samples/Sample_24_ReadODText.php index 73c110203e..1b3a43cd57 100644 --- a/samples/Sample_24_ReadODText.php +++ b/samples/Sample_24_ReadODText.php @@ -7,7 +7,7 @@ $source = __DIR__ . "/resources/{$name}.odt"; echo date('H:i:s'), " Reading contents from `{$source}`", EOL; -$phpWord = \PhpOffice\PhpWord\IOFactory::load($source, 'ODText'); +$phpWord = PhpOffice\PhpWord\IOFactory::load($source, 'ODText'); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_25_TextBox.php b/samples/Sample_25_TextBox.php index a897a6269f..3516379d42 100644 --- a/samples/Sample_25_TextBox.php +++ b/samples/Sample_25_TextBox.php @@ -4,7 +4,7 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New section $section = $phpWord->addSection(); @@ -12,7 +12,7 @@ // In section $textbox = $section->addTextBox( [ - 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER, + 'alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER, 'width' => 400, 'height' => 150, 'borderSize' => 1, @@ -39,7 +39,7 @@ $textrun->addText(', '); $textrun->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub'); $textrun->addText(', and image '); -$textrun->addImage('resources/_earth.jpg', ['width' => 18, 'height' => 18]); +$textrun->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 18, 'height' => 18]); $textrun->addText('.'); // Save file diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index daf109966c..971c317c43 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -4,7 +4,7 @@ // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $phpWord->addParagraphStyle('Heading2', ['alignment' => 'center']); $section = $phpWord->addSection(); @@ -93,7 +93,7 @@ $html .= '<p style="margin-top: 240pt;">The text below is not visible, click on show/hide to reveil it:</p>'; $html .= '<p style="display: none">This is hidden text</p>'; -\PhpOffice\PhpWord\Shared\Html::addHtml($section, $html, false, false); +PhpOffice\PhpWord\Shared\Html::addHtml($section, $html, false, false); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_27_Field.php b/samples/Sample_27_Field.php index fd441ba022..e1dbb4f258 100644 --- a/samples/Sample_27_Field.php +++ b/samples/Sample_27_Field.php @@ -6,7 +6,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); PhpOffice\PhpWord\Style::addTitleStyle(1, ['size' => 14]); // New section @@ -49,7 +49,7 @@ $section->addText('The actual index:'); $section->addField('INDEX', [], ['\\e " "'], 'right click to update the index'); -$textrun = $section->addTextRun(['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); +$textrun = $section->addTextRun(['alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $textrun->addText('This is the date of lunar calendar '); $textrun->addField('DATE', ['dateformat' => 'd-M-yyyy H:mm:ss'], ['PreserveFormat', 'LunarCalendar']); $textrun->addText(' written in a textrun.'); diff --git a/samples/Sample_28_ReadRTF.php b/samples/Sample_28_ReadRTF.php index 43b859ac28..52aa74a9a5 100644 --- a/samples/Sample_28_ReadRTF.php +++ b/samples/Sample_28_ReadRTF.php @@ -7,7 +7,7 @@ $source = __DIR__ . "/resources/{$name}.rtf"; echo date('H:i:s'), " Reading contents from `{$source}`", EOL; -$phpWord = \PhpOffice\PhpWord\IOFactory::load($source, 'RTF'); +$phpWord = PhpOffice\PhpWord\IOFactory::load($source, 'RTF'); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_29_Line.php b/samples/Sample_29_Line.php index e5f41b8340..2fdf33c30d 100644 --- a/samples/Sample_29_Line.php +++ b/samples/Sample_29_Line.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New section $section = $phpWord->addSection(); @@ -14,16 +14,16 @@ $section->addText('Horizontal Line (Inline style):'); $section->addLine( [ - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(4), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), + 'width' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(4), + 'height' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), 'positioning' => 'absolute', ] ); $section->addText('Vertical Line (Inline style):'); $section->addLine( [ - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(1), + 'width' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), + 'height' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(1), 'positioning' => 'absolute', ] ); @@ -33,14 +33,14 @@ $section->addText('Positioned Line (red):'); $section->addLine( [ - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(4), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(1), + 'width' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(4), + 'height' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(1), 'positioning' => 'absolute', 'posHorizontalRel' => 'page', 'posVerticalRel' => 'page', - 'marginLeft' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(10), - 'marginTop' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(8), - 'wrappingStyle' => \PhpOffice\PhpWord\Style\Image::WRAPPING_STYLE_SQUARE, + 'marginLeft' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(10), + 'marginTop' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(8), + 'wrappingStyle' => PhpOffice\PhpWord\Style\Image::WRAPPING_STYLE_SQUARE, 'color' => 'red', ] ); @@ -48,12 +48,12 @@ $section->addText('Horizontal Formatted Line'); $section->addLine( [ - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(15), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), + 'width' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(15), + 'height' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), 'positioning' => 'absolute', - 'beginArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_BLOCK, - 'endArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_OVAL, - 'dash' => \PhpOffice\PhpWord\Style\Line::DASH_STYLE_LONG_DASH_DOT_DOT, + 'beginArrow' => PhpOffice\PhpWord\Style\Line::ARROW_STYLE_BLOCK, + 'endArrow' => PhpOffice\PhpWord\Style\Line::ARROW_STYLE_OVAL, + 'dash' => PhpOffice\PhpWord\Style\Line::DASH_STYLE_LONG_DASH_DOT_DOT, 'weight' => 10, ] ); diff --git a/samples/Sample_30_ReadHTML.php b/samples/Sample_30_ReadHTML.php index 8698fe639a..b6564eddc8 100644 --- a/samples/Sample_30_ReadHTML.php +++ b/samples/Sample_30_ReadHTML.php @@ -7,7 +7,7 @@ $source = realpath(__DIR__ . "/resources/{$name}.html"); echo date('H:i:s'), " Reading contents from `{$source}`", EOL; -$phpWord = \PhpOffice\PhpWord\IOFactory::load($source, 'HTML'); +$phpWord = PhpOffice\PhpWord\IOFactory::load($source, 'HTML'); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_31_Shape.php b/samples/Sample_31_Shape.php index 90e364e7be..7f68f3fc2a 100644 --- a/samples/Sample_31_Shape.php +++ b/samples/Sample_31_Shape.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New section $section = $phpWord->addSection(); diff --git a/samples/Sample_32_Chart.php b/samples/Sample_32_Chart.php index 7e99984e41..c8c65e989e 100644 --- a/samples/Sample_32_Chart.php +++ b/samples/Sample_32_Chart.php @@ -6,7 +6,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Define styles $phpWord->addTitleStyle(1, ['size' => 14, 'bold' => true], ['keepNext' => true, 'spaceBefore' => 240]); diff --git a/samples/Sample_33_FormField.php b/samples/Sample_33_FormField.php index 24ef6ee947..223fdd2987 100644 --- a/samples/Sample_33_FormField.php +++ b/samples/Sample_33_FormField.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $phpWord->getSettings()->getDocumentProtection()->setEditing('forms'); // New section diff --git a/samples/Sample_34_SDT.php b/samples/Sample_34_SDT.php index c1722b5b5c..4c8f588e81 100644 --- a/samples/Sample_34_SDT.php +++ b/samples/Sample_34_SDT.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New section $section = $phpWord->addSection(); diff --git a/samples/Sample_35_InternalLink.php b/samples/Sample_35_InternalLink.php index e59c353001..ef10c4b61f 100644 --- a/samples/Sample_35_InternalLink.php +++ b/samples/Sample_35_InternalLink.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); $section->addTitle('This is page 1', 1); diff --git a/samples/Sample_36_RTL.php b/samples/Sample_36_RTL.php index b3baca90cb..e3cf84576a 100644 --- a/samples/Sample_36_RTL.php +++ b/samples/Sample_36_RTL.php @@ -6,7 +6,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $phpWord->setDefaultFontName('DejaVu Sans'); // for good rendition of PDF $rendererName = Settings::PDF_RENDERER_MPDF; $rendererLibraryPath = $vendorDirPath . '/mpdf/mpdf'; @@ -18,17 +18,17 @@ $textrun = $section->addTextRun(); $textrun->addText('This is a Left to Right paragraph.'); -$textrun = $section->addTextRun(['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::END]); +$textrun = $section->addTextRun(['alignment' => PhpOffice\PhpWord\SimpleType\Jc::END]); $textrun->addText('سلام این یک پاراگراف راست به چپ است', ['rtl' => true]); $section->addText('Table visually presented as RTL'); $style = ['rtl' => true, 'size' => 12]; -$tableStyle = ['borderSize' => 6, 'borderColor' => '000000', 'width' => 5000, 'unit' => \PhpOffice\PhpWord\SimpleType\TblWidth::PERCENT, 'bidiVisual' => true]; +$tableStyle = ['borderSize' => 6, 'borderColor' => '000000', 'width' => 5000, 'unit' => PhpOffice\PhpWord\SimpleType\TblWidth::PERCENT, 'bidiVisual' => true]; $table = $section->addTable($tableStyle); -$cellHCentered = ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]; -$cellHEnd = ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::END]; -$cellVCentered = ['valign' => \PhpOffice\PhpWord\SimpleType\VerticalJc::CENTER]; +$cellHCentered = ['alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER]; +$cellHEnd = ['alignment' => PhpOffice\PhpWord\SimpleType\Jc::END]; +$cellVCentered = ['valign' => PhpOffice\PhpWord\SimpleType\VerticalJc::CENTER]; //Vidually bidirectinal table $table->addRow(); diff --git a/samples/Sample_37_Comments.php b/samples/Sample_37_Comments.php index 8254f35c6d..ac03a699e4 100644 --- a/samples/Sample_37_Comments.php +++ b/samples/Sample_37_Comments.php @@ -4,10 +4,10 @@ // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // A comment -$comment = new \PhpOffice\PhpWord\Element\Comment('Authors name', new \DateTime(), 'my_initials'); +$comment = new PhpOffice\PhpWord\Element\Comment('Authors name', new DateTime(), 'my_initials'); $comment->addText('Test', ['bold' => true]); $phpWord->addComment($comment); @@ -22,7 +22,7 @@ $section->addTextBreak(2); // Let's create a comment that we will link to a start element and an end element -$commentWithStartAndEnd = new \PhpOffice\PhpWord\Element\Comment('Foo Bar', new \DateTime()); +$commentWithStartAndEnd = new PhpOffice\PhpWord\Element\Comment('Foo Bar', new DateTime()); $commentWithStartAndEnd->addText('A comment with a start and an end'); $phpWord->addComment($commentWithStartAndEnd); @@ -37,7 +37,7 @@ $section->addTextBreak(2); // Let's add a comment on an image -$commentOnImage = new \PhpOffice\PhpWord\Element\Comment('Mr Smart', new \DateTime()); +$commentOnImage = new PhpOffice\PhpWord\Element\Comment('Mr Smart', new DateTime()); $imageComment = $commentOnImage->addTextRun(); $imageComment->addText('Hey, Mars does look '); $imageComment->addText('red', ['color' => 'FF0000']); @@ -50,7 +50,7 @@ // We can also do things the other way round, link the comment to the element $anotherText = $section->addText('another text'); -$comment1 = new \PhpOffice\PhpWord\Element\Comment('Authors name', new \DateTime(), 'my_initials'); +$comment1 = new PhpOffice\PhpWord\Element\Comment('Authors name', new DateTime(), 'my_initials'); $comment1->addText('Test', ['bold' => true]); $comment1->setStartElement($anotherText); $comment1->setEndElement($anotherText); @@ -59,13 +59,13 @@ // We can also do things the other way round, link the comment to the element $lastText = $section->addText('with a last text and two comments'); -$comment1 = new \PhpOffice\PhpWord\Element\Comment('Authors name', new \DateTime(), 'my_initials'); +$comment1 = new PhpOffice\PhpWord\Element\Comment('Authors name', new DateTime(), 'my_initials'); $comment1->addText('Comment 1', ['bold' => true]); $comment1->setStartElement($lastText); $comment1->setEndElement($lastText); $phpWord->addComment($comment1); -$comment2 = new \PhpOffice\PhpWord\Element\Comment('Authors name', new \DateTime(), 'my_initials'); +$comment2 = new PhpOffice\PhpWord\Element\Comment('Authors name', new DateTime(), 'my_initials'); $comment2->addText('Comment 2', ['bold' => true]); $comment2->setStartElement($lastText); $comment2->setEndElement($lastText); diff --git a/samples/Sample_38_Protection.php b/samples/Sample_38_Protection.php index 9f61538096..737946d51a 100644 --- a/samples/Sample_38_Protection.php +++ b/samples/Sample_38_Protection.php @@ -6,7 +6,7 @@ // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $documentProtection = $phpWord->getSettings()->getDocumentProtection(); $documentProtection->setEditing(DocProtect::READ_ONLY); diff --git a/samples/Sample_39_TrackChanges.php b/samples/Sample_39_TrackChanges.php index a95d98cb81..a2c2bcf61c 100644 --- a/samples/Sample_39_TrackChanges.php +++ b/samples/Sample_39_TrackChanges.php @@ -6,7 +6,7 @@ // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New portrait section $section = $phpWord->addSection(); @@ -21,7 +21,7 @@ $text->setTrackChange(new TrackChange(TrackChange::INSERTED, 'Fred')); $text = $textRun->addText('go to sleep'); -$text->setChangeInfo(TrackChange::DELETED, 'Barney', new \DateTime('@' . (time() - 3600))); +$text->setChangeInfo(TrackChange::DELETED, 'Barney', new DateTime('@' . (time() - 3600))); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_40_TemplateSetComplexValue.php b/samples/Sample_40_TemplateSetComplexValue.php index 38ecb3f7ae..41cbab8950 100644 --- a/samples/Sample_40_TemplateSetComplexValue.php +++ b/samples/Sample_40_TemplateSetComplexValue.php @@ -9,7 +9,7 @@ // Template processor instance creation echo date('H:i:s'), ' Creating new TemplateProcessor instance...', EOL; -$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('resources/Sample_40_TemplateSetComplexValue.docx'); +$templateProcessor = new PhpOffice\PhpWord\TemplateProcessor(__DIR__ . '/resources/Sample_40_TemplateSetComplexValue.docx'); $title = new TextRun(); $title->addText('This title has been set ', ['bold' => true, 'italic' => true, 'color' => 'blue']); @@ -38,9 +38,9 @@ // $templateProcessor->setComplexValue('link', $link); echo date('H:i:s'), ' Saving the result document...', EOL; -$templateProcessor->saveAs('results/Sample_40_TemplateSetComplexValue.docx'); +$templateProcessor->saveAs(__DIR__ . '/results/Sample_40_TemplateSetComplexValue.docx'); -echo getEndingNotes(['Word2007' => 'docx'], 'results/Sample_40_TemplateSetComplexValue.docx'); +echo getEndingNotes(['Word2007' => 'docx'], __DIR__ . '/results/Sample_40_TemplateSetComplexValue.docx'); if (!CLI) { include_once 'Sample_Footer.php'; } diff --git a/samples/Sample_41_TemplateSetChart.php b/samples/Sample_41_TemplateSetChart.php index 88eb2ccbd9..36be5888f7 100644 --- a/samples/Sample_41_TemplateSetChart.php +++ b/samples/Sample_41_TemplateSetChart.php @@ -7,7 +7,7 @@ // Template processor instance creation echo date('H:i:s'), ' Creating new TemplateProcessor instance...', EOL; -$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('resources/Sample_41_TemplateSetChart.docx'); +$templateProcessor = new PhpOffice\PhpWord\TemplateProcessor(__DIR__ . '/resources/Sample_41_TemplateSetChart.docx'); $chartTypes = ['pie', 'doughnut', 'bar', 'column', 'line', 'area', 'scatter', 'radar', 'stacked_bar', 'percent_stacked_bar', 'stacked_column', 'percent_stacked_column']; $twoSeries = ['bar', 'column', 'line', 'area', 'scatter', 'radar', 'stacked_bar', 'percent_stacked_bar', 'stacked_column', 'percent_stacked_column']; @@ -38,9 +38,9 @@ } echo date('H:i:s'), ' Saving the result document...', EOL; -$templateProcessor->saveAs('results/Sample_41_TemplateSetChart.docx'); +$templateProcessor->saveAs(__DIR__ . '/results/Sample_41_TemplateSetChart.docx'); -echo getEndingNotes(['Word2007' => 'docx'], 'results/Sample_41_TemplateSetChart.docx'); +echo getEndingNotes(['Word2007' => 'docx'], __DIR__ . '/results/Sample_41_TemplateSetChart.docx'); if (!CLI) { include_once 'Sample_Footer.php'; } diff --git a/samples/Sample_44_ExtractVariablesFromReaderWord2007.php b/samples/Sample_44_ExtractVariablesFromReaderWord2007.php index 24574e5fb7..8c1703499f 100644 --- a/samples/Sample_44_ExtractVariablesFromReaderWord2007.php +++ b/samples/Sample_44_ExtractVariablesFromReaderWord2007.php @@ -9,6 +9,6 @@ echo date('H:i:s'), " Reading contents from `{$source}`", EOL; -$variables = \PhpOffice\PhpWord\IOFactory::extractVariables($source); +$variables = PhpOffice\PhpWord\IOFactory::extractVariables($source); var_dump($variables); diff --git a/samples/Sample_Header.php b/samples/Sample_Header.php index 8d05a2a34e..679848ad83 100644 --- a/samples/Sample_Header.php +++ b/samples/Sample_Header.php @@ -61,7 +61,7 @@ /** * Write documents. * - * @param \PhpOffice\PhpWord\PhpWord $phpWord + * @param PhpOffice\PhpWord\PhpWord $phpWord * @param string $filename * @param array $writers * diff --git a/src/PhpWord/Collection/AbstractCollection.php b/src/PhpWord/Collection/AbstractCollection.php index 646489d886..97c2c45dcf 100644 --- a/src/PhpWord/Collection/AbstractCollection.php +++ b/src/PhpWord/Collection/AbstractCollection.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -21,6 +22,7 @@ * Collection abstract class. * * @since 0.10.0 + * * @template T */ abstract class AbstractCollection diff --git a/src/PhpWord/Collection/Bookmarks.php b/src/PhpWord/Collection/Bookmarks.php index 71544c9469..0694bf7dd8 100644 --- a/src/PhpWord/Collection/Bookmarks.php +++ b/src/PhpWord/Collection/Bookmarks.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -23,6 +24,7 @@ * Bookmarks collection. * * @since 0.12.0 + * * @extends AbstractCollection<Bookmark> */ class Bookmarks extends AbstractCollection diff --git a/src/PhpWord/Collection/Charts.php b/src/PhpWord/Collection/Charts.php index 7c2dfbab94..ef1c6597ff 100644 --- a/src/PhpWord/Collection/Charts.php +++ b/src/PhpWord/Collection/Charts.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -23,6 +24,7 @@ * Charts collection. * * @since 0.12.0 + * * @extends AbstractCollection<Chart> */ class Charts extends AbstractCollection diff --git a/src/PhpWord/Collection/Comments.php b/src/PhpWord/Collection/Comments.php index 5fa4020a5a..4f1394359f 100644 --- a/src/PhpWord/Collection/Comments.php +++ b/src/PhpWord/Collection/Comments.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -23,6 +24,7 @@ * Comments collection. * * @since 0.12.0 + * * @extends AbstractCollection<Comment> */ class Comments extends AbstractCollection diff --git a/src/PhpWord/Collection/Endnotes.php b/src/PhpWord/Collection/Endnotes.php index 09903b1bf6..3de1ad22d5 100644 --- a/src/PhpWord/Collection/Endnotes.php +++ b/src/PhpWord/Collection/Endnotes.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -23,6 +24,7 @@ * Endnotes collection. * * @since 0.10.0 + * * @extends AbstractCollection<Endnote> */ class Endnotes extends AbstractCollection diff --git a/src/PhpWord/Collection/Footnotes.php b/src/PhpWord/Collection/Footnotes.php index 0387fce3c7..804a45c873 100644 --- a/src/PhpWord/Collection/Footnotes.php +++ b/src/PhpWord/Collection/Footnotes.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -23,6 +24,7 @@ * Footnotes collection. * * @since 0.10.0 + * * @extends AbstractCollection<Footnote> */ class Footnotes extends AbstractCollection diff --git a/src/PhpWord/Collection/Titles.php b/src/PhpWord/Collection/Titles.php index 543aabda1d..1a943697d2 100644 --- a/src/PhpWord/Collection/Titles.php +++ b/src/PhpWord/Collection/Titles.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -23,6 +24,7 @@ * Titles collection. * * @since 0.10.0 + * * @extends AbstractCollection<Title> */ class Titles extends AbstractCollection diff --git a/src/PhpWord/ComplexType/FootnoteProperties.php b/src/PhpWord/ComplexType/FootnoteProperties.php index 2e7743ca08..10c426e84c 100644 --- a/src/PhpWord/ComplexType/FootnoteProperties.php +++ b/src/PhpWord/ComplexType/FootnoteProperties.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/ComplexType/ProofState.php b/src/PhpWord/ComplexType/ProofState.php index 37039cb84e..0731238201 100644 --- a/src/PhpWord/ComplexType/ProofState.php +++ b/src/PhpWord/ComplexType/ProofState.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/ComplexType/TblWidth.php b/src/PhpWord/ComplexType/TblWidth.php index 6a9368f464..f1c0e10c9c 100644 --- a/src/PhpWord/ComplexType/TblWidth.php +++ b/src/PhpWord/ComplexType/TblWidth.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/ComplexType/TrackChangesView.php b/src/PhpWord/ComplexType/TrackChangesView.php index 4331047414..a9797fad4a 100644 --- a/src/PhpWord/ComplexType/TrackChangesView.php +++ b/src/PhpWord/ComplexType/TrackChangesView.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index f9b2822a12..f989e1069c 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -58,7 +59,7 @@ abstract class AbstractContainer extends AbstractElement /** * Elements collection. * - * @var \PhpOffice\PhpWord\Element\AbstractElement[] + * @var AbstractElement[] */ protected $elements = []; @@ -80,7 +81,7 @@ abstract class AbstractContainer extends AbstractElement * @param mixed $function * @param mixed $args * - * @return \PhpOffice\PhpWord\Element\AbstractElement + * @return AbstractElement */ public function __call($function, $args) { @@ -130,7 +131,7 @@ public function __call($function, $args) * * @param string $elementName * - * @return \PhpOffice\PhpWord\Element\AbstractElement + * @return AbstractElement */ protected function addElement($elementName) { @@ -149,7 +150,7 @@ protected function addElement($elementName) $elementArgs = $args; array_shift($elementArgs); // Shift the $elementName off the beginning of array - /** @var \PhpOffice\PhpWord\Element\AbstractElement $element Type hint */ + /** @var AbstractElement $element Type hint */ $element = $reflection->newInstanceArgs($elementArgs); // Set parent container @@ -165,7 +166,7 @@ protected function addElement($elementName) /** * Get all elements. * - * @return \PhpOffice\PhpWord\Element\AbstractElement[] + * @return AbstractElement[] */ public function getElements() { @@ -177,7 +178,7 @@ public function getElements() * * @param int $index * - * @return null|\PhpOffice\PhpWord\Element\AbstractElement + * @return null|AbstractElement */ public function getElement($index) { @@ -191,13 +192,13 @@ public function getElement($index) /** * Removes the element at requested index. * - * @param int|\PhpOffice\PhpWord\Element\AbstractElement $toRemove + * @param AbstractElement|int $toRemove */ public function removeElement($toRemove): void { if (is_int($toRemove) && array_key_exists($toRemove, $this->elements)) { unset($this->elements[$toRemove]); - } elseif ($toRemove instanceof \PhpOffice\PhpWord\Element\AbstractElement) { + } elseif ($toRemove instanceof AbstractElement) { foreach ($this->elements as $key => $element) { if ($element->getElementId() === $toRemove->getElementId()) { unset($this->elements[$key]); diff --git a/src/PhpWord/Element/AbstractElement.php b/src/PhpWord/Element/AbstractElement.php index 385e4d3140..3a29b68673 100644 --- a/src/PhpWord/Element/AbstractElement.php +++ b/src/PhpWord/Element/AbstractElement.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -148,8 +149,6 @@ abstract class AbstractElement /** * Get PhpWord. - * - * @return ?PhpWord */ public function getPhpWord(): ?PhpWord { @@ -256,7 +255,7 @@ public function getElementId() */ public function setElementId(): void { - $this->elementId = substr(md5(mt_rand()), 0, 6); + $this->elementId = substr(md5((string) mt_rand()), 0, 6); } /** @@ -291,8 +290,6 @@ public function getNestedLevel() /** * Get comments start. - * - * @return Comments */ public function getCommentsRangeStart(): ?Comments { @@ -301,8 +298,6 @@ public function getCommentsRangeStart(): ?Comments /** * Get comment start. - * - * @return Comment */ public function getCommentRangeStart(): ?Comment { @@ -339,8 +334,6 @@ public function setCommentRangeStart(Comment $value): void /** * Get comments end. - * - * @return Comments */ public function getCommentsRangeEnd(): ?Comments { @@ -349,8 +342,6 @@ public function getCommentsRangeEnd(): ?Comments /** * Get comment end. - * - * @return Comment */ public function getCommentRangeEnd(): ?Comment { diff --git a/src/PhpWord/Element/Bookmark.php b/src/PhpWord/Element/Bookmark.php index 4fe3d0f067..151d5a48bf 100644 --- a/src/PhpWord/Element/Bookmark.php +++ b/src/PhpWord/Element/Bookmark.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Element/Cell.php b/src/PhpWord/Element/Cell.php index b0aa0c4ed4..2adcc1ab54 100644 --- a/src/PhpWord/Element/Cell.php +++ b/src/PhpWord/Element/Cell.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -39,7 +40,7 @@ class Cell extends AbstractContainer /** * Cell style. * - * @var ?\PhpOffice\PhpWord\Style\Cell + * @var ?CellStyle */ private $style; @@ -47,7 +48,7 @@ class Cell extends AbstractContainer * Create new instance. * * @param null|int $width - * @param array|\PhpOffice\PhpWord\Style\Cell $style + * @param array|CellStyle $style */ public function __construct($width = null, $style = null) { @@ -58,7 +59,7 @@ public function __construct($width = null, $style = null) /** * Get cell style. * - * @return ?\PhpOffice\PhpWord\Style\Cell + * @return ?CellStyle */ public function getStyle() { diff --git a/src/PhpWord/Element/Chart.php b/src/PhpWord/Element/Chart.php index 4f652f2512..7aa49fb9f5 100644 --- a/src/PhpWord/Element/Chart.php +++ b/src/PhpWord/Element/Chart.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -50,7 +51,7 @@ class Chart extends AbstractElement /** * Chart style. * - * @var ?\PhpOffice\PhpWord\Style\Chart + * @var ?ChartStyle */ private $style; @@ -120,7 +121,7 @@ public function getSeries() /** * Get chart style. * - * @return ?\PhpOffice\PhpWord\Style\Chart + * @return ?ChartStyle */ public function getStyle() { diff --git a/src/PhpWord/Element/CheckBox.php b/src/PhpWord/Element/CheckBox.php index 80b17a87c7..b404a6027e 100644 --- a/src/PhpWord/Element/CheckBox.php +++ b/src/PhpWord/Element/CheckBox.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Element/Comment.php b/src/PhpWord/Element/Comment.php index 9173c49148..a6a2e29d56 100644 --- a/src/PhpWord/Element/Comment.php +++ b/src/PhpWord/Element/Comment.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -89,7 +90,7 @@ public function setStartElement(AbstractElement $value): void /** * Get the element where this comment starts. * - * @return \PhpOffice\PhpWord\Element\AbstractElement + * @return AbstractElement */ public function getStartElement() { @@ -108,7 +109,7 @@ public function setEndElement(AbstractElement $value): void /** * Get the element where this comment ends. * - * @return \PhpOffice\PhpWord\Element\AbstractElement + * @return AbstractElement */ public function getEndElement() { diff --git a/src/PhpWord/Element/Endnote.php b/src/PhpWord/Element/Endnote.php index 2888fdebc3..d2f42eafd0 100644 --- a/src/PhpWord/Element/Endnote.php +++ b/src/PhpWord/Element/Endnote.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Element/Field.php b/src/PhpWord/Element/Field.php index a828aaa02e..cb6ac070f0 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -128,16 +129,16 @@ class Field extends AbstractElement /** * Font style. * - * @var \PhpOffice\PhpWord\Style\Font|string + * @var Font|string */ protected $fontStyle; /** * Set Font style. * - * @param array|\PhpOffice\PhpWord\Style\Font|string $style + * @param array|Font|string $style * - * @return \PhpOffice\PhpWord\Style\Font|string + * @return Font|string */ public function setFontStyle($style = null) { @@ -158,7 +159,7 @@ public function setFontStyle($style = null) /** * Get Font style. * - * @return \PhpOffice\PhpWord\Style\Font|string + * @return Font|string */ public function getFontStyle() { @@ -172,7 +173,7 @@ public function getFontStyle() * @param array $properties * @param array $options * @param null|string|TextRun $text - * @param array|\PhpOffice\PhpWord\Style\Font|string $fontStyle + * @param array|Font|string $fontStyle */ public function __construct($type = null, $properties = [], $options = [], $text = null, $fontStyle = null) { diff --git a/src/PhpWord/Element/Footer.php b/src/PhpWord/Element/Footer.php index a9c48f7714..d17db10a32 100644 --- a/src/PhpWord/Element/Footer.php +++ b/src/PhpWord/Element/Footer.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Element/Footnote.php b/src/PhpWord/Element/Footnote.php index 7a08091abc..6f959c2432 100644 --- a/src/PhpWord/Element/Footnote.php +++ b/src/PhpWord/Element/Footnote.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -29,7 +30,7 @@ class Footnote extends AbstractContainer /** * Paragraph style. * - * @var null|\PhpOffice\PhpWord\Style\Paragraph|string + * @var null|Paragraph|string */ protected $paragraphStyle; @@ -43,7 +44,7 @@ class Footnote extends AbstractContainer /** * Create new instance. * - * @param array|\PhpOffice\PhpWord\Style\Paragraph|string $paragraphStyle + * @param array|Paragraph|string $paragraphStyle */ public function __construct($paragraphStyle = null) { @@ -54,7 +55,7 @@ public function __construct($paragraphStyle = null) /** * Get paragraph style. * - * @return null|\PhpOffice\PhpWord\Style\Paragraph|string + * @return null|Paragraph|string */ public function getParagraphStyle() { diff --git a/src/PhpWord/Element/FormField.php b/src/PhpWord/Element/FormField.php index ef8c22fe47..5318134584 100644 --- a/src/PhpWord/Element/FormField.php +++ b/src/PhpWord/Element/FormField.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Element/Formula.php b/src/PhpWord/Element/Formula.php index ca9f5d6b4b..76bef4f683 100644 --- a/src/PhpWord/Element/Formula.php +++ b/src/PhpWord/Element/Formula.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Element/Header.php b/src/PhpWord/Element/Header.php index 9a87241609..81a493f3f2 100644 --- a/src/PhpWord/Element/Header.php +++ b/src/PhpWord/Element/Header.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php index 12d637d7d2..c47e5effa5 100644 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Element/Line.php b/src/PhpWord/Element/Line.php index 40ad75c799..b3ad438197 100644 --- a/src/PhpWord/Element/Line.php +++ b/src/PhpWord/Element/Line.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -27,7 +28,7 @@ class Line extends AbstractElement /** * Line style. * - * @var ?\PhpOffice\PhpWord\Style\Line + * @var ?LineStyle */ private $style; @@ -44,7 +45,7 @@ public function __construct($style = null) /** * Get line style. * - * @return ?\PhpOffice\PhpWord\Style\Line + * @return ?LineStyle */ public function getStyle() { diff --git a/src/PhpWord/Element/Link.php b/src/PhpWord/Element/Link.php index b8acba1d3b..755fd7ba0f 100644 --- a/src/PhpWord/Element/Link.php +++ b/src/PhpWord/Element/Link.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -43,14 +44,14 @@ class Link extends AbstractElement /** * Font style. * - * @var null|\PhpOffice\PhpWord\Style\Font|string + * @var null|Font|string */ private $fontStyle; /** * Paragraph style. * - * @var null|\PhpOffice\PhpWord\Style\Paragraph|string + * @var null|Paragraph|string */ private $paragraphStyle; @@ -109,7 +110,7 @@ public function getText() /** * Get Text style. * - * @return null|\PhpOffice\PhpWord\Style\Font|string + * @return null|Font|string */ public function getFontStyle() { @@ -119,7 +120,7 @@ public function getFontStyle() /** * Get Paragraph style. * - * @return null|\PhpOffice\PhpWord\Style\Paragraph|string + * @return null|Paragraph|string */ public function getParagraphStyle() { diff --git a/src/PhpWord/Element/ListItem.php b/src/PhpWord/Element/ListItem.php index d3f25c29b7..bedfd110b6 100644 --- a/src/PhpWord/Element/ListItem.php +++ b/src/PhpWord/Element/ListItem.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -28,14 +29,14 @@ class ListItem extends AbstractElement /** * Element style. * - * @var ?\PhpOffice\PhpWord\Style\ListItem + * @var ?ListItemStyle */ private $style; /** * Text object. * - * @var \PhpOffice\PhpWord\Element\Text + * @var Text */ private $textObject; @@ -71,7 +72,7 @@ public function __construct($text, $depth = 0, $fontStyle = null, $listStyle = n /** * Get style. * - * @return ?\PhpOffice\PhpWord\Style\ListItem + * @return ?ListItemStyle */ public function getStyle() { @@ -81,7 +82,7 @@ public function getStyle() /** * Get Text object. * - * @return \PhpOffice\PhpWord\Element\Text + * @return Text */ public function getTextObject() { diff --git a/src/PhpWord/Element/ListItemRun.php b/src/PhpWord/Element/ListItemRun.php index 7a63337093..01d0947b81 100644 --- a/src/PhpWord/Element/ListItemRun.php +++ b/src/PhpWord/Element/ListItemRun.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -32,7 +33,7 @@ class ListItemRun extends TextRun /** * ListItem Style. * - * @var ?\PhpOffice\PhpWord\Style\ListItem + * @var ?ListItemStyle */ private $style; @@ -66,7 +67,7 @@ public function __construct($depth = 0, $listStyle = null, $paragraphStyle = nul /** * Get ListItem style. * - * @return ?\PhpOffice\PhpWord\Style\ListItem + * @return ?ListItemStyle */ public function getStyle() { diff --git a/src/PhpWord/Element/OLEObject.php b/src/PhpWord/Element/OLEObject.php index 73645e07f2..74c31a79ed 100644 --- a/src/PhpWord/Element/OLEObject.php +++ b/src/PhpWord/Element/OLEObject.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -35,7 +36,7 @@ class OLEObject extends AbstractElement /** * Image Style. * - * @var ?\PhpOffice\PhpWord\Style\Image + * @var ?ImageStyle */ private $style; @@ -100,7 +101,7 @@ public function getSource() /** * Get object style. * - * @return ?\PhpOffice\PhpWord\Style\Image + * @return ?ImageStyle */ public function getStyle() { diff --git a/src/PhpWord/Element/PageBreak.php b/src/PhpWord/Element/PageBreak.php index 02f5989f1d..950f0b7d5f 100644 --- a/src/PhpWord/Element/PageBreak.php +++ b/src/PhpWord/Element/PageBreak.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Element/PreserveText.php b/src/PhpWord/Element/PreserveText.php index 7370b63743..b218cc7a0f 100644 --- a/src/PhpWord/Element/PreserveText.php +++ b/src/PhpWord/Element/PreserveText.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -36,14 +37,14 @@ class PreserveText extends AbstractElement /** * Text style. * - * @var null|\PhpOffice\PhpWord\Style\Font|string + * @var null|Font|string */ private $fontStyle; /** * Paragraph style. * - * @var null|\PhpOffice\PhpWord\Style\Paragraph|string + * @var null|Paragraph|string */ private $paragraphStyle; @@ -69,7 +70,7 @@ public function __construct($text = null, $fontStyle = null, $paragraphStyle = n /** * Get Text style. * - * @return null|\PhpOffice\PhpWord\Style\Font|string + * @return null|Font|string */ public function getFontStyle() { @@ -79,7 +80,7 @@ public function getFontStyle() /** * Get Paragraph style. * - * @return null|\PhpOffice\PhpWord\Style\Paragraph|string + * @return null|Paragraph|string */ public function getParagraphStyle() { diff --git a/src/PhpWord/Element/Row.php b/src/PhpWord/Element/Row.php index f97df595f2..af8c19dd84 100644 --- a/src/PhpWord/Element/Row.php +++ b/src/PhpWord/Element/Row.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -36,14 +37,14 @@ class Row extends AbstractElement /** * Row style. * - * @var ?\PhpOffice\PhpWord\Style\Row + * @var ?RowStyle */ private $style; /** * Row cells. * - * @var \PhpOffice\PhpWord\Element\Cell[] + * @var Cell[] */ private $cells = []; @@ -65,7 +66,7 @@ public function __construct($height = null, $style = null) * @param int $width * @param mixed $style * - * @return \PhpOffice\PhpWord\Element\Cell + * @return Cell */ public function addCell($width = null, $style = null) { @@ -79,7 +80,7 @@ public function addCell($width = null, $style = null) /** * Get all cells. * - * @return \PhpOffice\PhpWord\Element\Cell[] + * @return Cell[] */ public function getCells() { @@ -89,7 +90,7 @@ public function getCells() /** * Get row style. * - * @return ?\PhpOffice\PhpWord\Style\Row + * @return ?RowStyle */ public function getStyle() { diff --git a/src/PhpWord/Element/SDT.php b/src/PhpWord/Element/SDT.php index 561cb9dd9e..62a66c0426 100644 --- a/src/PhpWord/Element/SDT.php +++ b/src/PhpWord/Element/SDT.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Element/Section.php b/src/PhpWord/Element/Section.php index dbba7f5ccb..cf765792dc 100644 --- a/src/PhpWord/Element/Section.php +++ b/src/PhpWord/Element/Section.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -31,7 +32,7 @@ class Section extends AbstractContainer /** * Section style. * - * @var ?\PhpOffice\PhpWord\Style\Section + * @var ?SectionStyle */ private $style; @@ -87,7 +88,7 @@ public function setStyle($style = null): void /** * Get section style. * - * @return ?\PhpOffice\PhpWord\Style\Section + * @return ?SectionStyle */ public function getStyle() { @@ -196,14 +197,14 @@ public function hasDifferentFirstPage() */ private function addHeaderFooter($type = Header::AUTO, $header = true) { - $containerClass = substr(static::class, 0, strrpos(static::class, '\\')) . '\\' . + $containerClass = substr(static::class, 0, strrpos(static::class, '\\') ?: 0) . '\\' . ($header ? 'Header' : 'Footer'); $collectionArray = $header ? 'headers' : 'footers'; $collection = &$this->$collectionArray; if (in_array($type, [Header::AUTO, Header::FIRST, Header::EVEN])) { $index = count($collection); - /** @var \PhpOffice\PhpWord\Element\AbstractContainer $container Type hint */ + /** @var AbstractContainer $container Type hint */ $container = new $containerClass($this->sectionId, ++$index, $type); $container->setPhpWord($this->phpWord); diff --git a/src/PhpWord/Element/Shape.php b/src/PhpWord/Element/Shape.php index 15161f892e..9ea221db3b 100644 --- a/src/PhpWord/Element/Shape.php +++ b/src/PhpWord/Element/Shape.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -36,7 +37,7 @@ class Shape extends AbstractElement /** * Shape style. * - * @var ?\PhpOffice\PhpWord\Style\Shape + * @var ?ShapeStyle */ private $style; @@ -80,7 +81,7 @@ public function setType($value = null) /** * Get shape style. * - * @return ?\PhpOffice\PhpWord\Style\Shape + * @return ?ShapeStyle */ public function getStyle() { diff --git a/src/PhpWord/Element/TOC.php b/src/PhpWord/Element/TOC.php index 320c3e9975..8f8e71f65a 100644 --- a/src/PhpWord/Element/TOC.php +++ b/src/PhpWord/Element/TOC.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -29,14 +30,14 @@ class TOC extends AbstractElement /** * TOC style. * - * @var \PhpOffice\PhpWord\Style\TOC + * @var TOCStyle */ private $tocStyle; /** * Font style. * - * @var \PhpOffice\PhpWord\Style\Font|string + * @var Font|string */ private $fontStyle; @@ -94,7 +95,7 @@ public function getTitles() $titles = $this->phpWord->getTitles()->getItems(); foreach ($titles as $i => $title) { - /** @var \PhpOffice\PhpWord\Element\Title $title Type hint */ + /** @var Title $title Type hint */ $depth = $title->getDepth(); if ($this->minDepth > $depth) { unset($titles[$i]); @@ -110,7 +111,7 @@ public function getTitles() /** * Get TOC Style. * - * @return \PhpOffice\PhpWord\Style\TOC + * @return TOCStyle */ public function getStyleTOC() { @@ -120,7 +121,7 @@ public function getStyleTOC() /** * Get Font Style. * - * @return \PhpOffice\PhpWord\Style\Font|string + * @return Font|string */ public function getStyleFont() { diff --git a/src/PhpWord/Element/Table.php b/src/PhpWord/Element/Table.php index 53a828a9ea..7fb1030638 100644 --- a/src/PhpWord/Element/Table.php +++ b/src/PhpWord/Element/Table.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -27,14 +28,14 @@ class Table extends AbstractElement /** * Table style. * - * @var ?\PhpOffice\PhpWord\Style\Table + * @var ?TableStyle */ private $style; /** * Table rows. * - * @var \PhpOffice\PhpWord\Element\Row[] + * @var Row[] */ private $rows = []; @@ -61,7 +62,7 @@ public function __construct($style = null) * @param int $height * @param mixed $style * - * @return \PhpOffice\PhpWord\Element\Row + * @return Row */ public function addRow($height = null, $style = null) { @@ -78,7 +79,7 @@ public function addRow($height = null, $style = null) * @param int $width * @param mixed $style * - * @return \PhpOffice\PhpWord\Element\Cell + * @return Cell */ public function addCell($width = null, $style = null) { @@ -92,7 +93,7 @@ public function addCell($width = null, $style = null) /** * Get all rows. * - * @return \PhpOffice\PhpWord\Element\Row[] + * @return Row[] */ public function getRows() { @@ -102,7 +103,7 @@ public function getRows() /** * Get table style. * - * @return null|\PhpOffice\PhpWord\Style\Table|string + * @return null|string|TableStyle */ public function getStyle() { @@ -140,7 +141,7 @@ public function countColumns() $rowCount = count($this->rows); for ($i = 0; $i < $rowCount; ++$i) { - /** @var \PhpOffice\PhpWord\Element\Row $row Type hint */ + /** @var Row $row Type hint */ $row = $this->rows[$i]; $cellCount = count($row->getCells()); if ($columnCount < $cellCount) { diff --git a/src/PhpWord/Element/Text.php b/src/PhpWord/Element/Text.php index 9695395324..ea5f5f87a4 100644 --- a/src/PhpWord/Element/Text.php +++ b/src/PhpWord/Element/Text.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -36,14 +37,14 @@ class Text extends AbstractElement /** * Text style. * - * @var \PhpOffice\PhpWord\Style\Font|string + * @var Font|string */ protected $fontStyle; /** * Paragraph style. * - * @var \PhpOffice\PhpWord\Style\Paragraph|string + * @var Paragraph|string */ protected $paragraphStyle; @@ -64,10 +65,10 @@ public function __construct($text = null, $fontStyle = null, $paragraphStyle = n /** * Set Text style. * - * @param array|\PhpOffice\PhpWord\Style\Font|string $style - * @param array|\PhpOffice\PhpWord\Style\Paragraph|string $paragraphStyle + * @param array|Font|string $style + * @param array|Paragraph|string $paragraphStyle * - * @return \PhpOffice\PhpWord\Style\Font|string + * @return Font|string */ public function setFontStyle($style = null, $paragraphStyle = null) { @@ -90,7 +91,7 @@ public function setFontStyle($style = null, $paragraphStyle = null) /** * Get Text style. * - * @return \PhpOffice\PhpWord\Style\Font|string + * @return Font|string */ public function getFontStyle() { @@ -100,9 +101,9 @@ public function getFontStyle() /** * Set Paragraph style. * - * @param array|\PhpOffice\PhpWord\Style\Paragraph|string $style + * @param array|Paragraph|string $style * - * @return \PhpOffice\PhpWord\Style\Paragraph|string + * @return Paragraph|string */ public function setParagraphStyle($style = null) { @@ -123,7 +124,7 @@ public function setParagraphStyle($style = null) /** * Get Paragraph style. * - * @return \PhpOffice\PhpWord\Style\Paragraph|string + * @return Paragraph|string */ public function getParagraphStyle() { diff --git a/src/PhpWord/Element/TextBox.php b/src/PhpWord/Element/TextBox.php index af37f65772..b9f8b50bc5 100644 --- a/src/PhpWord/Element/TextBox.php +++ b/src/PhpWord/Element/TextBox.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -34,7 +35,7 @@ class TextBox extends AbstractContainer /** * TextBox style. * - * @var ?\PhpOffice\PhpWord\Style\TextBox + * @var ?TextBoxStyle */ private $style; @@ -51,7 +52,7 @@ public function __construct($style = null) /** * Get textbox style. * - * @return ?\PhpOffice\PhpWord\Style\TextBox + * @return ?TextBoxStyle */ public function getStyle() { diff --git a/src/PhpWord/Element/TextBreak.php b/src/PhpWord/Element/TextBreak.php index c3cd087d74..8bfac74102 100644 --- a/src/PhpWord/Element/TextBreak.php +++ b/src/PhpWord/Element/TextBreak.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -28,14 +29,14 @@ class TextBreak extends AbstractElement /** * Paragraph style. * - * @var null|\PhpOffice\PhpWord\Style\Paragraph|string + * @var null|Paragraph|string */ private $paragraphStyle; /** * Text style. * - * @var null|\PhpOffice\PhpWord\Style\Font|string + * @var null|Font|string */ private $fontStyle; @@ -61,7 +62,7 @@ public function __construct($fontStyle = null, $paragraphStyle = null) * @param mixed $style * @param mixed $paragraphStyle * - * @return \PhpOffice\PhpWord\Style\Font|string + * @return Font|string */ public function setFontStyle($style = null, $paragraphStyle = null) { @@ -82,7 +83,7 @@ public function setFontStyle($style = null, $paragraphStyle = null) /** * Get Text style. * - * @return null|\PhpOffice\PhpWord\Style\Font|string + * @return null|Font|string */ public function getFontStyle() { @@ -92,9 +93,9 @@ public function getFontStyle() /** * Set Paragraph style. * - * @param array|\PhpOffice\PhpWord\Style\Paragraph|string $style + * @param array|Paragraph|string $style * - * @return \PhpOffice\PhpWord\Style\Paragraph|string + * @return Paragraph|string */ public function setParagraphStyle($style = null) { @@ -113,7 +114,7 @@ public function setParagraphStyle($style = null) /** * Get Paragraph style. * - * @return null|\PhpOffice\PhpWord\Style\Paragraph|string + * @return null|Paragraph|string */ public function getParagraphStyle() { diff --git a/src/PhpWord/Element/TextRun.php b/src/PhpWord/Element/TextRun.php index 8ddc9cd7ba..5dc8ef53c7 100644 --- a/src/PhpWord/Element/TextRun.php +++ b/src/PhpWord/Element/TextRun.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Element/Title.php b/src/PhpWord/Element/Title.php index 8fd5b21b1d..89f438a5ef 100644 --- a/src/PhpWord/Element/Title.php +++ b/src/PhpWord/Element/Title.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Element/TrackChange.php b/src/PhpWord/Element/TrackChange.php index 064e6380b7..3539bdc627 100644 --- a/src/PhpWord/Element/TrackChange.php +++ b/src/PhpWord/Element/TrackChange.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Escaper/AbstractEscaper.php b/src/PhpWord/Escaper/AbstractEscaper.php index 28e33818a4..9c5dca39e0 100644 --- a/src/PhpWord/Escaper/AbstractEscaper.php +++ b/src/PhpWord/Escaper/AbstractEscaper.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Escaper/EscaperInterface.php b/src/PhpWord/Escaper/EscaperInterface.php index ac68058ed2..a2f7d425ad 100644 --- a/src/PhpWord/Escaper/EscaperInterface.php +++ b/src/PhpWord/Escaper/EscaperInterface.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Escaper/RegExp.php b/src/PhpWord/Escaper/RegExp.php index 84f6faee99..c120d62621 100644 --- a/src/PhpWord/Escaper/RegExp.php +++ b/src/PhpWord/Escaper/RegExp.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Escaper/Rtf.php b/src/PhpWord/Escaper/Rtf.php index 842e3adc91..815e3a2751 100644 --- a/src/PhpWord/Escaper/Rtf.php +++ b/src/PhpWord/Escaper/Rtf.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Escaper/Xml.php b/src/PhpWord/Escaper/Xml.php index 446ea771d0..70e9cc21a4 100644 --- a/src/PhpWord/Escaper/Xml.php +++ b/src/PhpWord/Escaper/Xml.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Exception/CopyFileException.php b/src/PhpWord/Exception/CopyFileException.php index 2ee8187165..cd39f6401a 100644 --- a/src/PhpWord/Exception/CopyFileException.php +++ b/src/PhpWord/Exception/CopyFileException.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Exception/CreateTemporaryFileException.php b/src/PhpWord/Exception/CreateTemporaryFileException.php index 7be01d6750..294c542bfb 100644 --- a/src/PhpWord/Exception/CreateTemporaryFileException.php +++ b/src/PhpWord/Exception/CreateTemporaryFileException.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Exception/Exception.php b/src/PhpWord/Exception/Exception.php index 7500dd3b23..778ca121e8 100644 --- a/src/PhpWord/Exception/Exception.php +++ b/src/PhpWord/Exception/Exception.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Exception/InvalidImageException.php b/src/PhpWord/Exception/InvalidImageException.php index 359744451c..b1fc14c754 100644 --- a/src/PhpWord/Exception/InvalidImageException.php +++ b/src/PhpWord/Exception/InvalidImageException.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Exception/InvalidObjectException.php b/src/PhpWord/Exception/InvalidObjectException.php index 955b222fd4..2e1d8935bf 100644 --- a/src/PhpWord/Exception/InvalidObjectException.php +++ b/src/PhpWord/Exception/InvalidObjectException.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Exception/InvalidStyleException.php b/src/PhpWord/Exception/InvalidStyleException.php index dd4e09a454..5b738073c6 100644 --- a/src/PhpWord/Exception/InvalidStyleException.php +++ b/src/PhpWord/Exception/InvalidStyleException.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Exception/UnsupportedImageTypeException.php b/src/PhpWord/Exception/UnsupportedImageTypeException.php index 8807fe0d3f..051911af3b 100644 --- a/src/PhpWord/Exception/UnsupportedImageTypeException.php +++ b/src/PhpWord/Exception/UnsupportedImageTypeException.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/IOFactory.php b/src/PhpWord/IOFactory.php index 9ceb7026a3..55c374a8b9 100644 --- a/src/PhpWord/IOFactory.php +++ b/src/PhpWord/IOFactory.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -61,9 +62,9 @@ public static function createReader($name = 'Word2007') * * @param string $type * @param string $name - * @param \PhpOffice\PhpWord\PhpWord $phpWord + * @param PhpWord $phpWord * - * @return \PhpOffice\PhpWord\Reader\ReaderInterface|\PhpOffice\PhpWord\Writer\WriterInterface + * @return ReaderInterface|WriterInterface */ private static function createObject($type, $name, $phpWord = null) { @@ -81,11 +82,11 @@ private static function createObject($type, $name, $phpWord = null) * @param string $filename The name of the file * @param string $readerName * - * @return \PhpOffice\PhpWord\PhpWord $phpWord + * @return PhpWord $phpWord */ public static function load($filename, $readerName = 'Word2007') { - /** @var \PhpOffice\PhpWord\Reader\ReaderInterface $reader */ + /** @var ReaderInterface $reader */ $reader = self::createReader($readerName); return $reader->load($filename); @@ -100,7 +101,7 @@ public static function load($filename, $readerName = 'Word2007') */ public static function extractVariables(string $filename, string $readerName = 'Word2007'): array { - /** @var \PhpOffice\PhpWord\Reader\ReaderInterface $reader */ + /** @var ReaderInterface $reader */ $reader = self::createReader($readerName); $document = $reader->load($filename); $extractedVariables = []; diff --git a/src/PhpWord/Media.php b/src/PhpWord/Media.php index 31487a91fe..0a340a0a3c 100644 --- a/src/PhpWord/Media.php +++ b/src/PhpWord/Media.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Metadata/Compatibility.php b/src/PhpWord/Metadata/Compatibility.php index b0bf14020d..b958d309b9 100644 --- a/src/PhpWord/Metadata/Compatibility.php +++ b/src/PhpWord/Metadata/Compatibility.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Metadata/DocInfo.php b/src/PhpWord/Metadata/DocInfo.php index f7229cf0a5..d3a4bda17b 100644 --- a/src/PhpWord/Metadata/DocInfo.php +++ b/src/PhpWord/Metadata/DocInfo.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Metadata/Protection.php b/src/PhpWord/Metadata/Protection.php index c9b37631d3..667b1438e8 100644 --- a/src/PhpWord/Metadata/Protection.php +++ b/src/PhpWord/Metadata/Protection.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Metadata/Settings.php b/src/PhpWord/Metadata/Settings.php index 2de9ef8959..0e30ec76d6 100644 --- a/src/PhpWord/Metadata/Settings.php +++ b/src/PhpWord/Metadata/Settings.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -93,14 +94,14 @@ class Settings /** * Spelling and Grammatical Checking State. * - * @var \PhpOffice\PhpWord\ComplexType\ProofState + * @var ProofState */ private $proofState; /** * Document Editing Restrictions. * - * @var \PhpOffice\PhpWord\Metadata\Protection + * @var Protection */ private $documentProtection; @@ -266,7 +267,7 @@ public function setEvenAndOddHeaders($evenAndOddHeaders): void /** * Get the Visibility of Annotation Types. * - * @return \PhpOffice\PhpWord\ComplexType\TrackChangesView + * @return TrackChangesView */ public function getRevisionView() { diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index cf6f16ae02..f96bdcf401 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -47,7 +48,7 @@ class PhpWord /** * Collection of sections. * - * @var \PhpOffice\PhpWord\Element\Section[] + * @var Section[] */ private $sections = []; @@ -151,7 +152,7 @@ public function __call($function, $args) /** * Get document properties object. * - * @return \PhpOffice\PhpWord\Metadata\DocInfo + * @return Metadata\DocInfo */ public function getDocInfo() { @@ -161,7 +162,7 @@ public function getDocInfo() /** * Get compatibility. * - * @return \PhpOffice\PhpWord\Metadata\Compatibility + * @return Metadata\Compatibility * * @since 0.12.0 */ @@ -173,7 +174,7 @@ public function getCompatibility() /** * Get compatibility. * - * @return \PhpOffice\PhpWord\Metadata\Settings + * @return Metadata\Settings * * @since 0.14.0 */ @@ -185,7 +186,7 @@ public function getSettings() /** * Get all sections. * - * @return \PhpOffice\PhpWord\Element\Section[] + * @return Section[] */ public function getSections() { @@ -197,7 +198,7 @@ public function getSections() * * @param int $index * - * @return null|\PhpOffice\PhpWord\Element\Section + * @return null|Section */ public function getSection($index) { @@ -213,7 +214,7 @@ public function getSection($index) * * @param null|array|string $style * - * @return \PhpOffice\PhpWord\Element\Section + * @return Section */ public function addSection($style = null) { @@ -281,7 +282,7 @@ public function setDefaultFontSize($fontSize): void * * @param array $styles Paragraph style definition * - * @return \PhpOffice\PhpWord\Style\Paragraph + * @return Style\Paragraph */ public function setDefaultParagraphStyle($styles) { @@ -333,7 +334,7 @@ public function save($filename, $format = 'Word2007', $download = false) * * @param array $settings * - * @return \PhpOffice\PhpWord\Element\Section + * @return Section * * @codeCoverageIgnore */ @@ -347,7 +348,7 @@ public function createSection($settings = null) * * @deprecated 0.12.0 * - * @return \PhpOffice\PhpWord\Metadata\DocInfo + * @return Metadata\DocInfo * * @codeCoverageIgnore */ @@ -361,7 +362,7 @@ public function getDocumentProperties() * * @deprecated 0.12.0 * - * @param \PhpOffice\PhpWord\Metadata\DocInfo $documentProperties + * @param Metadata\DocInfo $documentProperties * * @return self * diff --git a/src/PhpWord/Reader/AbstractReader.php b/src/PhpWord/Reader/AbstractReader.php index da5e6f6e19..3c70834d16 100644 --- a/src/PhpWord/Reader/AbstractReader.php +++ b/src/PhpWord/Reader/AbstractReader.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Reader/HTML.php b/src/PhpWord/Reader/HTML.php index 30257d98cf..17871c21a2 100644 --- a/src/PhpWord/Reader/HTML.php +++ b/src/PhpWord/Reader/HTML.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -33,7 +34,7 @@ class HTML extends AbstractReader implements ReaderInterface * * @param string $docFile * - * @return \PhpOffice\PhpWord\PhpWord + * @return PhpWord */ public function load($docFile) { diff --git a/src/PhpWord/Reader/MsDoc.php b/src/PhpWord/Reader/MsDoc.php index 72b9af6c59..7cbeb1a8ac 100644 --- a/src/PhpWord/Reader/MsDoc.php +++ b/src/PhpWord/Reader/MsDoc.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Reader/ODText.php b/src/PhpWord/Reader/ODText.php index d7f8344443..288bf9a0dd 100644 --- a/src/PhpWord/Reader/ODText.php +++ b/src/PhpWord/Reader/ODText.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -32,7 +33,7 @@ class ODText extends AbstractReader implements ReaderInterface * * @param string $docFile * - * @return \PhpOffice\PhpWord\PhpWord + * @return PhpWord */ public function load($docFile) { @@ -58,7 +59,7 @@ private function readPart(PhpWord $phpWord, array $relationships, string $partNa { $partClass = "PhpOffice\\PhpWord\\Reader\\ODText\\{$partName}"; if (class_exists($partClass)) { - /** @var \PhpOffice\PhpWord\Reader\ODText\AbstractPart $part Type hint */ + /** @var ODText\AbstractPart $part Type hint */ $part = new $partClass($docFile, $xmlFile); $part->setRels($relationships); $part->read($phpWord); diff --git a/src/PhpWord/Reader/ODText/AbstractPart.php b/src/PhpWord/Reader/ODText/AbstractPart.php index 4c89192edd..447c96f094 100644 --- a/src/PhpWord/Reader/ODText/AbstractPart.php +++ b/src/PhpWord/Reader/ODText/AbstractPart.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Reader/ODText/Content.php b/src/PhpWord/Reader/ODText/Content.php index 15c76c27b9..f555d00654 100644 --- a/src/PhpWord/Reader/ODText/Content.php +++ b/src/PhpWord/Reader/ODText/Content.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Reader/ODText/Meta.php b/src/PhpWord/Reader/ODText/Meta.php index 200ee1306f..1321b6ce35 100644 --- a/src/PhpWord/Reader/ODText/Meta.php +++ b/src/PhpWord/Reader/ODText/Meta.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Reader/RTF.php b/src/PhpWord/Reader/RTF.php index 2fdfb03839..dbf1ebd7ad 100644 --- a/src/PhpWord/Reader/RTF.php +++ b/src/PhpWord/Reader/RTF.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -33,7 +34,7 @@ class RTF extends AbstractReader implements ReaderInterface * * @param string $docFile * - * @return \PhpOffice\PhpWord\PhpWord + * @return PhpWord */ public function load($docFile) { diff --git a/src/PhpWord/Reader/RTF/Document.php b/src/PhpWord/Reader/RTF/Document.php index 21b76cf71f..358464a61d 100644 --- a/src/PhpWord/Reader/RTF/Document.php +++ b/src/PhpWord/Reader/RTF/Document.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -42,7 +43,7 @@ class Document /** * PhpWord object. * - * @var \PhpOffice\PhpWord\PhpWord + * @var PhpWord */ private $phpWord; diff --git a/src/PhpWord/Reader/ReaderInterface.php b/src/PhpWord/Reader/ReaderInterface.php index 83c6993310..1dced12aba 100644 --- a/src/PhpWord/Reader/ReaderInterface.php +++ b/src/PhpWord/Reader/ReaderInterface.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Reader/Word2007.php b/src/PhpWord/Reader/Word2007.php index bb20a8fed2..a67cd612ed 100644 --- a/src/PhpWord/Reader/Word2007.php +++ b/src/PhpWord/Reader/Word2007.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -39,7 +40,7 @@ class Word2007 extends AbstractReader implements ReaderInterface * * @param string $docFile * - * @return \PhpOffice\PhpWord\PhpWord + * @return PhpWord */ public function load($docFile) { diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 98a74772cd..12ef96d287 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -183,7 +184,7 @@ protected function getCommentReference(string $id): array /** * Read w:p. * - * @param \PhpOffice\PhpWord\Element\AbstractContainer $parent + * @param AbstractContainer $parent * @param string $docPart * * @todo Get font style for preserve text @@ -450,7 +451,7 @@ private function getHeadingDepth(?array $paragraphStyle = null) /** * Read w:r. * - * @param \PhpOffice\PhpWord\Element\AbstractContainer $parent + * @param AbstractContainer $parent * @param string $docPart * @param mixed $paragraphStyle * diff --git a/src/PhpWord/Reader/Word2007/DocPropsApp.php b/src/PhpWord/Reader/Word2007/DocPropsApp.php index 9d6f3cbbe9..c7ecb007b3 100644 --- a/src/PhpWord/Reader/Word2007/DocPropsApp.php +++ b/src/PhpWord/Reader/Word2007/DocPropsApp.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Reader/Word2007/DocPropsCore.php b/src/PhpWord/Reader/Word2007/DocPropsCore.php index d3eac27de6..2458bb84cf 100644 --- a/src/PhpWord/Reader/Word2007/DocPropsCore.php +++ b/src/PhpWord/Reader/Word2007/DocPropsCore.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Reader/Word2007/DocPropsCustom.php b/src/PhpWord/Reader/Word2007/DocPropsCustom.php index 69cd551c79..442017199b 100644 --- a/src/PhpWord/Reader/Word2007/DocPropsCustom.php +++ b/src/PhpWord/Reader/Word2007/DocPropsCustom.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Reader/Word2007/Document.php b/src/PhpWord/Reader/Word2007/Document.php index 87a24f4198..11e6089dba 100644 --- a/src/PhpWord/Reader/Word2007/Document.php +++ b/src/PhpWord/Reader/Word2007/Document.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -34,7 +35,7 @@ class Document extends AbstractPart /** * PhpWord object. * - * @var \PhpOffice\PhpWord\PhpWord + * @var PhpWord */ private $phpWord; diff --git a/src/PhpWord/Reader/Word2007/Endnotes.php b/src/PhpWord/Reader/Word2007/Endnotes.php index 0c6b18db37..6ab4203579 100644 --- a/src/PhpWord/Reader/Word2007/Endnotes.php +++ b/src/PhpWord/Reader/Word2007/Endnotes.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Reader/Word2007/Footnotes.php b/src/PhpWord/Reader/Word2007/Footnotes.php index d40af195e3..0b259e926a 100644 --- a/src/PhpWord/Reader/Word2007/Footnotes.php +++ b/src/PhpWord/Reader/Word2007/Footnotes.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Reader/Word2007/Numbering.php b/src/PhpWord/Reader/Word2007/Numbering.php index 4ae7a828bc..564c43b23b 100644 --- a/src/PhpWord/Reader/Word2007/Numbering.php +++ b/src/PhpWord/Reader/Word2007/Numbering.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Reader/Word2007/Settings.php b/src/PhpWord/Reader/Word2007/Settings.php index 7466008d49..f4f8be6fb2 100644 --- a/src/PhpWord/Reader/Word2007/Settings.php +++ b/src/PhpWord/Reader/Word2007/Settings.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Reader/Word2007/Styles.php b/src/PhpWord/Reader/Word2007/Styles.php index 760adf9493..b327ff3346 100644 --- a/src/PhpWord/Reader/Word2007/Styles.php +++ b/src/PhpWord/Reader/Word2007/Styles.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Settings.php b/src/PhpWord/Settings.php index 984486ccfe..a2c461e29a 100644 --- a/src/PhpWord/Settings.php +++ b/src/PhpWord/Settings.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -29,7 +30,7 @@ class Settings */ public const ZIPARCHIVE = 'ZipArchive'; public const PCLZIP = 'PclZip'; - public const OLD_LIB = \PhpOffice\PhpWord\Shared\ZipArchive::class; // @deprecated 0.11 + public const OLD_LIB = Shared\ZipArchive::class; // @deprecated 0.11 /** * PDF rendering libraries. diff --git a/src/PhpWord/Shared/AbstractEnum.php b/src/PhpWord/Shared/AbstractEnum.php index e79f4b244e..cfbcf1e8a6 100644 --- a/src/PhpWord/Shared/AbstractEnum.php +++ b/src/PhpWord/Shared/AbstractEnum.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Shared/Converter.php b/src/PhpWord/Shared/Converter.php index 365aa141b0..17d2e1a05d 100644 --- a/src/PhpWord/Shared/Converter.php +++ b/src/PhpWord/Shared/Converter.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Shared/Css.php b/src/PhpWord/Shared/Css.php index fea3e3d5d6..93f69000b4 100644 --- a/src/PhpWord/Shared/Css.php +++ b/src/PhpWord/Shared/Css.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -39,10 +40,6 @@ public function process(): void { $cssContent = str_replace(["\r", "\n"], '', $this->cssContent); preg_match_all('/(.+?)\s?\{\s?(.+?)\s?\}/', $cssContent, $cssExtracted); - // Check the number of extracted - if (count($cssExtracted) != 3) { - return; - } // Check if there are x selectors and x rules if (count($cssExtracted[1]) != count($cssExtracted[2])) { return; diff --git a/src/PhpWord/Shared/Drawing.php b/src/PhpWord/Shared/Drawing.php index df218108d9..8af7da2ffc 100644 --- a/src/PhpWord/Shared/Drawing.php +++ b/src/PhpWord/Shared/Drawing.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 334f5c269e..36a66f4110 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -57,7 +58,7 @@ class Html * Warning: Do not pass user-generated HTML here, as that would allow an attacker to read arbitrary * files or perform server-side request forgery by passing local file paths or URLs in <img>. * - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element Where the parts need to be added + * @param AbstractContainer $element Where the parts need to be added * @param string $html The code to parse * @param bool $fullHTML If it's a full HTML, no need to add 'body' tag * @param bool $preserveWhiteSpace If false, the whitespaces between nodes will be removed @@ -185,7 +186,7 @@ protected static function parseInlineStyle($node, $styles = []) * Parse a node and add a corresponding element to the parent element. * * @param DOMNode $node node to parse - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element object to add an element corresponding with the node + * @param AbstractContainer $element object to add an element corresponding with the node * @param array $styles Array with all styles * @param array $data Array to transport data to a next level in the DOM tree, for example level of listitems */ @@ -276,7 +277,7 @@ protected static function parseNode($node, $element, $styles = [], $data = []): * Parse child nodes. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer|Row|Table $element + * @param AbstractContainer|Row|Table $element * @param array $styles * @param array $data */ @@ -298,7 +299,7 @@ protected static function parseChildNodes($node, $element, $styles, $data): void * Parse paragraph node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * @param array &$styles * * @return \PhpOffice\PhpWord\Element\PageBreak|\PhpOffice\PhpWord\Element\TextRun @@ -317,7 +318,7 @@ protected static function parseParagraph($node, $element, &$styles) * Parse input node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * @param array &$styles */ protected static function parseInput($node, $element, &$styles): void @@ -341,7 +342,7 @@ protected static function parseInput($node, $element, &$styles): void /** * Parse heading node. * - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * @param array &$styles * @param string $argument1 Name of heading style * @@ -362,7 +363,7 @@ protected static function parseHeading($element, &$styles, $argument1) * Parse text node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * @param array &$styles */ protected static function parseText($node, $element, &$styles): void @@ -406,7 +407,7 @@ protected static function parseSpan($node, &$styles): void * Parse table node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * @param array &$styles * * @return Table $element @@ -437,7 +438,7 @@ protected static function parseTable($node, $element, &$styles) * Parse a table row. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\Table $element + * @param Table $element * @param array &$styles * * @return Row $element @@ -460,7 +461,7 @@ protected static function parseRow($node, $element, &$styles) * Parse table cell. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\Table $element + * @param Table $element * @param array &$styles * * @return \PhpOffice\PhpWord\Element\Cell|\PhpOffice\PhpWord\Element\TextRun $element @@ -554,7 +555,7 @@ protected static function filterOutNonInheritedStyles(array $styles) * Parse list node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * @param array &$styles * @param array &$data */ @@ -644,7 +645,7 @@ protected static function getListStyle($isOrderedList) * Parse list item node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * @param array &$styles * @param array $data * @@ -886,7 +887,7 @@ protected static function parseStyleDeclarations(array $selectors, array $styles * Parse image node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * * @return \PhpOffice\PhpWord\Element\Image */ @@ -970,14 +971,15 @@ protected static function parseImage($node, $element) $match = []; preg_match('/data:image\/(\w+);base64,(.+)/', $src, $match); + if (!empty($match)) { + $src = $imgFile = $tmpDir . uniqid() . '.' . $match[1]; - $src = $imgFile = $tmpDir . uniqid() . '.' . $match[1]; - - $ifp = fopen($imgFile, 'wb'); + $ifp = fopen($imgFile, 'wb'); - if ($ifp !== false) { - fwrite($ifp, base64_decode($match[2])); - fclose($ifp); + if ($ifp !== false) { + fwrite($ifp, base64_decode($match[2])); + fclose($ifp); + } } } $src = urldecode($src); @@ -1129,7 +1131,7 @@ protected static function mapListType($cssListType) /** * Parse line break. * - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element */ protected static function parseLineBreak($element): void { @@ -1140,7 +1142,7 @@ protected static function parseLineBreak($element): void * Parse link node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * @param array $styles */ protected static function parseLink($node, $element, &$styles) @@ -1172,7 +1174,7 @@ protected static function parseLink($node, $element, &$styles) * Note: Word rule is not the same as HTML's <hr> since it does not support width and thus neither alignment. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element */ protected static function parseHorizRule($node, $element): void { diff --git a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php b/src/PhpWord/Shared/Microsoft/PasswordEncoder.php index d6cf69fc6d..45f9a53632 100644 --- a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php +++ b/src/PhpWord/Shared/Microsoft/PasswordEncoder.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Shared/Text.php b/src/PhpWord/Shared/Text.php index b9a8831cdd..90550c0650 100644 --- a/src/PhpWord/Shared/Text.php +++ b/src/PhpWord/Shared/Text.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Shared/Validate.php b/src/PhpWord/Shared/Validate.php index 0967b5693c..faa7df0db4 100644 --- a/src/PhpWord/Shared/Validate.php +++ b/src/PhpWord/Shared/Validate.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Shared/XMLReader.php b/src/PhpWord/Shared/XMLReader.php index e836607d29..ec41f2d674 100644 --- a/src/PhpWord/Shared/XMLReader.php +++ b/src/PhpWord/Shared/XMLReader.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Shared/XMLWriter.php b/src/PhpWord/Shared/XMLWriter.php index 9f51c0e514..8dc28e1184 100644 --- a/src/PhpWord/Shared/XMLWriter.php +++ b/src/PhpWord/Shared/XMLWriter.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Shared/ZipArchive.php b/src/PhpWord/Shared/ZipArchive.php index f120756d8b..3ee3869191 100644 --- a/src/PhpWord/Shared/ZipArchive.php +++ b/src/PhpWord/Shared/ZipArchive.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -293,8 +294,10 @@ public function pclzipAddFromString($localname, $contents) // Write $contents to a temp file $handle = fopen($this->tempDir . DIRECTORY_SEPARATOR . $filenameParts['basename'], 'wb'); - fwrite($handle, $contents); - fclose($handle); + if ($handle) { + fwrite($handle, $contents); + fclose($handle); + } // Add temp file to zip $filename = $this->tempDir . DIRECTORY_SEPARATOR . $filenameParts['basename']; diff --git a/src/PhpWord/SimpleType/Border.php b/src/PhpWord/SimpleType/Border.php index 6cb42f0467..acd1c1a1b1 100644 --- a/src/PhpWord/SimpleType/Border.php +++ b/src/PhpWord/SimpleType/Border.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/SimpleType/DocProtect.php b/src/PhpWord/SimpleType/DocProtect.php index 2d13485493..c966e1a59d 100644 --- a/src/PhpWord/SimpleType/DocProtect.php +++ b/src/PhpWord/SimpleType/DocProtect.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/SimpleType/Jc.php b/src/PhpWord/SimpleType/Jc.php index ab665822c4..8d8ecca76a 100644 --- a/src/PhpWord/SimpleType/Jc.php +++ b/src/PhpWord/SimpleType/Jc.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -26,7 +27,7 @@ * Since ISO/IEC-29500:2008 the type must not be used for table alignment. * * @since 0.13.0 - * @see \PhpOffice\PhpWord\SimpleType\JcTable For table alignment modes available since ISO/IEC-29500:2008. + * @see JcTable For table alignment modes available since ISO/IEC-29500:2008. * @see http://www.datypic.com/sc/ooxml/t-w_ST_Jc.html */ final class Jc extends AbstractEnum diff --git a/src/PhpWord/SimpleType/JcTable.php b/src/PhpWord/SimpleType/JcTable.php index 86a1b03462..47f026d797 100644 --- a/src/PhpWord/SimpleType/JcTable.php +++ b/src/PhpWord/SimpleType/JcTable.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/SimpleType/LineSpacingRule.php b/src/PhpWord/SimpleType/LineSpacingRule.php index 833b626953..648b8f930d 100644 --- a/src/PhpWord/SimpleType/LineSpacingRule.php +++ b/src/PhpWord/SimpleType/LineSpacingRule.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/SimpleType/NumberFormat.php b/src/PhpWord/SimpleType/NumberFormat.php index 36a678e8ce..35c32ee3c8 100644 --- a/src/PhpWord/SimpleType/NumberFormat.php +++ b/src/PhpWord/SimpleType/NumberFormat.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/SimpleType/TblWidth.php b/src/PhpWord/SimpleType/TblWidth.php index 28ba0db2d1..b77ab0313a 100644 --- a/src/PhpWord/SimpleType/TblWidth.php +++ b/src/PhpWord/SimpleType/TblWidth.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/SimpleType/TextAlignment.php b/src/PhpWord/SimpleType/TextAlignment.php index 1f2af0fd89..77bfc48a34 100644 --- a/src/PhpWord/SimpleType/TextAlignment.php +++ b/src/PhpWord/SimpleType/TextAlignment.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/SimpleType/VerticalJc.php b/src/PhpWord/SimpleType/VerticalJc.php index 147cd20910..f7ceeb67e6 100644 --- a/src/PhpWord/SimpleType/VerticalJc.php +++ b/src/PhpWord/SimpleType/VerticalJc.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/SimpleType/Zoom.php b/src/PhpWord/SimpleType/Zoom.php index fc53ec8ff3..ed41d62338 100644 --- a/src/PhpWord/SimpleType/Zoom.php +++ b/src/PhpWord/SimpleType/Zoom.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style.php b/src/PhpWord/Style.php index ea039622df..7d28f3b7e6 100644 --- a/src/PhpWord/Style.php +++ b/src/PhpWord/Style.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -41,7 +42,7 @@ class Style * @param string $styleName * @param AbstractStyle|array $styles * - * @return \PhpOffice\PhpWord\Style\Paragraph + * @return Paragraph */ public static function addParagraphStyle($styleName, $styles) { @@ -55,7 +56,7 @@ public static function addParagraphStyle($styleName, $styles) * @param AbstractStyle|array $fontStyle * @param AbstractStyle|array $paragraphStyle * - * @return \PhpOffice\PhpWord\Style\Font + * @return Font */ public static function addFontStyle($styleName, $fontStyle, $paragraphStyle = null) { @@ -68,7 +69,7 @@ public static function addFontStyle($styleName, $fontStyle, $paragraphStyle = nu * @param string $styleName * @param AbstractStyle|array $styles * - * @return \PhpOffice\PhpWord\Style\Font + * @return Font */ public static function addLinkStyle($styleName, $styles) { @@ -81,7 +82,7 @@ public static function addLinkStyle($styleName, $styles) * @param string $styleName * @param AbstractStyle|array $styleValues * - * @return \PhpOffice\PhpWord\Style\Numbering + * @return Numbering * * @since 0.10.0 */ @@ -97,7 +98,7 @@ public static function addNumberingStyle($styleName, $styleValues) * @param AbstractStyle|array $fontStyle * @param AbstractStyle|array $paragraphStyle * - * @return \PhpOffice\PhpWord\Style\Font + * @return Font */ public static function addTitleStyle($depth, $fontStyle, $paragraphStyle = null) { @@ -117,7 +118,7 @@ public static function addTitleStyle($depth, $fontStyle, $paragraphStyle = null) * @param array $styleTable * @param null|array $styleFirstRow * - * @return \PhpOffice\PhpWord\Style\Table + * @return Table */ public static function addTableStyle($styleName, $styleTable, $styleFirstRow = null) { @@ -151,7 +152,7 @@ public static function resetStyles(): void * * @param AbstractStyle|array $styles Paragraph style definition * - * @return \PhpOffice\PhpWord\Style\Paragraph + * @return Paragraph */ public static function setDefaultParagraphStyle($styles) { diff --git a/src/PhpWord/Style/AbstractStyle.php b/src/PhpWord/Style/AbstractStyle.php index 4e5def618d..3d883978dd 100644 --- a/src/PhpWord/Style/AbstractStyle.php +++ b/src/PhpWord/Style/AbstractStyle.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -134,7 +135,7 @@ public function setAuto($value = true) /** * Return style value of child style object, e.g. `left` from `Indentation` child style of `Paragraph`. * - * @param \PhpOffice\PhpWord\Style\AbstractStyle $substyleObject + * @param AbstractStyle $substyleObject * @param string $substyleProperty * * @return mixed @@ -323,9 +324,9 @@ protected function setEnumVal($value = null, $enum = [], $default = null) */ protected function setObjectVal($value, $styleName, &$style) { - $styleClass = substr(static::class, 0, strrpos(static::class, '\\')) . '\\' . $styleName; + $styleClass = substr(static::class, 0, (int) strrpos(static::class, '\\')) . '\\' . $styleName; if (is_array($value)) { - /** @var \PhpOffice\PhpWord\Style\AbstractStyle $style Type hint */ + /** @var AbstractStyle $style Type hint */ if (!$style instanceof $styleClass) { $style = new $styleClass(); } diff --git a/src/PhpWord/Style/Border.php b/src/PhpWord/Style/Border.php index e2a56c5d21..722e09931a 100644 --- a/src/PhpWord/Style/Border.php +++ b/src/PhpWord/Style/Border.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index 0888d52083..f102bfa862 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -100,7 +101,7 @@ class Cell extends Border /** * Shading. * - * @var \PhpOffice\PhpWord\Style\Shading + * @var Shading */ private $shading; @@ -272,7 +273,7 @@ public function setVMerge($value = null) /** * Get shading. * - * @return \PhpOffice\PhpWord\Style\Shading + * @return Shading */ public function getShading() { diff --git a/src/PhpWord/Style/Chart.php b/src/PhpWord/Style/Chart.php index 9dbc8db0a6..6cffc4d5b0 100644 --- a/src/PhpWord/Style/Chart.php +++ b/src/PhpWord/Style/Chart.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Extrusion.php b/src/PhpWord/Style/Extrusion.php index dd00231223..c31c51eb4f 100644 --- a/src/PhpWord/Style/Extrusion.php +++ b/src/PhpWord/Style/Extrusion.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Fill.php b/src/PhpWord/Style/Fill.php index af0149d0fe..f9dfe5a1cb 100644 --- a/src/PhpWord/Style/Fill.php +++ b/src/PhpWord/Style/Fill.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Font.php b/src/PhpWord/Style/Font.php index a4580bc87b..fe7f621454 100644 --- a/src/PhpWord/Style/Font.php +++ b/src/PhpWord/Style/Font.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -219,14 +220,14 @@ class Font extends AbstractStyle /** * Paragraph style. * - * @var \PhpOffice\PhpWord\Style\Paragraph + * @var Paragraph */ private $paragraph; /** * Shading. * - * @var \PhpOffice\PhpWord\Style\Shading + * @var Shading */ private $shading; @@ -248,7 +249,7 @@ class Font extends AbstractStyle /** * Languages. * - * @var null|\PhpOffice\PhpWord\Style\Language + * @var null|Language */ private $lang; @@ -288,7 +289,7 @@ class Font extends AbstractStyle * Create new font style. * * @param string $type Type of font - * @param array|\PhpOffice\PhpWord\Style\AbstractStyle|string $paragraph Paragraph styles definition + * @param AbstractStyle|array|string $paragraph Paragraph styles definition */ public function __construct($type = 'text', $paragraph = null) { @@ -682,7 +683,7 @@ public function getBgColor() * * @param string $value * - * @return \PhpOffice\PhpWord\Style\Table + * @return Table */ public function setBgColor($value = null) { @@ -812,7 +813,7 @@ public function setLineHeight($value) /** * Get paragraph style. * - * @return \PhpOffice\PhpWord\Style\Paragraph + * @return Paragraph */ public function getParagraph() { @@ -860,7 +861,7 @@ public function setRTL($value = true) /** * Get shading. * - * @return \PhpOffice\PhpWord\Style\Shading + * @return Shading */ public function getShading() { @@ -884,7 +885,7 @@ public function setShading($value = null) /** * Get language. * - * @return null|\PhpOffice\PhpWord\Style\Language + * @return null|Language */ public function getLang() { diff --git a/src/PhpWord/Style/Frame.php b/src/PhpWord/Style/Frame.php index 45fc583ed1..016722f36c 100644 --- a/src/PhpWord/Style/Frame.php +++ b/src/PhpWord/Style/Frame.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Image.php b/src/PhpWord/Style/Image.php index dbb8572f99..f53a778793 100644 --- a/src/PhpWord/Style/Image.php +++ b/src/PhpWord/Style/Image.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Indentation.php b/src/PhpWord/Style/Indentation.php index 42c6e11845..22b8f44c0b 100644 --- a/src/PhpWord/Style/Indentation.php +++ b/src/PhpWord/Style/Indentation.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index 18e7f76e77..54e4376562 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Line.php b/src/PhpWord/Style/Line.php index 2aeefa5ae5..cc5a12ffe9 100644 --- a/src/PhpWord/Style/Line.php +++ b/src/PhpWord/Style/Line.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/LineNumbering.php b/src/PhpWord/Style/LineNumbering.php index 61a98dc8e1..95267a295e 100644 --- a/src/PhpWord/Style/LineNumbering.php +++ b/src/PhpWord/Style/LineNumbering.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/ListItem.php b/src/PhpWord/Style/ListItem.php index 28d3fb1b66..e34aeb7c7c 100644 --- a/src/PhpWord/Style/ListItem.php +++ b/src/PhpWord/Style/ListItem.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Numbering.php b/src/PhpWord/Style/Numbering.php index c3af1fc352..1ecbe68c83 100644 --- a/src/PhpWord/Style/Numbering.php +++ b/src/PhpWord/Style/Numbering.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/NumberingLevel.php b/src/PhpWord/Style/NumberingLevel.php index 39c0d839d6..31ec3738c8 100644 --- a/src/PhpWord/Style/NumberingLevel.php +++ b/src/PhpWord/Style/NumberingLevel.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Outline.php b/src/PhpWord/Style/Outline.php index 6d83f0378d..7706580825 100644 --- a/src/PhpWord/Style/Outline.php +++ b/src/PhpWord/Style/Outline.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Paper.php b/src/PhpWord/Style/Paper.php index 3a340bda9d..c59ea42d7b 100644 --- a/src/PhpWord/Style/Paper.php +++ b/src/PhpWord/Style/Paper.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Paragraph.php b/src/PhpWord/Style/Paragraph.php index c77617403d..43acedaee2 100644 --- a/src/PhpWord/Style/Paragraph.php +++ b/src/PhpWord/Style/Paragraph.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -86,14 +87,14 @@ class Paragraph extends Border /** * Indentation. * - * @var null|\PhpOffice\PhpWord\Style\Indentation + * @var null|Indentation */ private $indentation; /** * Spacing. * - * @var \PhpOffice\PhpWord\Style\Spacing + * @var Spacing */ private $spacing; @@ -149,14 +150,14 @@ class Paragraph extends Border /** * Set of Custom Tab Stops. * - * @var \PhpOffice\PhpWord\Style\Tab[] + * @var Tab[] */ private $tabs = []; /** * Shading. * - * @var \PhpOffice\PhpWord\Style\Shading + * @var Shading */ private $shading; @@ -324,7 +325,7 @@ public function setNext($value = null) /** * Get indentation. * - * @return null|\PhpOffice\PhpWord\Style\Indentation + * @return null|Indentation */ public function getIndentation() { @@ -392,7 +393,7 @@ public function setHanging($value = null) /** * Get spacing. * - * @return \PhpOffice\PhpWord\Style\Spacing + * @return Spacing * * @todo Rename to getSpacing in 1.0 */ @@ -498,7 +499,7 @@ public function getSpacingLineRule() * * @param string $value Possible values are defined in LineSpacingRule * - * @return \PhpOffice\PhpWord\Style\Paragraph + * @return Paragraph */ public function setSpacingLineRule($value) { @@ -686,7 +687,7 @@ public function setNumLevel($value = 0) /** * Get tabs. * - * @return \PhpOffice\PhpWord\Style\Tab[] + * @return Tab[] */ public function getTabs() { @@ -712,7 +713,7 @@ public function setTabs($value = null) /** * Get shading. * - * @return \PhpOffice\PhpWord\Style\Shading + * @return Shading */ public function getShading() { diff --git a/src/PhpWord/Style/Row.php b/src/PhpWord/Style/Row.php index 765c54f80e..31ae3dedc1 100644 --- a/src/PhpWord/Style/Row.php +++ b/src/PhpWord/Style/Row.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Section.php b/src/PhpWord/Style/Section.php index 3b08aa5f38..1f8e1f5c41 100644 --- a/src/PhpWord/Style/Section.php +++ b/src/PhpWord/Style/Section.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -58,7 +59,7 @@ class Section extends Border /** * Paper size. * - * @var \PhpOffice\PhpWord\Style\Paper + * @var Paper */ private $paper; @@ -137,7 +138,7 @@ class Section extends Border /** * Line numbering. * - * @var \PhpOffice\PhpWord\Style\LineNumbering + * @var LineNumbering * * @see http://www.schemacentral.com/sc/ooxml/e-w_lnNumType-1.html */ @@ -278,7 +279,7 @@ public function getPageSizeW() /** * @param null|float|int $value * - * @return \PhpOffice\PhpWord\Style\Section + * @return Section * * @since 0.12.0 */ @@ -304,7 +305,7 @@ public function getPageSizeH() /** * @param null|float|int $value * - * @return \PhpOffice\PhpWord\Style\Section + * @return Section * * @since 0.12.0 */ @@ -486,7 +487,7 @@ public function setBreakType($value = null) /** * Get line numbering. * - * @return \PhpOffice\PhpWord\Style\LineNumbering + * @return LineNumbering */ public function getLineNumbering() { diff --git a/src/PhpWord/Style/Shading.php b/src/PhpWord/Style/Shading.php index 81d69e313d..739e56e9de 100644 --- a/src/PhpWord/Style/Shading.php +++ b/src/PhpWord/Style/Shading.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Shadow.php b/src/PhpWord/Style/Shadow.php index 3f6252d439..2cdf058117 100644 --- a/src/PhpWord/Style/Shadow.php +++ b/src/PhpWord/Style/Shadow.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Shape.php b/src/PhpWord/Style/Shape.php index 7dd62a1f71..9f47ff7feb 100644 --- a/src/PhpWord/Style/Shape.php +++ b/src/PhpWord/Style/Shape.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -51,35 +52,35 @@ class Shape extends AbstractStyle /** * Frame. * - * @var \PhpOffice\PhpWord\Style\Frame + * @var Frame */ private $frame; /** * Fill. * - * @var \PhpOffice\PhpWord\Style\Fill + * @var Fill */ private $fill; /** * Outline. * - * @var \PhpOffice\PhpWord\Style\Outline + * @var Outline */ private $outline; /** * Shadow. * - * @var \PhpOffice\PhpWord\Style\Shadow + * @var Shadow */ private $shadow; /** * 3D extrusion. * - * @var \PhpOffice\PhpWord\Style\Extrusion + * @var Extrusion */ private $extrusion; @@ -144,7 +145,7 @@ public function setRoundness($value = null) /** * Get frame. * - * @return \PhpOffice\PhpWord\Style\Frame + * @return Frame */ public function getFrame() { @@ -168,7 +169,7 @@ public function setFrame($value = null) /** * Get fill. * - * @return \PhpOffice\PhpWord\Style\Fill + * @return Fill */ public function getFill() { @@ -192,7 +193,7 @@ public function setFill($value = null) /** * Get outline. * - * @return \PhpOffice\PhpWord\Style\Outline + * @return Outline */ public function getOutline() { @@ -216,7 +217,7 @@ public function setOutline($value = null) /** * Get shadow. * - * @return \PhpOffice\PhpWord\Style\Shadow + * @return Shadow */ public function getShadow() { @@ -240,7 +241,7 @@ public function setShadow($value = null) /** * Get 3D extrusion. * - * @return \PhpOffice\PhpWord\Style\Extrusion + * @return Extrusion */ public function getExtrusion() { diff --git a/src/PhpWord/Style/Spacing.php b/src/PhpWord/Style/Spacing.php index 196ad8daa1..2ffa40620c 100644 --- a/src/PhpWord/Style/Spacing.php +++ b/src/PhpWord/Style/Spacing.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/TOC.php b/src/PhpWord/Style/TOC.php index bd0d906907..1efcb6e474 100644 --- a/src/PhpWord/Style/TOC.php +++ b/src/PhpWord/Style/TOC.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Tab.php b/src/PhpWord/Style/Tab.php index 02158fd498..044ee090ee 100644 --- a/src/PhpWord/Style/Tab.php +++ b/src/PhpWord/Style/Tab.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/Table.php b/src/PhpWord/Style/Table.php index 3adb1a38f5..21e8a74823 100644 --- a/src/PhpWord/Style/Table.php +++ b/src/PhpWord/Style/Table.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -50,7 +51,7 @@ class Table extends Border /** * Style for first row. * - * @var \PhpOffice\PhpWord\Style\Table + * @var Table */ private $firstRowStyle; @@ -113,7 +114,7 @@ class Table extends Border /** * Shading. * - * @var \PhpOffice\PhpWord\Style\Shading + * @var Shading */ private $shading; @@ -145,7 +146,7 @@ class Table extends Border /** * Position. * - * @var ?\PhpOffice\PhpWord\Style\TablePosition + * @var ?TablePosition */ private $position; @@ -208,7 +209,7 @@ public function getCellSpacing() /** * Set first row. * - * @return \PhpOffice\PhpWord\Style\Table + * @return Table */ public function getFirstRow() { @@ -538,7 +539,7 @@ public function hasMargin() /** * Get shading. * - * @return \PhpOffice\PhpWord\Style\Shading + * @return Shading */ public function getShading() { @@ -706,7 +707,7 @@ private function setTableOnlyProperty($property, $value, $isNumeric = true) /** * Get position. * - * @return ?\PhpOffice\PhpWord\Style\TablePosition + * @return ?TablePosition */ public function getPosition() { diff --git a/src/PhpWord/Style/TablePosition.php b/src/PhpWord/Style/TablePosition.php index a61926b83c..deec49dfe3 100644 --- a/src/PhpWord/Style/TablePosition.php +++ b/src/PhpWord/Style/TablePosition.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Style/TextBox.php b/src/PhpWord/Style/TextBox.php index 341d93068f..82fe7a95c4 100644 --- a/src/PhpWord/Style/TextBox.php +++ b/src/PhpWord/Style/TextBox.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index f6fe1d8887..643bae4cb6 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -154,7 +154,7 @@ public function __destruct() * To replace an image: $templateProcessor->zip()->AddFromString("word/media/image1.jpg", file_get_contents($file));<br> * To read a file: $templateProcessor->zip()->getFromName("word/media/image1.jpg"); * - * @return \PhpOffice\PhpWord\Shared\ZipArchive + * @return ZipArchive */ public function zip() { @@ -281,7 +281,7 @@ public function setComplexValue($search, Element\AbstractElement $complexType): $objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $elementName; $xmlWriter = new XMLWriter(); - /** @var \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement $elementWriter */ + /** @var Writer\Word2007\Element\AbstractElement $elementWriter */ $elementWriter = new $objectClass($xmlWriter, $complexType, true); $elementWriter->write(); @@ -308,7 +308,7 @@ public function setComplexBlock($search, Element\AbstractElement $complexType): $objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $elementName; $xmlWriter = new XMLWriter(); - /** @var \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement $elementWriter */ + /** @var Writer\Word2007\Element\AbstractElement $elementWriter */ $elementWriter = new $objectClass($xmlWriter, $complexType, false); $elementWriter->write(); @@ -406,7 +406,7 @@ public function setChart($search, Element\AbstractElement $chart): void $filename = "charts/chart{$rId}.xml"; // Get the part writer - $writerPart = new \PhpOffice\PhpWord\Writer\Word2007\Part\Chart(); + $writerPart = new Writer\Word2007\Part\Chart(); $writerPart->setElement($chart); // ContentTypes.xml @@ -499,20 +499,22 @@ private function fixImageWidthHeightRatio(&$width, &$height, $actualWidth, $actu $widthFloat = $heightFloat * $imageRatio; $matches = []; preg_match('/\\d([a-z%]+)$/', $height, $matches); - $width = $widthFloat . $matches[1]; + $width = $widthFloat . (!empty($matches) ? $matches[1] : 'px'); } elseif ($height === '') { // defined height is empty $widthFloat = (float) $width; $heightFloat = $widthFloat / $imageRatio; $matches = []; preg_match('/\\d([a-z%]+)$/', $width, $matches); - $height = $heightFloat . $matches[1]; + $height = $heightFloat . (!empty($matches) ? $matches[1] : 'px'); } else { // we have defined size, but we need also check it aspect ratio $widthMatches = []; preg_match('/\\d([a-z%]+)$/', $width, $widthMatches); $heightMatches = []; preg_match('/\\d([a-z%]+)$/', $height, $heightMatches); // try to fix only if dimensions are same - if ($widthMatches[1] == $heightMatches[1]) { + if (!empty($widthMatches) + && !empty($heightMatches) + && $widthMatches[1] == $heightMatches[1]) { $dimention = $widthMatches[1]; $widthFloat = (float) $width; $heightFloat = (float) $height; @@ -1287,7 +1289,7 @@ protected function getSlice($startPosition, $endPosition = 0) * @param int $count * @param string $xmlBlock * - * @return string + * @return array<string> */ protected function indexClonedVariables($count, $xmlBlock) { @@ -1339,7 +1341,7 @@ protected function replaceClonedVariables($variableReplacements, $xmlBlock) * @param string $block New block content * @param string $blockType XML tag type of block * - * @return \PhpOffice\PhpWord\TemplateProcessor Fluent interface + * @return TemplateProcessor Fluent interface */ public function replaceXmlBlock($macro, $block, $blockType = 'w:p') { diff --git a/src/PhpWord/Writer/AbstractWriter.php b/src/PhpWord/Writer/AbstractWriter.php index 8ebf98c7b5..13859d8227 100644 --- a/src/PhpWord/Writer/AbstractWriter.php +++ b/src/PhpWord/Writer/AbstractWriter.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -33,7 +34,7 @@ abstract class AbstractWriter implements WriterInterface /** * PHPWord object. * - * @var \PhpOffice\PhpWord\PhpWord + * @var PhpWord */ protected $phpWord; @@ -96,7 +97,7 @@ abstract class AbstractWriter implements WriterInterface /** * Get PhpWord object. * - * @return \PhpOffice\PhpWord\PhpWord + * @return PhpWord */ public function getPhpWord() { @@ -110,8 +111,6 @@ public function getPhpWord() /** * Set PhpWord object. * - * @param \PhpOffice\PhpWord\PhpWord - * * @return self */ public function setPhpWord(?PhpWord $phpWord = null) @@ -267,7 +266,7 @@ protected function clearTempDir(): void * * @param string $filename * - * @return \PhpOffice\PhpWord\Shared\ZipArchive + * @return ZipArchive */ protected function getZipArchive($filename) { @@ -360,7 +359,7 @@ protected function addFilesToPackage(ZipArchive $zip, $elements): void * * Get the actual source from an archive image. * - * @param \PhpOffice\PhpWord\Shared\ZipArchive $zipPackage + * @param ZipArchive $zipPackage * @param string $source * @param string $target */ diff --git a/src/PhpWord/Writer/HTML.php b/src/PhpWord/Writer/HTML.php index 647890591d..41229b45d5 100644 --- a/src/PhpWord/Writer/HTML.php +++ b/src/PhpWord/Writer/HTML.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -77,7 +78,7 @@ public function __construct(?PhpWord $phpWord = null) foreach ($this->parts as $partName) { $partClass = 'PhpOffice\\PhpWord\\Writer\\HTML\\Part\\' . $partName; if (class_exists($partClass)) { - /** @var \PhpOffice\PhpWord\Writer\HTML\Part\AbstractPart $part Type hint */ + /** @var HTML\Part\AbstractPart $part Type hint */ $part = new $partClass(); $part->setParentWriter($this); $this->writerParts[strtolower($partName)] = $part; diff --git a/src/PhpWord/Writer/HTML/Element/AbstractElement.php b/src/PhpWord/Writer/HTML/Element/AbstractElement.php index 7c7bde3189..0e6a112eed 100644 --- a/src/PhpWord/Writer/HTML/Element/AbstractElement.php +++ b/src/PhpWord/Writer/HTML/Element/AbstractElement.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -37,7 +38,7 @@ abstract class AbstractElement /** * Element. * - * @var \PhpOffice\PhpWord\Element\AbstractElement + * @var Element */ protected $element; diff --git a/src/PhpWord/Writer/HTML/Element/Bookmark.php b/src/PhpWord/Writer/HTML/Element/Bookmark.php index 521a73db09..55a8c22e27 100644 --- a/src/PhpWord/Writer/HTML/Element/Bookmark.php +++ b/src/PhpWord/Writer/HTML/Element/Bookmark.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Element/Container.php b/src/PhpWord/Writer/HTML/Element/Container.php index 7909e73f21..6e2569f3c6 100644 --- a/src/PhpWord/Writer/HTML/Element/Container.php +++ b/src/PhpWord/Writer/HTML/Element/Container.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -53,7 +54,7 @@ public function write() $elementClass = get_class($element); $writerClass = str_replace('PhpOffice\\PhpWord\\Element', $this->namespace, $elementClass); if (class_exists($writerClass)) { - /** @var \PhpOffice\PhpWord\Writer\HTML\Element\AbstractElement $writer Type hint */ + /** @var AbstractElement $writer Type hint */ $writer = new $writerClass($this->parentWriter, $element, $withoutP); $content .= $writer->write(); } diff --git a/src/PhpWord/Writer/HTML/Element/Endnote.php b/src/PhpWord/Writer/HTML/Element/Endnote.php index 1c35e8faa8..7e7f31d4fc 100644 --- a/src/PhpWord/Writer/HTML/Element/Endnote.php +++ b/src/PhpWord/Writer/HTML/Element/Endnote.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Element/Footnote.php b/src/PhpWord/Writer/HTML/Element/Footnote.php index 0cb2ca5fcd..153516f421 100644 --- a/src/PhpWord/Writer/HTML/Element/Footnote.php +++ b/src/PhpWord/Writer/HTML/Element/Footnote.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Element/Image.php b/src/PhpWord/Writer/HTML/Element/Image.php index 40e864e6a4..1b183a217f 100644 --- a/src/PhpWord/Writer/HTML/Element/Image.php +++ b/src/PhpWord/Writer/HTML/Element/Image.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Element/Link.php b/src/PhpWord/Writer/HTML/Element/Link.php index ac48c865bd..a9f609f6e2 100644 --- a/src/PhpWord/Writer/HTML/Element/Link.php +++ b/src/PhpWord/Writer/HTML/Element/Link.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Element/ListItem.php b/src/PhpWord/Writer/HTML/Element/ListItem.php index ddc3ecf0fd..232a894a59 100644 --- a/src/PhpWord/Writer/HTML/Element/ListItem.php +++ b/src/PhpWord/Writer/HTML/Element/ListItem.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Element/ListItemRun.php b/src/PhpWord/Writer/HTML/Element/ListItemRun.php index 5bbe23f0f3..a708868c3d 100644 --- a/src/PhpWord/Writer/HTML/Element/ListItemRun.php +++ b/src/PhpWord/Writer/HTML/Element/ListItemRun.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Element/PageBreak.php b/src/PhpWord/Writer/HTML/Element/PageBreak.php index e5c48cc789..60335591c5 100644 --- a/src/PhpWord/Writer/HTML/Element/PageBreak.php +++ b/src/PhpWord/Writer/HTML/Element/PageBreak.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Element/Table.php b/src/PhpWord/Writer/HTML/Element/Table.php index 7f8d0bcc3c..b66e2f8c92 100644 --- a/src/PhpWord/Writer/HTML/Element/Table.php +++ b/src/PhpWord/Writer/HTML/Element/Table.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Element/Text.php b/src/PhpWord/Writer/HTML/Element/Text.php index 5af9f2ab63..312d3a19c2 100644 --- a/src/PhpWord/Writer/HTML/Element/Text.php +++ b/src/PhpWord/Writer/HTML/Element/Text.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Element/TextBreak.php b/src/PhpWord/Writer/HTML/Element/TextBreak.php index af73cb4a06..576f6a8364 100644 --- a/src/PhpWord/Writer/HTML/Element/TextBreak.php +++ b/src/PhpWord/Writer/HTML/Element/TextBreak.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Element/TextRun.php b/src/PhpWord/Writer/HTML/Element/TextRun.php index abae7d303f..faeeb22e7d 100644 --- a/src/PhpWord/Writer/HTML/Element/TextRun.php +++ b/src/PhpWord/Writer/HTML/Element/TextRun.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Element/Title.php b/src/PhpWord/Writer/HTML/Element/Title.php index 65e6cb090b..84b0b199fc 100644 --- a/src/PhpWord/Writer/HTML/Element/Title.php +++ b/src/PhpWord/Writer/HTML/Element/Title.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Part/AbstractPart.php b/src/PhpWord/Writer/HTML/Part/AbstractPart.php index 0fd9a40940..61bf20b29a 100644 --- a/src/PhpWord/Writer/HTML/Part/AbstractPart.php +++ b/src/PhpWord/Writer/HTML/Part/AbstractPart.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Part/Body.php b/src/PhpWord/Writer/HTML/Part/Body.php index e5e2a5b80f..4a391b53ef 100644 --- a/src/PhpWord/Writer/HTML/Part/Body.php +++ b/src/PhpWord/Writer/HTML/Part/Body.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Part/Head.php b/src/PhpWord/Writer/HTML/Part/Head.php index 0f3f86e3d2..32761a7959 100644 --- a/src/PhpWord/Writer/HTML/Part/Head.php +++ b/src/PhpWord/Writer/HTML/Part/Head.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Style/AbstractStyle.php b/src/PhpWord/Writer/HTML/Style/AbstractStyle.php index a650786769..4672347ba2 100644 --- a/src/PhpWord/Writer/HTML/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/HTML/Style/AbstractStyle.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Style/Font.php b/src/PhpWord/Writer/HTML/Style/Font.php index eb59d02d1e..1001b64d2e 100644 --- a/src/PhpWord/Writer/HTML/Style/Font.php +++ b/src/PhpWord/Writer/HTML/Style/Font.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Style/Generic.php b/src/PhpWord/Writer/HTML/Style/Generic.php index cc81c31996..21603a7be1 100644 --- a/src/PhpWord/Writer/HTML/Style/Generic.php +++ b/src/PhpWord/Writer/HTML/Style/Generic.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Style/Image.php b/src/PhpWord/Writer/HTML/Style/Image.php index c45a7a8cec..30fb373018 100644 --- a/src/PhpWord/Writer/HTML/Style/Image.php +++ b/src/PhpWord/Writer/HTML/Style/Image.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Style/Paragraph.php b/src/PhpWord/Writer/HTML/Style/Paragraph.php index 07d91f5487..22267e7b18 100644 --- a/src/PhpWord/Writer/HTML/Style/Paragraph.php +++ b/src/PhpWord/Writer/HTML/Style/Paragraph.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/HTML/Style/Table.php b/src/PhpWord/Writer/HTML/Style/Table.php index 53eea0e96f..a59d1cdba4 100644 --- a/src/PhpWord/Writer/HTML/Style/Table.php +++ b/src/PhpWord/Writer/HTML/Style/Table.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText.php b/src/PhpWord/Writer/ODText.php index 616119e5cc..c9a524e882 100644 --- a/src/PhpWord/Writer/ODText.php +++ b/src/PhpWord/Writer/ODText.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -55,7 +56,7 @@ public function __construct(?PhpWord $phpWord = null) foreach (array_keys($this->parts) as $partName) { $partClass = static::class . '\\Part\\' . $partName; if (class_exists($partClass)) { - /** @var \PhpOffice\PhpWord\Writer\ODText\Part\AbstractPart $partObject Type hint */ + /** @var AbstractPart $partObject Type hint */ $partObject = new $partClass(); $partObject->setParentWriter($this); $this->writerParts[strtolower($partName)] = $partObject; diff --git a/src/PhpWord/Writer/ODText/Element/AbstractElement.php b/src/PhpWord/Writer/ODText/Element/AbstractElement.php index 5cd396aa51..ff3a6569de 100644 --- a/src/PhpWord/Writer/ODText/Element/AbstractElement.php +++ b/src/PhpWord/Writer/ODText/Element/AbstractElement.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Element/Container.php b/src/PhpWord/Writer/ODText/Element/Container.php index 6262ad227e..6b0fee8c64 100644 --- a/src/PhpWord/Writer/ODText/Element/Container.php +++ b/src/PhpWord/Writer/ODText/Element/Container.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Element/Field.php b/src/PhpWord/Writer/ODText/Element/Field.php index 46f62b0f02..6b54807869 100644 --- a/src/PhpWord/Writer/ODText/Element/Field.php +++ b/src/PhpWord/Writer/ODText/Element/Field.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Element/Formula.php b/src/PhpWord/Writer/ODText/Element/Formula.php index ddb1d81aee..2c7ce3aaf1 100644 --- a/src/PhpWord/Writer/ODText/Element/Formula.php +++ b/src/PhpWord/Writer/ODText/Element/Formula.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Element/Image.php b/src/PhpWord/Writer/ODText/Element/Image.php index e5a7fba284..baa3c8cdb6 100644 --- a/src/PhpWord/Writer/ODText/Element/Image.php +++ b/src/PhpWord/Writer/ODText/Element/Image.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Element/Link.php b/src/PhpWord/Writer/ODText/Element/Link.php index 0375b11bc1..9ef35692c8 100644 --- a/src/PhpWord/Writer/ODText/Element/Link.php +++ b/src/PhpWord/Writer/ODText/Element/Link.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Element/ListItemRun.php b/src/PhpWord/Writer/ODText/Element/ListItemRun.php index 89352bbbd2..1319e48577 100644 --- a/src/PhpWord/Writer/ODText/Element/ListItemRun.php +++ b/src/PhpWord/Writer/ODText/Element/ListItemRun.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Element/PageBreak.php b/src/PhpWord/Writer/ODText/Element/PageBreak.php index 367106c0fd..ca9e53f4a6 100644 --- a/src/PhpWord/Writer/ODText/Element/PageBreak.php +++ b/src/PhpWord/Writer/ODText/Element/PageBreak.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Element/Table.php b/src/PhpWord/Writer/ODText/Element/Table.php index e12ae24b58..097f6742bb 100644 --- a/src/PhpWord/Writer/ODText/Element/Table.php +++ b/src/PhpWord/Writer/ODText/Element/Table.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -35,7 +36,7 @@ public function write(): void { $xmlWriter = $this->getXmlWriter(); $element = $this->getElement(); - if (!$element instanceof \PhpOffice\PhpWord\Element\Table) { + if (!$element instanceof TableElement) { return; } $rows = $element->getRows(); @@ -77,7 +78,7 @@ private function writeColumns(XMLWriter $xmlWriter, TableElement $element): void private function writeRow(XMLWriter $xmlWriter, RowElement $row): void { $xmlWriter->startElement('table:table-row'); - /** @var \PhpOffice\PhpWord\Element\Row $row Type hint */ + /** @var RowElement $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/Text.php b/src/PhpWord/Writer/ODText/Element/Text.php index 7d54071471..65909fce0c 100644 --- a/src/PhpWord/Writer/ODText/Element/Text.php +++ b/src/PhpWord/Writer/ODText/Element/Text.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Element/TextBreak.php b/src/PhpWord/Writer/ODText/Element/TextBreak.php index 1bfe398857..1a69700792 100644 --- a/src/PhpWord/Writer/ODText/Element/TextBreak.php +++ b/src/PhpWord/Writer/ODText/Element/TextBreak.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Element/TextRun.php b/src/PhpWord/Writer/ODText/Element/TextRun.php index 6d1e1a191a..9d009c3994 100644 --- a/src/PhpWord/Writer/ODText/Element/TextRun.php +++ b/src/PhpWord/Writer/ODText/Element/TextRun.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Element/Title.php b/src/PhpWord/Writer/ODText/Element/Title.php index ebe7dc4d5f..6108710517 100644 --- a/src/PhpWord/Writer/ODText/Element/Title.php +++ b/src/PhpWord/Writer/ODText/Element/Title.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Part/AbstractPart.php b/src/PhpWord/Writer/ODText/Part/AbstractPart.php index 59035ff787..458831d3ad 100644 --- a/src/PhpWord/Writer/ODText/Part/AbstractPart.php +++ b/src/PhpWord/Writer/ODText/Part/AbstractPart.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Part/Content.php b/src/PhpWord/Writer/ODText/Part/Content.php index 00871d9c52..de82ed96d1 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -230,7 +231,7 @@ private function writeTextStyles(XMLWriter $xmlWriter): void } } foreach ($this->imageParagraphStyles as $style) { - $styleWriter = new \PhpOffice\PhpWord\Writer\ODText\Style\Paragraph($xmlWriter, $style); + $styleWriter = new ParagraphStyleWriter($xmlWriter, $style); $styleWriter->write(); } } @@ -256,7 +257,7 @@ private function getAutoStyles(PhpWord $phpWord): void * * Table style can be null or string of the style name * - * @param \PhpOffice\PhpWord\Element\AbstractContainer $container + * @param AbstractContainer $container * @param int $paragraphStyleCount * @param int $fontStyleCount * @@ -277,7 +278,7 @@ private function getContainerStyle($container, &$paragraphStyleCount, &$fontStyl $style = $element->getStyle(); $style->setStyleName('fr' . $element->getMediaIndex()); $this->autoStyles['Image'][] = $style; - $sty = new \PhpOffice\PhpWord\Style\Paragraph(); + $sty = new Paragraph(); $sty->setStyleName('IM' . $element->getMediaIndex()); $sty->setAuto(); $sty->setAlignment($style->getAlignment()); @@ -300,7 +301,7 @@ private function getContainerStyle($container, &$paragraphStyleCount, &$fontStyl /** * Get style of individual element. * - * @param \PhpOffice\PhpWord\Element\Text $element + * @param Text $element * @param int $paragraphStyleCount * @param int $fontStyleCount */ @@ -346,7 +347,7 @@ private function getElementStyle($element, &$paragraphStyleCount, &$fontStyleCou /** * Get font style of individual field element. * - * @param \PhpOffice\PhpWord\Element\Field $element + * @param Field $element * @param int $fontStyleCount */ private function getElementStyleField($element, &$fontStyleCount): void @@ -371,7 +372,7 @@ private function getElementStyleField($element, &$fontStyleCount): void /** * Get style of individual element. * - * @param \PhpOffice\PhpWord\Element\TextRun $element + * @param TextRun $element * @param int $paragraphStyleCount */ private function getElementStyleTextRun($element, &$paragraphStyleCount): void diff --git a/src/PhpWord/Writer/ODText/Part/Manifest.php b/src/PhpWord/Writer/ODText/Part/Manifest.php index 37fb797935..200da15836 100644 --- a/src/PhpWord/Writer/ODText/Part/Manifest.php +++ b/src/PhpWord/Writer/ODText/Part/Manifest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Part/Meta.php b/src/PhpWord/Writer/ODText/Part/Meta.php index 8a35d02a62..21410ba9fd 100644 --- a/src/PhpWord/Writer/ODText/Part/Meta.php +++ b/src/PhpWord/Writer/ODText/Part/Meta.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Part/Mimetype.php b/src/PhpWord/Writer/ODText/Part/Mimetype.php index 32676660f0..1b94c155b1 100644 --- a/src/PhpWord/Writer/ODText/Part/Mimetype.php +++ b/src/PhpWord/Writer/ODText/Part/Mimetype.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Part/Styles.php b/src/PhpWord/Writer/ODText/Part/Styles.php index e1538be67b..72b93f5815 100644 --- a/src/PhpWord/Writer/ODText/Part/Styles.php +++ b/src/PhpWord/Writer/ODText/Part/Styles.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Style/AbstractStyle.php b/src/PhpWord/Writer/ODText/Style/AbstractStyle.php index 439434c986..3545009f6b 100644 --- a/src/PhpWord/Writer/ODText/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/ODText/Style/AbstractStyle.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Style/Font.php b/src/PhpWord/Writer/ODText/Style/Font.php index 1d0d14de97..85720f0274 100644 --- a/src/PhpWord/Writer/ODText/Style/Font.php +++ b/src/PhpWord/Writer/ODText/Style/Font.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -39,7 +40,7 @@ public function write(): void if ($stylep instanceof \PhpOffice\PhpWord\Style\Paragraph) { $temp1 = clone $stylep; $temp1->setStyleName($style->getStyleName()); - $temp2 = new \PhpOffice\PhpWord\Writer\ODText\Style\Paragraph($xmlWriter, $temp1); + $temp2 = new Paragraph($xmlWriter, $temp1); $temp2->write(); } diff --git a/src/PhpWord/Writer/ODText/Style/Image.php b/src/PhpWord/Writer/ODText/Style/Image.php index 79ddfc502e..56c4f57a5b 100644 --- a/src/PhpWord/Writer/ODText/Style/Image.php +++ b/src/PhpWord/Writer/ODText/Style/Image.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Style/Numbering.php b/src/PhpWord/Writer/ODText/Style/Numbering.php index 83a1c9a750..287b25b34a 100644 --- a/src/PhpWord/Writer/ODText/Style/Numbering.php +++ b/src/PhpWord/Writer/ODText/Style/Numbering.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -72,9 +73,9 @@ public function write(): void $xmlWriter->writeAttribute('fo:margin-left', number_format($tabPos, 2, '.', '') . 'cm'); $xmlWriter->endElement(); // style:list-level-label-alignment - $xmlWriter->endElement(); // style:list-level-properties + $xmlWriter->endElement(); // style:list-level-properties - $xmlWriter->startElement('style:text-properties'); + $xmlWriter->startElement('style:text-properties'); $xmlWriter->writeAttribute('style:font-name', $styleLevel->getFont()); $xmlWriter->endElement(); // style:text-properties diff --git a/src/PhpWord/Writer/ODText/Style/Paragraph.php b/src/PhpWord/Writer/ODText/Style/Paragraph.php index 4459c76c01..99963bd4a3 100644 --- a/src/PhpWord/Writer/ODText/Style/Paragraph.php +++ b/src/PhpWord/Writer/ODText/Style/Paragraph.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -45,7 +46,7 @@ class Paragraph extends AbstractStyle public function write(): void { $style = $this->getStyle(); - if (!$style instanceof \PhpOffice\PhpWord\Style\Paragraph) { + if (!$style instanceof Style\Paragraph) { return; } $xmlWriter = $this->getXmlWriter(); @@ -73,13 +74,13 @@ public function write(): void } elseif (substr($styleName, 0, 2) === 'HD') { $styleAuto = true; $psm = 'Heading_' . substr($styleName, 2); - $stylep = \PhpOffice\PhpWord\Style::getStyle($psm); - if ($stylep instanceof \PhpOffice\PhpWord\Style\Font) { + $stylep = Style::getStyle($psm); + if ($stylep instanceof Style\Font) { if (method_exists($stylep, 'getParagraph')) { $stylep = $stylep->getParagraph(); } } - if ($stylep instanceof \PhpOffice\PhpWord\Style\Paragraph) { + if ($stylep instanceof Style\Paragraph) { if ($stylep->hasPageBreakBefore()) { $breakbefore = true; } diff --git a/src/PhpWord/Writer/ODText/Style/Section.php b/src/PhpWord/Writer/ODText/Style/Section.php index 0a250194fd..05152a3944 100644 --- a/src/PhpWord/Writer/ODText/Style/Section.php +++ b/src/PhpWord/Writer/ODText/Style/Section.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/ODText/Style/Table.php b/src/PhpWord/Writer/ODText/Style/Table.php index eca6a1a3f3..b30389d8e8 100644 --- a/src/PhpWord/Writer/ODText/Style/Table.php +++ b/src/PhpWord/Writer/ODText/Style/Table.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/PDF.php b/src/PhpWord/Writer/PDF.php index f937f599c1..4f7f1be99a 100644 --- a/src/PhpWord/Writer/PDF.php +++ b/src/PhpWord/Writer/PDF.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -32,7 +33,7 @@ class PDF /** * The wrapper for the requested PDF rendering engine. * - * @var \PhpOffice\PhpWord\Writer\PDF\AbstractRenderer + * @var AbstractRenderer */ private $renderer; diff --git a/src/PhpWord/Writer/PDF/AbstractRenderer.php b/src/PhpWord/Writer/PDF/AbstractRenderer.php index c143a6cb5c..125bf4fa43 100644 --- a/src/PhpWord/Writer/PDF/AbstractRenderer.php +++ b/src/PhpWord/Writer/PDF/AbstractRenderer.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/PDF/DomPDF.php b/src/PhpWord/Writer/PDF/DomPDF.php index 8e5b4054d5..464dbfa59f 100644 --- a/src/PhpWord/Writer/PDF/DomPDF.php +++ b/src/PhpWord/Writer/PDF/DomPDF.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/PDF/MPDF.php b/src/PhpWord/Writer/PDF/MPDF.php index 311f743d6d..03ef1f3ad7 100644 --- a/src/PhpWord/Writer/PDF/MPDF.php +++ b/src/PhpWord/Writer/PDF/MPDF.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/PDF/TCPDF.php b/src/PhpWord/Writer/PDF/TCPDF.php index 1bb1974244..93bdd58528 100644 --- a/src/PhpWord/Writer/PDF/TCPDF.php +++ b/src/PhpWord/Writer/PDF/TCPDF.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF.php b/src/PhpWord/Writer/RTF.php index 0a04d4f53e..390311aa26 100644 --- a/src/PhpWord/Writer/RTF.php +++ b/src/PhpWord/Writer/RTF.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -44,7 +45,7 @@ public function __construct(?PhpWord $phpWord = null) foreach ($this->parts as $partName) { $partClass = static::class . '\\Part\\' . $partName; if (class_exists($partClass)) { - /** @var \PhpOffice\PhpWord\Writer\RTF\Part\AbstractPart $part Type hint */ + /** @var RTF\Part\AbstractPart $part Type hint */ $part = new $partClass(); $part->setParentWriter($this); $this->writerParts[strtolower($partName)] = $part; diff --git a/src/PhpWord/Writer/RTF/Element/AbstractElement.php b/src/PhpWord/Writer/RTF/Element/AbstractElement.php index 5c33868a8b..e007e6aa26 100644 --- a/src/PhpWord/Writer/RTF/Element/AbstractElement.php +++ b/src/PhpWord/Writer/RTF/Element/AbstractElement.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -45,7 +46,7 @@ abstract class AbstractElement /** * Element. * - * @var \PhpOffice\PhpWord\Element\AbstractElement + * @var Element */ protected $element; @@ -66,14 +67,14 @@ abstract public function write(); /** * Font style. * - * @var \PhpOffice\PhpWord\Style\Font + * @var FontStyle */ protected $fontStyle; /** * Paragraph style. * - * @var \PhpOffice\PhpWord\Style\Paragraph + * @var ParagraphStyle */ protected $paragraphStyle; @@ -95,7 +96,7 @@ public function __construct(WriterRTF $parentWriter, Element $element, bool $wit */ protected function getStyles(): void { - /** @var \PhpOffice\PhpWord\Writer\RTF $parentWriter Type hint */ + /** @var WriterRTF $parentWriter Type hint */ $parentWriter = $this->parentWriter; /** @var \PhpOffice\PhpWord\Element\Text $element Type hint */ @@ -188,7 +189,7 @@ protected function writeFontStyle() return ''; } - /** @var \PhpOffice\PhpWord\Writer\RTF $parentWriter Type hint */ + /** @var WriterRTF $parentWriter Type hint */ $parentWriter = $this->parentWriter; // Create style writer and set color/name index diff --git a/src/PhpWord/Writer/RTF/Element/Container.php b/src/PhpWord/Writer/RTF/Element/Container.php index 5e198aec86..dcac8ec071 100644 --- a/src/PhpWord/Writer/RTF/Element/Container.php +++ b/src/PhpWord/Writer/RTF/Element/Container.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Element/Field.php b/src/PhpWord/Writer/RTF/Element/Field.php index 34024f5e51..c5e49c1d44 100644 --- a/src/PhpWord/Writer/RTF/Element/Field.php +++ b/src/PhpWord/Writer/RTF/Element/Field.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Element/Image.php b/src/PhpWord/Writer/RTF/Element/Image.php index bec8e9caa7..53052c85e7 100644 --- a/src/PhpWord/Writer/RTF/Element/Image.php +++ b/src/PhpWord/Writer/RTF/Element/Image.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Element/Link.php b/src/PhpWord/Writer/RTF/Element/Link.php index 76b7ebaa1c..1687d38bca 100644 --- a/src/PhpWord/Writer/RTF/Element/Link.php +++ b/src/PhpWord/Writer/RTF/Element/Link.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Element/ListItem.php b/src/PhpWord/Writer/RTF/Element/ListItem.php index 6ed6d2bd14..8ce7d0d063 100644 --- a/src/PhpWord/Writer/RTF/Element/ListItem.php +++ b/src/PhpWord/Writer/RTF/Element/ListItem.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Element/PageBreak.php b/src/PhpWord/Writer/RTF/Element/PageBreak.php index 386c1222c1..bb4af332ba 100644 --- a/src/PhpWord/Writer/RTF/Element/PageBreak.php +++ b/src/PhpWord/Writer/RTF/Element/PageBreak.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Element/Table.php b/src/PhpWord/Writer/RTF/Element/Table.php index f2d5f9fb5a..3b08a5db86 100644 --- a/src/PhpWord/Writer/RTF/Element/Table.php +++ b/src/PhpWord/Writer/RTF/Element/Table.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Element/Text.php b/src/PhpWord/Writer/RTF/Element/Text.php index bd8cbae5ca..71d3a27ce8 100644 --- a/src/PhpWord/Writer/RTF/Element/Text.php +++ b/src/PhpWord/Writer/RTF/Element/Text.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Element/TextBreak.php b/src/PhpWord/Writer/RTF/Element/TextBreak.php index 0c470f407d..d74bf23dcb 100644 --- a/src/PhpWord/Writer/RTF/Element/TextBreak.php +++ b/src/PhpWord/Writer/RTF/Element/TextBreak.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Element/TextRun.php b/src/PhpWord/Writer/RTF/Element/TextRun.php index f2b70ad525..6418de54a8 100644 --- a/src/PhpWord/Writer/RTF/Element/TextRun.php +++ b/src/PhpWord/Writer/RTF/Element/TextRun.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Element/Title.php b/src/PhpWord/Writer/RTF/Element/Title.php index fb11da7849..1022e59f8f 100644 --- a/src/PhpWord/Writer/RTF/Element/Title.php +++ b/src/PhpWord/Writer/RTF/Element/Title.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Part/AbstractPart.php b/src/PhpWord/Writer/RTF/Part/AbstractPart.php index be772b93a0..a07f70bbf7 100644 --- a/src/PhpWord/Writer/RTF/Part/AbstractPart.php +++ b/src/PhpWord/Writer/RTF/Part/AbstractPart.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Part/Document.php b/src/PhpWord/Writer/RTF/Part/Document.php index a0002583a9..bd659c6794 100644 --- a/src/PhpWord/Writer/RTF/Part/Document.php +++ b/src/PhpWord/Writer/RTF/Part/Document.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -162,12 +163,12 @@ private function writeSections() foreach ($section->getHeaders() as $header) { $type = $header->getType(); - if ($evenOdd || $type !== FOOTER::EVEN) { + if ($evenOdd || $type !== Footer::EVEN) { $content .= '{\\header'; if ($type === Footer::FIRST) { $content .= 'f'; } elseif ($evenOdd) { - $content .= ($type === FOOTER::EVEN) ? 'l' : 'r'; + $content .= ($type === Footer::EVEN) ? 'l' : 'r'; } foreach ($header->getElements() as $element) { $cl = get_class($element); @@ -182,12 +183,12 @@ private function writeSections() } foreach ($section->getFooters() as $footer) { $type = $footer->getType(); - if ($evenOdd || $type !== FOOTER::EVEN) { + if ($evenOdd || $type !== Footer::EVEN) { $content .= '{\\footer'; if ($type === Footer::FIRST) { $content .= 'f'; } elseif ($evenOdd) { - $content .= ($type === FOOTER::EVEN) ? 'l' : 'r'; + $content .= ($type === Footer::EVEN) ? 'l' : 'r'; } foreach ($footer->getElements() as $element) { $cl = get_class($element); diff --git a/src/PhpWord/Writer/RTF/Part/Header.php b/src/PhpWord/Writer/RTF/Part/Header.php index 7f8cc84b97..97644fe4ac 100644 --- a/src/PhpWord/Writer/RTF/Part/Header.php +++ b/src/PhpWord/Writer/RTF/Part/Header.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -211,7 +212,7 @@ private function registerFont(): void /** * Register border colors. * - * @param \PhpOffice\PhpWord\Style\Border $style + * @param Style\Border $style */ private function registerBorderColor($style): void { @@ -226,7 +227,7 @@ private function registerBorderColor($style): void /** * Register fonts and colors. * - * @param \PhpOffice\PhpWord\Style\AbstractStyle $style + * @param Style\AbstractStyle $style */ private function registerFontItems($style): void { diff --git a/src/PhpWord/Writer/RTF/Style/AbstractStyle.php b/src/PhpWord/Writer/RTF/Style/AbstractStyle.php index 355e384440..00e148dfe9 100644 --- a/src/PhpWord/Writer/RTF/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/RTF/Style/AbstractStyle.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Style/Border.php b/src/PhpWord/Writer/RTF/Style/Border.php index c674170d8b..8f3024493c 100644 --- a/src/PhpWord/Writer/RTF/Style/Border.php +++ b/src/PhpWord/Writer/RTF/Style/Border.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Style/Font.php b/src/PhpWord/Writer/RTF/Style/Font.php index 5980c100b4..f343c0502f 100644 --- a/src/PhpWord/Writer/RTF/Style/Font.php +++ b/src/PhpWord/Writer/RTF/Style/Font.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Style/Indentation.php b/src/PhpWord/Writer/RTF/Style/Indentation.php index fc33a8514a..589125a26a 100644 --- a/src/PhpWord/Writer/RTF/Style/Indentation.php +++ b/src/PhpWord/Writer/RTF/Style/Indentation.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index e19d24bbad..040c60b5aa 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Style/Section.php b/src/PhpWord/Writer/RTF/Style/Section.php index 9c6a60ad6a..598015ed4d 100644 --- a/src/PhpWord/Writer/RTF/Style/Section.php +++ b/src/PhpWord/Writer/RTF/Style/Section.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/RTF/Style/Tab.php b/src/PhpWord/Writer/RTF/Style/Tab.php index bb885e16c0..95e1f10a5c 100644 --- a/src/PhpWord/Writer/RTF/Style/Tab.php +++ b/src/PhpWord/Writer/RTF/Style/Tab.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007.php b/src/PhpWord/Writer/Word2007.php index e7801c04c2..e54bfa8ad2 100644 --- a/src/PhpWord/Writer/Word2007.php +++ b/src/PhpWord/Writer/Word2007.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -43,8 +44,6 @@ class Word2007 extends AbstractWriter implements WriterInterface /** * Create new Word2007 writer. - * - * @param \PhpOffice\PhpWord\PhpWord */ public function __construct(?PhpWord $phpWord = null) { @@ -78,7 +77,7 @@ public function __construct(?PhpWord $phpWord = null) foreach (array_keys($this->parts) as $partName) { $partClass = static::class . '\\Part\\' . $partName; if (class_exists($partClass)) { - /** @var \PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart $part Type hint */ + /** @var Word2007\Part\AbstractPart $part Type hint */ $part = new $partClass(); $part->setParentWriter($this); $this->writerParts[strtolower($partName)] = $part; @@ -179,7 +178,7 @@ private function addHeaderFooterMedia(ZipArchive $zip, $docPart): void $this->registerContentTypes($media); } - /** @var \PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart $writerPart Type hint */ + /** @var Word2007\Part\AbstractPart $writerPart Type hint */ $writerPart = $this->getWriterPart('relspart')->setMedia($media); $zip->addFromString("word/_rels/{$file}.xml.rels", $writerPart->write()); } @@ -206,7 +205,7 @@ private function addHeaderFooterContent(Section &$section, ZipArchive $zip, $elm $this->contentTypes['override']["/word/$elmFile"] = $elmType; $this->relationships[] = ['target' => $elmFile, 'type' => $elmType, 'rID' => $rId]; - /** @var \PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart $writerPart Type hint */ + /** @var Word2007\Part\AbstractPart $writerPart Type hint */ $writerPart = $this->getWriterPart($elmType)->setElement($element); $zip->addFromString("word/$elmFile", $writerPart->write()); } @@ -236,7 +235,7 @@ private function addNotes(ZipArchive $zip, &$rId, $noteType = 'footnote'): void // Write relationships file, e.g. word/_rels/footnotes.xml if (!empty($media)) { - /** @var \PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart $writerPart Type hint */ + /** @var Word2007\Part\AbstractPart $writerPart Type hint */ $writerPart = $this->getWriterPart('relspart')->setMedia($media); $zip->addFromString("word/_rels/{$partName}.xml.rels", $writerPart->write()); } diff --git a/src/PhpWord/Writer/Word2007/Element/AbstractElement.php b/src/PhpWord/Writer/Word2007/Element/AbstractElement.php index a71ec6f95e..5743c8c7c7 100644 --- a/src/PhpWord/Writer/Word2007/Element/AbstractElement.php +++ b/src/PhpWord/Writer/Word2007/Element/AbstractElement.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -33,14 +34,14 @@ abstract class AbstractElement /** * XML writer. * - * @var \PhpOffice\PhpWord\Shared\XMLWriter + * @var XMLWriter */ private $xmlWriter; /** * Element. * - * @var \PhpOffice\PhpWord\Element\AbstractElement + * @var Element */ private $element; @@ -74,7 +75,7 @@ public function __construct(XMLWriter $xmlWriter, Element $element, bool $withou /** * Get XML Writer. * - * @return \PhpOffice\PhpWord\Shared\XMLWriter + * @return XMLWriter */ protected function getXmlWriter() { @@ -84,7 +85,7 @@ protected function getXmlWriter() /** * Get element. * - * @return \PhpOffice\PhpWord\Element\AbstractElement + * @return Element */ protected function getElement() { diff --git a/src/PhpWord/Writer/Word2007/Element/Bookmark.php b/src/PhpWord/Writer/Word2007/Element/Bookmark.php index 1e618af987..ba61ad69fd 100644 --- a/src/PhpWord/Writer/Word2007/Element/Bookmark.php +++ b/src/PhpWord/Writer/Word2007/Element/Bookmark.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/Chart.php b/src/PhpWord/Writer/Word2007/Element/Chart.php index 9721384fd3..6d4e18a9e4 100644 --- a/src/PhpWord/Writer/Word2007/Element/Chart.php +++ b/src/PhpWord/Writer/Word2007/Element/Chart.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/CheckBox.php b/src/PhpWord/Writer/Word2007/Element/CheckBox.php index 3d7fdab1fa..1adf7d6eb1 100644 --- a/src/PhpWord/Writer/Word2007/Element/CheckBox.php +++ b/src/PhpWord/Writer/Word2007/Element/CheckBox.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/Container.php b/src/PhpWord/Writer/Word2007/Element/Container.php index 919954c152..85386f0b18 100644 --- a/src/PhpWord/Writer/Word2007/Element/Container.php +++ b/src/PhpWord/Writer/Word2007/Element/Container.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -67,7 +68,7 @@ public function write(): void $writeLastTextBreak = ($containerClass == 'Cell') && ($elementClass == '' || $elementClass == 'Table'); if ($writeLastTextBreak) { $writerClass = $this->namespace . '\\TextBreak'; - /** @var \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement $writer Type hint */ + /** @var AbstractElement $writer Type hint */ $writer = new $writerClass($xmlWriter, new TextBreakElement(), $withoutP); $writer->write(); } @@ -82,7 +83,7 @@ private function writeElement(XMLWriter $xmlWriter, Element $element, bool $with $writerClass = $this->namespace . '\\' . $elementClass; if (class_exists($writerClass)) { - /** @var \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement $writer Type hint */ + /** @var AbstractElement $writer Type hint */ $writer = new $writerClass($xmlWriter, $element, $withoutP); $writer->setPart($this->getPart()); $writer->write(); diff --git a/src/PhpWord/Writer/Word2007/Element/Endnote.php b/src/PhpWord/Writer/Word2007/Element/Endnote.php index f96ac7977f..6a00ed5b3b 100644 --- a/src/PhpWord/Writer/Word2007/Element/Endnote.php +++ b/src/PhpWord/Writer/Word2007/Element/Endnote.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/Field.php b/src/PhpWord/Writer/Word2007/Element/Field.php index 2977c01626..c02bbdbcc9 100644 --- a/src/PhpWord/Writer/Word2007/Element/Field.php +++ b/src/PhpWord/Writer/Word2007/Element/Field.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -147,7 +148,7 @@ protected function writeMacrobutton(ElementField $element): void $xmlWriter->endElement(); // w:r if ($element->getText() != null) { - if ($element->getText() instanceof \PhpOffice\PhpWord\Element\TextRun) { + if ($element->getText() instanceof TextRun) { $containerWriter = new Container($xmlWriter, $element->getText(), true); $containerWriter->write(); } @@ -262,7 +263,7 @@ protected function writeRef(ElementField $element): void $xmlWriter->endElement(); // w:r if ($element->getText() != null) { - if ($element->getText() instanceof \PhpOffice\PhpWord\Element\TextRun) { + if ($element->getText() instanceof TextRun) { $containerWriter = new Container($xmlWriter, $element->getText(), true); $containerWriter->write(); diff --git a/src/PhpWord/Writer/Word2007/Element/Footnote.php b/src/PhpWord/Writer/Word2007/Element/Footnote.php index 77073a239d..68f998e390 100644 --- a/src/PhpWord/Writer/Word2007/Element/Footnote.php +++ b/src/PhpWord/Writer/Word2007/Element/Footnote.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/FormField.php b/src/PhpWord/Writer/Word2007/Element/FormField.php index 5bfc8cab45..c5d59a4497 100644 --- a/src/PhpWord/Writer/Word2007/Element/FormField.php +++ b/src/PhpWord/Writer/Word2007/Element/FormField.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/Formula.php b/src/PhpWord/Writer/Word2007/Element/Formula.php index 6abb74b782..9556706221 100644 --- a/src/PhpWord/Writer/Word2007/Element/Formula.php +++ b/src/PhpWord/Writer/Word2007/Element/Formula.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/Image.php b/src/PhpWord/Writer/Word2007/Element/Image.php index d33a5776dd..7835f32ad5 100644 --- a/src/PhpWord/Writer/Word2007/Element/Image.php +++ b/src/PhpWord/Writer/Word2007/Element/Image.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/Line.php b/src/PhpWord/Writer/Word2007/Element/Line.php index f01386b408..fe8370653a 100644 --- a/src/PhpWord/Writer/Word2007/Element/Line.php +++ b/src/PhpWord/Writer/Word2007/Element/Line.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/Link.php b/src/PhpWord/Writer/Word2007/Element/Link.php index a8686e82a5..563343899d 100644 --- a/src/PhpWord/Writer/Word2007/Element/Link.php +++ b/src/PhpWord/Writer/Word2007/Element/Link.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/ListItem.php b/src/PhpWord/Writer/Word2007/Element/ListItem.php index e254fb1459..a91301cdc0 100644 --- a/src/PhpWord/Writer/Word2007/Element/ListItem.php +++ b/src/PhpWord/Writer/Word2007/Element/ListItem.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/ListItemRun.php b/src/PhpWord/Writer/Word2007/Element/ListItemRun.php index daa2fc1d0f..a20912a0a8 100644 --- a/src/PhpWord/Writer/Word2007/Element/ListItemRun.php +++ b/src/PhpWord/Writer/Word2007/Element/ListItemRun.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/OLEObject.php b/src/PhpWord/Writer/Word2007/Element/OLEObject.php index 94c2472908..f7db89defe 100644 --- a/src/PhpWord/Writer/Word2007/Element/OLEObject.php +++ b/src/PhpWord/Writer/Word2007/Element/OLEObject.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/PageBreak.php b/src/PhpWord/Writer/Word2007/Element/PageBreak.php index b9c3e79a7e..2e9ba4f202 100644 --- a/src/PhpWord/Writer/Word2007/Element/PageBreak.php +++ b/src/PhpWord/Writer/Word2007/Element/PageBreak.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/ParagraphAlignment.php b/src/PhpWord/Writer/Word2007/Element/ParagraphAlignment.php index 0f3e65e7b1..2dbf229d63 100644 --- a/src/PhpWord/Writer/Word2007/Element/ParagraphAlignment.php +++ b/src/PhpWord/Writer/Word2007/Element/ParagraphAlignment.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/PreserveText.php b/src/PhpWord/Writer/Word2007/Element/PreserveText.php index 3a3768e717..3ae708381f 100644 --- a/src/PhpWord/Writer/Word2007/Element/PreserveText.php +++ b/src/PhpWord/Writer/Word2007/Element/PreserveText.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/SDT.php b/src/PhpWord/Writer/Word2007/Element/SDT.php index f007dc790f..950c293776 100644 --- a/src/PhpWord/Writer/Word2007/Element/SDT.php +++ b/src/PhpWord/Writer/Word2007/Element/SDT.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/Shape.php b/src/PhpWord/Writer/Word2007/Element/Shape.php index 0fe4e6dba7..653c31809a 100644 --- a/src/PhpWord/Writer/Word2007/Element/Shape.php +++ b/src/PhpWord/Writer/Word2007/Element/Shape.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/TOC.php b/src/PhpWord/Writer/Word2007/Element/TOC.php index 2cf76155e4..8164aa6528 100644 --- a/src/PhpWord/Writer/Word2007/Element/TOC.php +++ b/src/PhpWord/Writer/Word2007/Element/TOC.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/Table.php b/src/PhpWord/Writer/Word2007/Element/Table.php index a32cc19639..2bb1b3f3a8 100644 --- a/src/PhpWord/Writer/Word2007/Element/Table.php +++ b/src/PhpWord/Writer/Word2007/Element/Table.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/TableAlignment.php b/src/PhpWord/Writer/Word2007/Element/TableAlignment.php index c8b48644da..9c0977b8fd 100644 --- a/src/PhpWord/Writer/Word2007/Element/TableAlignment.php +++ b/src/PhpWord/Writer/Word2007/Element/TableAlignment.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/Text.php b/src/PhpWord/Writer/Word2007/Element/Text.php index d61dd66800..c11b2d517f 100644 --- a/src/PhpWord/Writer/Word2007/Element/Text.php +++ b/src/PhpWord/Writer/Word2007/Element/Text.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/TextBox.php b/src/PhpWord/Writer/Word2007/Element/TextBox.php index ff94094de7..e005480802 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Element/TextBox.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/TextBreak.php b/src/PhpWord/Writer/Word2007/Element/TextBreak.php index bcae3b2e1e..4c2ecde7ed 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextBreak.php +++ b/src/PhpWord/Writer/Word2007/Element/TextBreak.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/TextRun.php b/src/PhpWord/Writer/Word2007/Element/TextRun.php index 8a5870777b..865ceb742a 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextRun.php +++ b/src/PhpWord/Writer/Word2007/Element/TextRun.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Element/Title.php b/src/PhpWord/Writer/Word2007/Element/Title.php index 072dcc8d84..b69fbd40db 100644 --- a/src/PhpWord/Writer/Word2007/Element/Title.php +++ b/src/PhpWord/Writer/Word2007/Element/Title.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Part/AbstractPart.php b/src/PhpWord/Writer/Word2007/Part/AbstractPart.php index ef823f104d..92ef1b521f 100644 --- a/src/PhpWord/Writer/Word2007/Part/AbstractPart.php +++ b/src/PhpWord/Writer/Word2007/Part/AbstractPart.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -30,7 +31,7 @@ abstract class AbstractPart /** * Parent writer. * - * @var \PhpOffice\PhpWord\Writer\AbstractWriter + * @var AbstractWriter */ protected $parentWriter; @@ -57,7 +58,7 @@ public function setParentWriter(?AbstractWriter $writer = null): void /** * Get parent writer. * - * @return \PhpOffice\PhpWord\Writer\AbstractWriter + * @return AbstractWriter */ public function getParentWriter() { @@ -71,7 +72,7 @@ public function getParentWriter() /** * Get XML Writer. * - * @return \PhpOffice\PhpWord\Shared\XMLWriter + * @return XMLWriter */ protected function getXmlWriter() { diff --git a/src/PhpWord/Writer/Word2007/Part/Chart.php b/src/PhpWord/Writer/Word2007/Part/Chart.php index 314b6453f3..65e686ebad 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -31,7 +32,7 @@ class Chart extends AbstractPart /** * Chart element. * - * @var \PhpOffice\PhpWord\Element\Chart + * @var ChartElement */ private $element; diff --git a/src/PhpWord/Writer/Word2007/Part/Comments.php b/src/PhpWord/Writer/Word2007/Part/Comments.php index 93dd4e1ce5..e1d7d05340 100644 --- a/src/PhpWord/Writer/Word2007/Part/Comments.php +++ b/src/PhpWord/Writer/Word2007/Part/Comments.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -29,7 +30,7 @@ class Comments extends AbstractPart /** * Comments collection to be written. * - * @var \PhpOffice\PhpWord\Element\Comment[] + * @var Comment[] */ protected $elements; @@ -89,7 +90,7 @@ protected function writeComment(XMLWriter $xmlWriter, Comment $comment): void /** * Set element. * - * @param \PhpOffice\PhpWord\Element\Comment[] $elements + * @param Comment[] $elements * * @return self */ diff --git a/src/PhpWord/Writer/Word2007/Part/ContentTypes.php b/src/PhpWord/Writer/Word2007/Part/ContentTypes.php index c1da573e12..2973eea15b 100644 --- a/src/PhpWord/Writer/Word2007/Part/ContentTypes.php +++ b/src/PhpWord/Writer/Word2007/Part/ContentTypes.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -80,7 +81,7 @@ public function write() /** * Write content types element. * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter XML Writer + * @param XMLWriter $xmlWriter XML Writer * @param array $parts * @param bool $isDefault */ diff --git a/src/PhpWord/Writer/Word2007/Part/DocPropsApp.php b/src/PhpWord/Writer/Word2007/Part/DocPropsApp.php index cc7d7ea26e..aaba2fcf37 100644 --- a/src/PhpWord/Writer/Word2007/Part/DocPropsApp.php +++ b/src/PhpWord/Writer/Word2007/Part/DocPropsApp.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Part/DocPropsCore.php b/src/PhpWord/Writer/Word2007/Part/DocPropsCore.php index 92f19fbc41..25eae6ab1f 100644 --- a/src/PhpWord/Writer/Word2007/Part/DocPropsCore.php +++ b/src/PhpWord/Writer/Word2007/Part/DocPropsCore.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Part/DocPropsCustom.php b/src/PhpWord/Writer/Word2007/Part/DocPropsCustom.php index 08da912e84..53297787d6 100644 --- a/src/PhpWord/Writer/Word2007/Part/DocPropsCustom.php +++ b/src/PhpWord/Writer/Word2007/Part/DocPropsCustom.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Part/Document.php b/src/PhpWord/Writer/Word2007/Part/Document.php index 6eca90e730..9a2ec09ef2 100644 --- a/src/PhpWord/Writer/Word2007/Part/Document.php +++ b/src/PhpWord/Writer/Word2007/Part/Document.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Part/Endnotes.php b/src/PhpWord/Writer/Word2007/Part/Endnotes.php index 423482b27f..5e733834db 100644 --- a/src/PhpWord/Writer/Word2007/Part/Endnotes.php +++ b/src/PhpWord/Writer/Word2007/Part/Endnotes.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Part/FontTable.php b/src/PhpWord/Writer/Word2007/Part/FontTable.php index f979ca5a6c..1232cc7aa7 100644 --- a/src/PhpWord/Writer/Word2007/Part/FontTable.php +++ b/src/PhpWord/Writer/Word2007/Part/FontTable.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Part/Footer.php b/src/PhpWord/Writer/Word2007/Part/Footer.php index fd62c8941f..0e2f55e74e 100644 --- a/src/PhpWord/Writer/Word2007/Part/Footer.php +++ b/src/PhpWord/Writer/Word2007/Part/Footer.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Part/Footnotes.php b/src/PhpWord/Writer/Word2007/Part/Footnotes.php index e284c674b5..5e6e92a9db 100644 --- a/src/PhpWord/Writer/Word2007/Part/Footnotes.php +++ b/src/PhpWord/Writer/Word2007/Part/Footnotes.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -136,7 +137,7 @@ public function setElements($elements) /** * Write note item. * - * @param \PhpOffice\PhpWord\Element\Endnote|\PhpOffice\PhpWord\Element\Footnote $element + * @param Footnote|\PhpOffice\PhpWord\Element\Endnote $element */ protected function writeNote(XMLWriter $xmlWriter, $element): void { diff --git a/src/PhpWord/Writer/Word2007/Part/Header.php b/src/PhpWord/Writer/Word2007/Part/Header.php index 36abd06040..1fafc79129 100644 --- a/src/PhpWord/Writer/Word2007/Part/Header.php +++ b/src/PhpWord/Writer/Word2007/Part/Header.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Part/Numbering.php b/src/PhpWord/Writer/Word2007/Part/Numbering.php index 3f50de08d4..ca29cd01d5 100644 --- a/src/PhpWord/Writer/Word2007/Part/Numbering.php +++ b/src/PhpWord/Writer/Word2007/Part/Numbering.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -190,6 +191,6 @@ private function writeFont(XMLWriter $xmlWriter, NumberingLevel $level): void */ private function getRandomHexNumber($length = 8) { - return strtoupper(substr(md5(mt_rand()), 0, $length)); + return strtoupper((string) substr(md5((string) mt_rand()), 0, $length)); } } diff --git a/src/PhpWord/Writer/Word2007/Part/Rels.php b/src/PhpWord/Writer/Word2007/Part/Rels.php index 2dd9cce1de..f282f80ef4 100644 --- a/src/PhpWord/Writer/Word2007/Part/Rels.php +++ b/src/PhpWord/Writer/Word2007/Part/Rels.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Part/RelsDocument.php b/src/PhpWord/Writer/Word2007/Part/RelsDocument.php index 1d6ad7b2f3..d2a9f994a8 100644 --- a/src/PhpWord/Writer/Word2007/Part/RelsDocument.php +++ b/src/PhpWord/Writer/Word2007/Part/RelsDocument.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Part/RelsPart.php b/src/PhpWord/Writer/Word2007/Part/RelsPart.php index 375fadc433..5e73c1f28d 100644 --- a/src/PhpWord/Writer/Word2007/Part/RelsPart.php +++ b/src/PhpWord/Writer/Word2007/Part/RelsPart.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Part/Settings.php b/src/PhpWord/Writer/Word2007/Part/Settings.php index 85a7fe2c50..cd7beb4e7b 100644 --- a/src/PhpWord/Writer/Word2007/Part/Settings.php +++ b/src/PhpWord/Writer/Word2007/Part/Settings.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -196,7 +197,7 @@ private function setDocumentProtection($documentProtection): void ]; } else { if ($documentProtection->getSalt() == null) { - $documentProtection->setSalt(openssl_random_pseudo_bytes(16)); + $documentProtection->setSalt((string) openssl_random_pseudo_bytes(16)); } $passwordHash = PasswordEncoder::hashPassword($documentProtection->getPassword(), $documentProtection->getAlgorithm(), $documentProtection->getSalt(), $documentProtection->getSpinCount()); $this->settings['w:documentProtection'] = [ diff --git a/src/PhpWord/Writer/Word2007/Part/Styles.php b/src/PhpWord/Writer/Word2007/Part/Styles.php index 2112fd3ce6..bda1e653b7 100644 --- a/src/PhpWord/Writer/Word2007/Part/Styles.php +++ b/src/PhpWord/Writer/Word2007/Part/Styles.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -77,7 +78,7 @@ public function write() /** * Write default font and other default styles. * - * @param \PhpOffice\PhpWord\Style\AbstractStyle[] $styles + * @param Style\AbstractStyle[] $styles */ private function writeDefaultStyles(XMLWriter $xmlWriter, $styles): void { @@ -125,7 +126,7 @@ private function writeDefaultStyles(XMLWriter $xmlWriter, $styles): void if (isset($styles['Normal'])) { $normalStyle = $styles['Normal']; // w:pPr - if ($normalStyle instanceof Fontstyle && $normalStyle->getParagraph() != null) { + if ($normalStyle instanceof FontStyle && $normalStyle->getParagraph() != null) { $styleWriter = new ParagraphStyleWriter($xmlWriter, $normalStyle->getParagraph()); $styleWriter->write(); } elseif ($normalStyle instanceof ParagraphStyle) { diff --git a/src/PhpWord/Writer/Word2007/Part/Theme.php b/src/PhpWord/Writer/Word2007/Part/Theme.php index ad57d66493..a70c248da6 100644 --- a/src/PhpWord/Writer/Word2007/Part/Theme.php +++ b/src/PhpWord/Writer/Word2007/Part/Theme.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Part/WebSettings.php b/src/PhpWord/Writer/Word2007/Part/WebSettings.php index 36bea059ea..d3a05bd70a 100644 --- a/src/PhpWord/Writer/Word2007/Part/WebSettings.php +++ b/src/PhpWord/Writer/Word2007/Part/WebSettings.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php b/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php index dc4eccd2ce..9a30bebf0e 100644 --- a/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -30,7 +31,7 @@ abstract class AbstractStyle /** * XML writer. * - * @var \PhpOffice\PhpWord\Shared\XMLWriter + * @var XMLWriter */ private $xmlWriter; @@ -60,7 +61,7 @@ public function __construct(XMLWriter $xmlWriter, $style = null) /** * Get XML Writer. * - * @return \PhpOffice\PhpWord\Shared\XMLWriter + * @return XMLWriter */ protected function getXmlWriter() { @@ -114,7 +115,7 @@ protected function writeChildStyle(XMLWriter $xmlWriter, $name, $value): void if ($value !== null) { $class = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Style\\' . $name; - /** @var \PhpOffice\PhpWord\Writer\Word2007\Style\AbstractStyle $writer */ + /** @var AbstractStyle $writer */ $writer = new $class($xmlWriter, $value); $writer->write(); } diff --git a/src/PhpWord/Writer/Word2007/Style/Cell.php b/src/PhpWord/Writer/Word2007/Style/Cell.php index 6e22597dd3..ea6fba6d7c 100644 --- a/src/PhpWord/Writer/Word2007/Style/Cell.php +++ b/src/PhpWord/Writer/Word2007/Style/Cell.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Extrusion.php b/src/PhpWord/Writer/Word2007/Style/Extrusion.php index f6ad622191..8bb9218789 100644 --- a/src/PhpWord/Writer/Word2007/Style/Extrusion.php +++ b/src/PhpWord/Writer/Word2007/Style/Extrusion.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Fill.php b/src/PhpWord/Writer/Word2007/Style/Fill.php index ec3800482f..8e21abe395 100644 --- a/src/PhpWord/Writer/Word2007/Style/Fill.php +++ b/src/PhpWord/Writer/Word2007/Style/Fill.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Font.php b/src/PhpWord/Writer/Word2007/Style/Font.php index 1f6db009e4..623e8d5e72 100644 --- a/src/PhpWord/Writer/Word2007/Style/Font.php +++ b/src/PhpWord/Writer/Word2007/Style/Font.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Frame.php b/src/PhpWord/Writer/Word2007/Style/Frame.php index 0ba52ec5ab..a7aab43e61 100644 --- a/src/PhpWord/Writer/Word2007/Style/Frame.php +++ b/src/PhpWord/Writer/Word2007/Style/Frame.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Image.php b/src/PhpWord/Writer/Word2007/Style/Image.php index 18d924fd3d..a2279e5b9c 100644 --- a/src/PhpWord/Writer/Word2007/Style/Image.php +++ b/src/PhpWord/Writer/Word2007/Style/Image.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Indentation.php b/src/PhpWord/Writer/Word2007/Style/Indentation.php index 63ffb6323a..85880d4c22 100644 --- a/src/PhpWord/Writer/Word2007/Style/Indentation.php +++ b/src/PhpWord/Writer/Word2007/Style/Indentation.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Line.php b/src/PhpWord/Writer/Word2007/Style/Line.php index 90107f8ea2..2603545fc2 100644 --- a/src/PhpWord/Writer/Word2007/Style/Line.php +++ b/src/PhpWord/Writer/Word2007/Style/Line.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/LineNumbering.php b/src/PhpWord/Writer/Word2007/Style/LineNumbering.php index 62e577a4d8..f915e3ab4e 100644 --- a/src/PhpWord/Writer/Word2007/Style/LineNumbering.php +++ b/src/PhpWord/Writer/Word2007/Style/LineNumbering.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/MarginBorder.php b/src/PhpWord/Writer/Word2007/Style/MarginBorder.php index ce250e54d4..b464e66ffb 100644 --- a/src/PhpWord/Writer/Word2007/Style/MarginBorder.php +++ b/src/PhpWord/Writer/Word2007/Style/MarginBorder.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Outline.php b/src/PhpWord/Writer/Word2007/Style/Outline.php index 63ea6dee78..45f37cc61e 100644 --- a/src/PhpWord/Writer/Word2007/Style/Outline.php +++ b/src/PhpWord/Writer/Word2007/Style/Outline.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Paragraph.php b/src/PhpWord/Writer/Word2007/Style/Paragraph.php index d4ec87a1ab..55f51a54d6 100644 --- a/src/PhpWord/Writer/Word2007/Style/Paragraph.php +++ b/src/PhpWord/Writer/Word2007/Style/Paragraph.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -147,7 +148,7 @@ private function writeStyle(): void /** * Write tabs. * - * @param \PhpOffice\PhpWord\Style\Tab[] $tabs + * @param Style\Tab[] $tabs */ private function writeTabs(XMLWriter $xmlWriter, $tabs): void { @@ -171,7 +172,7 @@ private function writeNumbering(XMLWriter $xmlWriter, $numbering): void $numStyle = $numbering['style']; $numLevel = $numbering['level']; - /** @var \PhpOffice\PhpWord\Style\Numbering $numbering */ + /** @var Style\Numbering $numbering */ $numbering = Style::getStyle($numStyle); if ($numStyle !== null && $numbering !== null) { $xmlWriter->startElement('w:numPr'); diff --git a/src/PhpWord/Writer/Word2007/Style/Row.php b/src/PhpWord/Writer/Word2007/Style/Row.php index 7e1468e87b..2b9d804f39 100644 --- a/src/PhpWord/Writer/Word2007/Style/Row.php +++ b/src/PhpWord/Writer/Word2007/Style/Row.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Section.php b/src/PhpWord/Writer/Word2007/Style/Section.php index 3bdeafa4ab..cb2c9a083a 100644 --- a/src/PhpWord/Writer/Word2007/Style/Section.php +++ b/src/PhpWord/Writer/Word2007/Style/Section.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Shading.php b/src/PhpWord/Writer/Word2007/Style/Shading.php index 97dbeeed0d..bf7476cdb1 100644 --- a/src/PhpWord/Writer/Word2007/Style/Shading.php +++ b/src/PhpWord/Writer/Word2007/Style/Shading.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Shadow.php b/src/PhpWord/Writer/Word2007/Style/Shadow.php index 85ddab3b89..33678155b0 100644 --- a/src/PhpWord/Writer/Word2007/Style/Shadow.php +++ b/src/PhpWord/Writer/Word2007/Style/Shadow.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Shape.php b/src/PhpWord/Writer/Word2007/Style/Shape.php index 6e2a880eaf..06082f1e71 100644 --- a/src/PhpWord/Writer/Word2007/Style/Shape.php +++ b/src/PhpWord/Writer/Word2007/Style/Shape.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Spacing.php b/src/PhpWord/Writer/Word2007/Style/Spacing.php index 3f4c632caa..6b99f5ac4b 100644 --- a/src/PhpWord/Writer/Word2007/Style/Spacing.php +++ b/src/PhpWord/Writer/Word2007/Style/Spacing.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Tab.php b/src/PhpWord/Writer/Word2007/Style/Tab.php index 8e7b3e3559..4a8da4045c 100644 --- a/src/PhpWord/Writer/Word2007/Style/Tab.php +++ b/src/PhpWord/Writer/Word2007/Style/Tab.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/Table.php b/src/PhpWord/Writer/Word2007/Style/Table.php index 05cec492ca..446fc3b1a4 100644 --- a/src/PhpWord/Writer/Word2007/Style/Table.php +++ b/src/PhpWord/Writer/Word2007/Style/Table.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/TablePosition.php b/src/PhpWord/Writer/Word2007/Style/TablePosition.php index f96bab58ba..71668032e5 100644 --- a/src/PhpWord/Writer/Word2007/Style/TablePosition.php +++ b/src/PhpWord/Writer/Word2007/Style/TablePosition.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/Word2007/Style/TextBox.php b/src/PhpWord/Writer/Word2007/Style/TextBox.php index d5ccf7a83b..2f8b5e9b3d 100644 --- a/src/PhpWord/Writer/Word2007/Style/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Style/TextBox.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/src/PhpWord/Writer/WriterInterface.php b/src/PhpWord/Writer/WriterInterface.php index f205eed019..86743e7bd2 100644 --- a/src/PhpWord/Writer/WriterInterface.php +++ b/src/PhpWord/Writer/WriterInterface.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/AbstractTestReader.php b/tests/PhpWordTests/AbstractTestReader.php index 121a213850..a51af6b96a 100644 --- a/tests/PhpWordTests/AbstractTestReader.php +++ b/tests/PhpWordTests/AbstractTestReader.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -36,7 +37,7 @@ abstract class AbstractTestReader extends \PHPUnit\Framework\TestCase /** * Builds a PhpWord instance based on the xml passed. * - * @return \PhpOffice\PhpWord\PhpWord + * @return PhpWord */ protected function getDocumentFromString(array $partXmls = []) { diff --git a/tests/PhpWordTests/AbstractWebServerEmbeddedTest.php b/tests/PhpWordTests/AbstractWebServerEmbedded.php similarity index 96% rename from tests/PhpWordTests/AbstractWebServerEmbeddedTest.php rename to tests/PhpWordTests/AbstractWebServerEmbedded.php index 38420b4462..fde7e1007c 100644 --- a/tests/PhpWordTests/AbstractWebServerEmbeddedTest.php +++ b/tests/PhpWordTests/AbstractWebServerEmbedded.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -19,7 +20,7 @@ use Symfony\Component\Process\Process; -abstract class AbstractWebServerEmbeddedTest extends \PHPUnit\Framework\TestCase +abstract class AbstractWebServerEmbedded extends \PHPUnit\Framework\TestCase { private static $httpServer; diff --git a/tests/PhpWordTests/Collection/CollectionTest.php b/tests/PhpWordTests/Collection/CollectionTest.php index 55425a333a..fe0b78d9b5 100644 --- a/tests/PhpWordTests/Collection/CollectionTest.php +++ b/tests/PhpWordTests/Collection/CollectionTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/ComplexType/FootnotePropertiesTest.php b/tests/PhpWordTests/ComplexType/FootnotePropertiesTest.php index 1c36545970..6472968d3b 100644 --- a/tests/PhpWordTests/ComplexType/FootnotePropertiesTest.php +++ b/tests/PhpWordTests/ComplexType/FootnotePropertiesTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/ComplexType/ProofStateTest.php b/tests/PhpWordTests/ComplexType/ProofStateTest.php index 360a47fda0..700e3f6d98 100644 --- a/tests/PhpWordTests/ComplexType/ProofStateTest.php +++ b/tests/PhpWordTests/ComplexType/ProofStateTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/AbstractElementTest.php b/tests/PhpWordTests/Element/AbstractElementTest.php index a059712b1a..8219871f73 100644 --- a/tests/PhpWordTests/Element/AbstractElementTest.php +++ b/tests/PhpWordTests/Element/AbstractElementTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/BookmarkTest.php b/tests/PhpWordTests/Element/BookmarkTest.php index efd89566c0..87abf971e5 100644 --- a/tests/PhpWordTests/Element/BookmarkTest.php +++ b/tests/PhpWordTests/Element/BookmarkTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/CellTest.php b/tests/PhpWordTests/Element/CellTest.php index 700e16d58e..919d627bfb 100644 --- a/tests/PhpWordTests/Element/CellTest.php +++ b/tests/PhpWordTests/Element/CellTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -19,14 +20,14 @@ use BadMethodCallException; use PhpOffice\PhpWord\Element\Cell; -use PhpOffice\PhpWordTests\AbstractWebServerEmbeddedTest; +use PhpOffice\PhpWordTests\AbstractWebServerEmbedded; /** * Test class for PhpOffice\PhpWord\Element\Cell. * * @runTestsInSeparateProcesses */ -class CellTest extends AbstractWebServerEmbeddedTest +class CellTest extends AbstractWebServerEmbedded { /** * New instance. diff --git a/tests/PhpWordTests/Element/CheckBoxTest.php b/tests/PhpWordTests/Element/CheckBoxTest.php index f7b780f025..761cfba649 100644 --- a/tests/PhpWordTests/Element/CheckBoxTest.php +++ b/tests/PhpWordTests/Element/CheckBoxTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/CommentTest.php b/tests/PhpWordTests/Element/CommentTest.php index b4d9cc6a5d..c887362cbc 100644 --- a/tests/PhpWordTests/Element/CommentTest.php +++ b/tests/PhpWordTests/Element/CommentTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/FieldTest.php b/tests/PhpWordTests/Element/FieldTest.php index 06f7c6841b..f3accf8789 100644 --- a/tests/PhpWordTests/Element/FieldTest.php +++ b/tests/PhpWordTests/Element/FieldTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/FooterTest.php b/tests/PhpWordTests/Element/FooterTest.php index 87a857b702..e167204f17 100644 --- a/tests/PhpWordTests/Element/FooterTest.php +++ b/tests/PhpWordTests/Element/FooterTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -18,14 +19,14 @@ namespace PhpOffice\PhpWordTests\Element; use PhpOffice\PhpWord\Element\Footer; -use PhpOffice\PhpWordTests\AbstractWebServerEmbeddedTest; +use PhpOffice\PhpWordTests\AbstractWebServerEmbedded; /** * Test class for PhpOffice\PhpWord\Element\Footer. * * @runTestsInSeparateProcesses */ -class FooterTest extends AbstractWebServerEmbeddedTest +class FooterTest extends AbstractWebServerEmbedded { /** * New instance. diff --git a/tests/PhpWordTests/Element/FootnoteTest.php b/tests/PhpWordTests/Element/FootnoteTest.php index a82bc1ec0e..cd64d6ddf0 100644 --- a/tests/PhpWordTests/Element/FootnoteTest.php +++ b/tests/PhpWordTests/Element/FootnoteTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/FormulaTest.php b/tests/PhpWordTests/Element/FormulaTest.php index 7e368e8995..0eb2805d0b 100644 --- a/tests/PhpWordTests/Element/FormulaTest.php +++ b/tests/PhpWordTests/Element/FormulaTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -20,14 +21,14 @@ use PhpOffice\Math\Element; use PhpOffice\Math\Math; use PhpOffice\PhpWord\Element\Formula; -use PhpOffice\PhpWordTests\AbstractWebServerEmbeddedTest; +use PhpOffice\PhpWordTests\AbstractWebServerEmbedded; /** * Test class for PhpOffice\PhpWord\Element\Formula. * * @runTestsInSeparateProcesses */ -class FormulaTest extends AbstractWebServerEmbeddedTest +class FormulaTest extends AbstractWebServerEmbedded { /** * @covers \PhpOffice\PhpWord\Element\Formula::__construct diff --git a/tests/PhpWordTests/Element/HeaderTest.php b/tests/PhpWordTests/Element/HeaderTest.php index 12bf5df3e2..24b7dd32f9 100644 --- a/tests/PhpWordTests/Element/HeaderTest.php +++ b/tests/PhpWordTests/Element/HeaderTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -19,14 +20,14 @@ use BadMethodCallException; use PhpOffice\PhpWord\Element\Header; -use PhpOffice\PhpWordTests\AbstractWebServerEmbeddedTest; +use PhpOffice\PhpWordTests\AbstractWebServerEmbedded; /** * Test class for PhpOffice\PhpWord\Element\Header. * * @runTestsInSeparateProcesses */ -class HeaderTest extends AbstractWebServerEmbeddedTest +class HeaderTest extends AbstractWebServerEmbedded { /** * New instance. diff --git a/tests/PhpWordTests/Element/ImageTest.php b/tests/PhpWordTests/Element/ImageTest.php index 725331a2df..86b6b77c58 100644 --- a/tests/PhpWordTests/Element/ImageTest.php +++ b/tests/PhpWordTests/Element/ImageTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -19,12 +20,12 @@ use PhpOffice\PhpWord\Element\Image; use PhpOffice\PhpWord\SimpleType\Jc; -use PhpOffice\PhpWordTests\AbstractWebServerEmbeddedTest; +use PhpOffice\PhpWordTests\AbstractWebServerEmbedded; /** * Test class for PhpOffice\PhpWord\Element\Image. */ -class ImageTest extends AbstractWebServerEmbeddedTest +class ImageTest extends AbstractWebServerEmbedded { /** * New instance. @@ -68,7 +69,7 @@ public function testConstructWithStyle(): void */ public function testImages($source, $type, $extension, $createFunction, $imageFunction, $imageQuality): void { - $nam = ucfirst(strtok($source, '.')); + $nam = ucfirst((string) strtok($source, '.')); $source = __DIR__ . "/../_files/images/{$source}"; $image = new Image($source, null, null, $nam); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $image); @@ -205,7 +206,7 @@ public function testConstructFromString(): void $image = new Image($source); self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $image); self::assertEquals($source, $image->getSource()); - self::assertEquals(md5($source), $image->getMediaId()); + self::assertEquals(md5((string) $source), $image->getMediaId()); self::assertEquals('image/jpeg', $image->getImageType()); self::assertEquals('jpg', $image->getImageExtension()); self::assertEquals('imagecreatefromstring', $image->getImageCreateFunction()); diff --git a/tests/PhpWordTests/Element/LineTest.php b/tests/PhpWordTests/Element/LineTest.php index 101c7309fb..98298fc76c 100644 --- a/tests/PhpWordTests/Element/LineTest.php +++ b/tests/PhpWordTests/Element/LineTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/LinkTest.php b/tests/PhpWordTests/Element/LinkTest.php index fd6bfc701a..6a87b308c1 100644 --- a/tests/PhpWordTests/Element/LinkTest.php +++ b/tests/PhpWordTests/Element/LinkTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/ListItemRunTest.php b/tests/PhpWordTests/Element/ListItemRunTest.php index f22c171018..633b8c3e26 100644 --- a/tests/PhpWordTests/Element/ListItemRunTest.php +++ b/tests/PhpWordTests/Element/ListItemRunTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/ListItemTest.php b/tests/PhpWordTests/Element/ListItemTest.php index 704f4fef2a..3da9a8d101 100644 --- a/tests/PhpWordTests/Element/ListItemTest.php +++ b/tests/PhpWordTests/Element/ListItemTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/ObjectTest.php b/tests/PhpWordTests/Element/ObjectTest.php index 21bb2ceff1..8ad856732b 100644 --- a/tests/PhpWordTests/Element/ObjectTest.php +++ b/tests/PhpWordTests/Element/ObjectTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/PageBreakTest.php b/tests/PhpWordTests/Element/PageBreakTest.php index c4789b278c..13cfb937d3 100644 --- a/tests/PhpWordTests/Element/PageBreakTest.php +++ b/tests/PhpWordTests/Element/PageBreakTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/PreserveTextTest.php b/tests/PhpWordTests/Element/PreserveTextTest.php index de510bdf7d..98d133c45d 100644 --- a/tests/PhpWordTests/Element/PreserveTextTest.php +++ b/tests/PhpWordTests/Element/PreserveTextTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/RowTest.php b/tests/PhpWordTests/Element/RowTest.php index 28c6681bb3..c2881acbc2 100644 --- a/tests/PhpWordTests/Element/RowTest.php +++ b/tests/PhpWordTests/Element/RowTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/SDTTest.php b/tests/PhpWordTests/Element/SDTTest.php index b33dde141b..505ef14fe4 100644 --- a/tests/PhpWordTests/Element/SDTTest.php +++ b/tests/PhpWordTests/Element/SDTTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/SectionTest.php b/tests/PhpWordTests/Element/SectionTest.php index f978188349..bf38a33300 100644 --- a/tests/PhpWordTests/Element/SectionTest.php +++ b/tests/PhpWordTests/Element/SectionTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/TOCTest.php b/tests/PhpWordTests/Element/TOCTest.php index ad2f61f7ae..3770823f5f 100644 --- a/tests/PhpWordTests/Element/TOCTest.php +++ b/tests/PhpWordTests/Element/TOCTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/TableTest.php b/tests/PhpWordTests/Element/TableTest.php index 6ce0739ba2..8e941cd056 100644 --- a/tests/PhpWordTests/Element/TableTest.php +++ b/tests/PhpWordTests/Element/TableTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/TextBoxTest.php b/tests/PhpWordTests/Element/TextBoxTest.php index 30d684ac87..6305b4e7ed 100644 --- a/tests/PhpWordTests/Element/TextBoxTest.php +++ b/tests/PhpWordTests/Element/TextBoxTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/TextBreakTest.php b/tests/PhpWordTests/Element/TextBreakTest.php index 5cdea5adec..10ca058180 100644 --- a/tests/PhpWordTests/Element/TextBreakTest.php +++ b/tests/PhpWordTests/Element/TextBreakTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/TextRunTest.php b/tests/PhpWordTests/Element/TextRunTest.php index d1318199f9..8d250676f4 100644 --- a/tests/PhpWordTests/Element/TextRunTest.php +++ b/tests/PhpWordTests/Element/TextRunTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/TextTest.php b/tests/PhpWordTests/Element/TextTest.php index f2e2066eeb..ee3c67edd9 100644 --- a/tests/PhpWordTests/Element/TextTest.php +++ b/tests/PhpWordTests/Element/TextTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/TitleTest.php b/tests/PhpWordTests/Element/TitleTest.php index e48a163721..2663189dd6 100644 --- a/tests/PhpWordTests/Element/TitleTest.php +++ b/tests/PhpWordTests/Element/TitleTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Element/TrackChangeTest.php b/tests/PhpWordTests/Element/TrackChangeTest.php index de5585b5e5..bf2e1dea1c 100644 --- a/tests/PhpWordTests/Element/TrackChangeTest.php +++ b/tests/PhpWordTests/Element/TrackChangeTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Escaper/RtfEscaper2Test.php b/tests/PhpWordTests/Escaper/RtfEscaper2Test.php index e303641856..d65b543f21 100644 --- a/tests/PhpWordTests/Escaper/RtfEscaper2Test.php +++ b/tests/PhpWordTests/Escaper/RtfEscaper2Test.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Escaper/RtfEscaper3Test.php b/tests/PhpWordTests/Escaper/RtfEscaper3Test.php index 6bbc089a2a..1aebea52f0 100644 --- a/tests/PhpWordTests/Escaper/RtfEscaper3Test.php +++ b/tests/PhpWordTests/Escaper/RtfEscaper3Test.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -35,7 +36,7 @@ protected function tearDown(): void public function escapestring(string $str): string { - \PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(true); + Settings::setOutputEscapingEnabled(true); $parentWriter = new \PhpOffice\PhpWord\Writer\RTF(); $element = new \PhpOffice\PhpWord\Element\Text($str); $txt = new \PhpOffice\PhpWord\Writer\RTF\Element\Text($parentWriter, $element); diff --git a/tests/PhpWordTests/Exception/CopyFileExceptionTest.php b/tests/PhpWordTests/Exception/CopyFileExceptionTest.php index a4574b6be1..a11ac79afa 100644 --- a/tests/PhpWordTests/Exception/CopyFileExceptionTest.php +++ b/tests/PhpWordTests/Exception/CopyFileExceptionTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -33,7 +34,7 @@ class CopyFileExceptionTest extends \PHPUnit\Framework\TestCase */ public function testCopyFileExceptionCanBeThrown(): void { - $this->expectException(\PhpOffice\PhpWord\Exception\CopyFileException::class); + $this->expectException(CopyFileException::class); throw new CopyFileException('C:\source\dummy.txt', 'C:\destination\dummy.txt'); } diff --git a/tests/PhpWordTests/Exception/CreateTemporaryFileExceptionTest.php b/tests/PhpWordTests/Exception/CreateTemporaryFileExceptionTest.php index 834a1c09fc..dd8f395318 100644 --- a/tests/PhpWordTests/Exception/CreateTemporaryFileExceptionTest.php +++ b/tests/PhpWordTests/Exception/CreateTemporaryFileExceptionTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -33,7 +34,7 @@ class CreateTemporaryFileExceptionTest extends \PHPUnit\Framework\TestCase */ public function testCreateTemporaryFileExceptionCanBeThrown(): void { - $this->expectException(\PhpOffice\PhpWord\Exception\CreateTemporaryFileException::class); + $this->expectException(CreateTemporaryFileException::class); throw new CreateTemporaryFileException(); } diff --git a/tests/PhpWordTests/Exception/ExceptionTest.php b/tests/PhpWordTests/Exception/ExceptionTest.php index e186e94fad..09ee933c86 100644 --- a/tests/PhpWordTests/Exception/ExceptionTest.php +++ b/tests/PhpWordTests/Exception/ExceptionTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Exception/InvalidImageExceptionTest.php b/tests/PhpWordTests/Exception/InvalidImageExceptionTest.php index d3cb57578e..dea167bb25 100644 --- a/tests/PhpWordTests/Exception/InvalidImageExceptionTest.php +++ b/tests/PhpWordTests/Exception/InvalidImageExceptionTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -35,7 +36,7 @@ class InvalidImageExceptionTest extends \PHPUnit\Framework\TestCase */ public function testThrowException(): void { - $this->expectException(\PhpOffice\PhpWord\Exception\InvalidImageException::class); + $this->expectException(InvalidImageException::class); throw new InvalidImageException(); } diff --git a/tests/PhpWordTests/Exception/InvalidStyleExceptionTest.php b/tests/PhpWordTests/Exception/InvalidStyleExceptionTest.php index d1da3b2a85..7f2a1650e4 100644 --- a/tests/PhpWordTests/Exception/InvalidStyleExceptionTest.php +++ b/tests/PhpWordTests/Exception/InvalidStyleExceptionTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -35,7 +36,7 @@ class InvalidStyleExceptionTest extends \PHPUnit\Framework\TestCase */ public function testThrowException(): void { - $this->expectException(\PhpOffice\PhpWord\Exception\InvalidStyleException::class); + $this->expectException(InvalidStyleException::class); throw new InvalidStyleException(); } diff --git a/tests/PhpWordTests/Exception/UnsupportedImageTypeExceptionTest.php b/tests/PhpWordTests/Exception/UnsupportedImageTypeExceptionTest.php index e978b97254..2252b874ef 100644 --- a/tests/PhpWordTests/Exception/UnsupportedImageTypeExceptionTest.php +++ b/tests/PhpWordTests/Exception/UnsupportedImageTypeExceptionTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -33,7 +34,7 @@ class UnsupportedImageTypeExceptionTest extends \PHPUnit\Framework\TestCase */ public function testThrowException(): void { - $this->expectException(\PhpOffice\PhpWord\Exception\UnsupportedImageTypeException::class); + $this->expectException(UnsupportedImageTypeException::class); throw new UnsupportedImageTypeException(); } diff --git a/tests/PhpWordTests/IOFactoryTest.php b/tests/PhpWordTests/IOFactoryTest.php index 79f0fd0c76..6a8d746bd0 100644 --- a/tests/PhpWordTests/IOFactoryTest.php +++ b/tests/PhpWordTests/IOFactoryTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/MediaTest.php b/tests/PhpWordTests/MediaTest.php index fe17680c81..2eb60a858b 100644 --- a/tests/PhpWordTests/MediaTest.php +++ b/tests/PhpWordTests/MediaTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -26,7 +27,7 @@ * * @runTestsInSeparateProcesses */ -class MediaTest extends AbstractWebServerEmbeddedTest +class MediaTest extends AbstractWebServerEmbedded { /** * Get section media elements. diff --git a/tests/PhpWordTests/Metadata/DocInfoTest.php b/tests/PhpWordTests/Metadata/DocInfoTest.php index a4d34f3e13..d5c9eb5124 100644 --- a/tests/PhpWordTests/Metadata/DocInfoTest.php +++ b/tests/PhpWordTests/Metadata/DocInfoTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Metadata/SettingsTest.php b/tests/PhpWordTests/Metadata/SettingsTest.php index 14f19f318d..c7f165db28 100644 --- a/tests/PhpWordTests/Metadata/SettingsTest.php +++ b/tests/PhpWordTests/Metadata/SettingsTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/PhpWordTest.php b/tests/PhpWordTests/PhpWordTest.php index 33118a11e8..9ad7b02574 100644 --- a/tests/PhpWordTests/PhpWordTest.php +++ b/tests/PhpWordTests/PhpWordTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Reader/HTMLTest.php b/tests/PhpWordTests/Reader/HTMLTest.php index f091e5a275..7a35a06f78 100644 --- a/tests/PhpWordTests/Reader/HTMLTest.php +++ b/tests/PhpWordTests/Reader/HTMLTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Reader/MsDocTest.php b/tests/PhpWordTests/Reader/MsDocTest.php index b243fccfee..3552271823 100644 --- a/tests/PhpWordTests/Reader/MsDocTest.php +++ b/tests/PhpWordTests/Reader/MsDocTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Reader/ODText/ODTextSectionTest.php b/tests/PhpWordTests/Reader/ODText/ODTextSectionTest.php index 0a1a4512db..8567dbcbea 100644 --- a/tests/PhpWordTests/Reader/ODText/ODTextSectionTest.php +++ b/tests/PhpWordTests/Reader/ODText/ODTextSectionTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Reader/ODTextTest.php b/tests/PhpWordTests/Reader/ODTextTest.php index 20c5916c7d..c05705a439 100644 --- a/tests/PhpWordTests/Reader/ODTextTest.php +++ b/tests/PhpWordTests/Reader/ODTextTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Reader/RTFTest.php b/tests/PhpWordTests/Reader/RTFTest.php index a1054ab283..a8f472571b 100644 --- a/tests/PhpWordTests/Reader/RTFTest.php +++ b/tests/PhpWordTests/Reader/RTFTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Reader/Word2007/ElementTest.php b/tests/PhpWordTests/Reader/Word2007/ElementTest.php index 3685cbea03..b27fc9df1d 100644 --- a/tests/PhpWordTests/Reader/Word2007/ElementTest.php +++ b/tests/PhpWordTests/Reader/Word2007/ElementTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -195,13 +196,13 @@ public function testReadTrackChange(): void self::assertEquals('two', $textRun->getElement(1)->getText()); self::assertNotNull($textRun->getElement(1)->getTrackChange()); - /** @var \PhpOffice\PhpWord\Element\TrackChange $trackChange */ + /** @var TrackChange $trackChange */ $trackChange = $textRun->getElement(1)->getTrackChange(); self::assertEquals(TrackChange::DELETED, $trackChange->getChangeType()); self::assertEquals('three', $textRun->getElement(2)->getText()); self::assertNotNull($textRun->getElement(2)->getTrackChange()); - /** @var \PhpOffice\PhpWord\Element\TrackChange $trackChange */ + /** @var TrackChange $trackChange */ $trackChange = $textRun->getElement(2)->getTrackChange(); self::assertEquals(TrackChange::INSERTED, $trackChange->getChangeType()); } diff --git a/tests/PhpWordTests/Reader/Word2007/PartTest.php b/tests/PhpWordTests/Reader/Word2007/PartTest.php index 46089e8f02..4f19f8b91f 100644 --- a/tests/PhpWordTests/Reader/Word2007/PartTest.php +++ b/tests/PhpWordTests/Reader/Word2007/PartTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Reader/Word2007/StyleTest.php b/tests/PhpWordTests/Reader/Word2007/StyleTest.php index f622c57e90..006e6ff01f 100644 --- a/tests/PhpWordTests/Reader/Word2007/StyleTest.php +++ b/tests/PhpWordTests/Reader/Word2007/StyleTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -67,7 +68,7 @@ public function testReadTablePosition(): void self::assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); self::assertNotNull($elements[0]->getStyle()->getPosition()); self::assertInstanceOf('PhpOffice\PhpWord\Style\TablePosition', $elements[0]->getStyle()->getPosition()); - /** @var \PhpOffice\PhpWord\Style\TablePosition $tableStyle */ + /** @var TablePosition $tableStyle */ $tableStyle = $elements[0]->getStyle()->getPosition(); self::assertEquals(10, $tableStyle->getLeftFromText()); self::assertEquals(20, $tableStyle->getRightFromText()); @@ -118,7 +119,7 @@ public function testReadTableCellSpacing(): void $elements = $phpWord->getSection(0)->getElements(); self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); self::assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); - /** @var \PhpOffice\PhpWord\Style\Table $tableStyle */ + /** @var Table $tableStyle */ $tableStyle = $elements[0]->getStyle(); self::assertEquals(TblWidth::AUTO, $tableStyle->getUnit()); self::assertEquals(10.5, $tableStyle->getCellSpacing()); @@ -225,7 +226,7 @@ public function testReadPosition(): void self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $textRun); self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(0)); self::assertInstanceOf('PhpOffice\PhpWord\Style\Font', $textRun->getElement(0)->getFontStyle()); - /** @var \PhpOffice\PhpWord\Style\Font $fontStyle */ + /** @var Style\Font $fontStyle */ $fontStyle = $textRun->getElement(0)->getFontStyle(); self::assertEquals(15, $fontStyle->getPosition()); } @@ -243,7 +244,7 @@ public function testReadIndent(): void $elements = $phpWord->getSection(0)->getElements(); self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); self::assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); - /** @var \PhpOffice\PhpWord\Style\Table $tableStyle */ + /** @var Table $tableStyle */ $tableStyle = $elements[0]->getStyle(); self::assertSame(TblWidth::TWIP, $tableStyle->getIndent()->getType()); self::assertSame(2160, $tableStyle->getIndent()->getValue()); @@ -262,7 +263,7 @@ public function testReadTableRTL(): void $elements = $phpWord->getSection(0)->getElements(); self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); self::assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); - /** @var \PhpOffice\PhpWord\Style\Table $tableStyle */ + /** @var Table $tableStyle */ $tableStyle = $elements[0]->getStyle(); self::assertTrue($tableStyle->isBidiVisual()); } @@ -286,7 +287,7 @@ public function testReadHidden(): void self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $textRun); self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(0)); self::assertInstanceOf('PhpOffice\PhpWord\Style\Font', $textRun->getElement(0)->getFontStyle()); - /** @var \PhpOffice\PhpWord\Style\Font $fontStyle */ + /** @var Style\Font $fontStyle */ $fontStyle = $textRun->getElement(0)->getFontStyle(); self::assertTrue($fontStyle->isHidden()); } diff --git a/tests/PhpWordTests/Reader/Word2007Test.php b/tests/PhpWordTests/Reader/Word2007Test.php index ebfd8ad7a2..65c8a4a71b 100644 --- a/tests/PhpWordTests/Reader/Word2007Test.php +++ b/tests/PhpWordTests/Reader/Word2007Test.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -92,30 +93,30 @@ public function testLoadStyles(): void $section2 = $phpWord->getSection(2); self::assertInstanceOf(Section::class, $section2); - $element2_31 = $section2->getElement(31); - self::assertInstanceOf(TextRun::class, $element2_31); - self::assertEquals('This is a paragraph with border differents', $element2_31->getText()); + $element2e31 = $section2->getElement(31); + self::assertInstanceOf(TextRun::class, $element2e31); + self::assertEquals('This is a paragraph with border differents', $element2e31->getText()); - /** @var Paragraph $element2_31_pStyle */ - $element2_31_pStyle = $element2_31->getParagraphStyle(); - self::assertInstanceOf(Paragraph::class, $element2_31_pStyle); + /** @var Paragraph $element2e31pStyle */ + $element2e31pStyle = $element2e31->getParagraphStyle(); + self::assertInstanceOf(Paragraph::class, $element2e31pStyle); // Top - self::assertEquals('FFFF00', $element2_31_pStyle->getBorderTopColor()); - self::assertEquals('10', $element2_31_pStyle->getBorderTopSize()); - self::assertEquals('dotted', $element2_31_pStyle->getBorderTopStyle()); + self::assertEquals('FFFF00', $element2e31pStyle->getBorderTopColor()); + self::assertEquals('10', $element2e31pStyle->getBorderTopSize()); + self::assertEquals('dotted', $element2e31pStyle->getBorderTopStyle()); // Right - self::assertEquals('00A933', $element2_31_pStyle->getBorderRightColor()); - self::assertEquals('4', $element2_31_pStyle->getBorderRightSize()); - self::assertEquals('dashed', $element2_31_pStyle->getBorderRightStyle()); + self::assertEquals('00A933', $element2e31pStyle->getBorderRightColor()); + self::assertEquals('4', $element2e31pStyle->getBorderRightSize()); + self::assertEquals('dashed', $element2e31pStyle->getBorderRightStyle()); // Bottom - self::assertEquals('F10D0C', $element2_31_pStyle->getBorderBottomColor()); - self::assertEquals('8', $element2_31_pStyle->getBorderBottomSize()); - self::assertEquals('dashSmallGap', $element2_31_pStyle->getBorderBottomStyle()); + self::assertEquals('F10D0C', $element2e31pStyle->getBorderBottomColor()); + self::assertEquals('8', $element2e31pStyle->getBorderBottomSize()); + self::assertEquals('dashSmallGap', $element2e31pStyle->getBorderBottomStyle()); // Left - self::assertEquals('3465A4', $element2_31_pStyle->getBorderLeftColor()); - self::assertEquals('8', $element2_31_pStyle->getBorderLeftSize()); - self::assertEquals('dashed', $element2_31_pStyle->getBorderLeftStyle()); + self::assertEquals('3465A4', $element2e31pStyle->getBorderLeftColor()); + self::assertEquals('8', $element2e31pStyle->getBorderLeftSize()); + self::assertEquals('dashed', $element2e31pStyle->getBorderLeftStyle()); } /** @@ -162,7 +163,7 @@ public function testLoadWord2011SettingsImageLoading(bool $hasImageLoading): voi } } - public function providerSettingsImageLoading(): iterable + public static function providerSettingsImageLoading(): iterable { return [ [true], diff --git a/tests/PhpWordTests/SettingsTest.php b/tests/PhpWordTests/SettingsTest.php index 46c72eab28..67099650aa 100644 --- a/tests/PhpWordTests/SettingsTest.php +++ b/tests/PhpWordTests/SettingsTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Shared/ConverterTest.php b/tests/PhpWordTests/Shared/ConverterTest.php index 95981210ec..36ba797aeb 100644 --- a/tests/PhpWordTests/Shared/ConverterTest.php +++ b/tests/PhpWordTests/Shared/ConverterTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Shared/CssTest.php b/tests/PhpWordTests/Shared/CssTest.php index 402e953611..6c2eb5ccfd 100644 --- a/tests/PhpWordTests/Shared/CssTest.php +++ b/tests/PhpWordTests/Shared/CssTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Shared/DrawingTest.php b/tests/PhpWordTests/Shared/DrawingTest.php index 6e2cb707a3..dbaa42a686 100644 --- a/tests/PhpWordTests/Shared/DrawingTest.php +++ b/tests/PhpWordTests/Shared/DrawingTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Shared/HtmlTest.php b/tests/PhpWordTests/Shared/HtmlTest.php index 2d39701cd1..e6a0bd4953 100644 --- a/tests/PhpWordTests/Shared/HtmlTest.php +++ b/tests/PhpWordTests/Shared/HtmlTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -25,7 +26,7 @@ use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\SimpleType\LineSpacingRule; use PhpOffice\PhpWord\Style\Paragraph; -use PhpOffice\PhpWordTests\AbstractWebServerEmbeddedTest; +use PhpOffice\PhpWordTests\AbstractWebServerEmbedded; use PhpOffice\PhpWordTests\TestHelperDOCX; /** @@ -33,7 +34,7 @@ * * @coversDefaultClass \PhpOffice\PhpWord\Shared\Html */ -class HtmlTest extends AbstractWebServerEmbeddedTest +class HtmlTest extends AbstractWebServerEmbedded { /** * Tear down after each test. @@ -986,7 +987,7 @@ public function testParseLink2(): void public function testParseLinkAllowsAbsenceOfHref(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $section = $phpWord->addSection(); $html = '<p><a>text of href-less link</a></p>'; Html::addHtml($section, $html); @@ -995,7 +996,7 @@ public function testParseLinkAllowsAbsenceOfHref(): void self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:hyperlink')); self::assertEquals('text of href-less link', $doc->getElement('/w:document/w:body/w:p/w:hyperlink/w:r/w:t')->nodeValue); - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $section = $phpWord->addSection(); $html = '<p><a href="">text of empty-href link</a></p>'; Html::addHtml($section, $html); diff --git a/tests/PhpWordTests/Shared/Microsoft/PasswordEncoderTest.php b/tests/PhpWordTests/Shared/Microsoft/PasswordEncoderTest.php index 9389c97411..d3c13bf8b4 100644 --- a/tests/PhpWordTests/Shared/Microsoft/PasswordEncoderTest.php +++ b/tests/PhpWordTests/Shared/Microsoft/PasswordEncoderTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Shared/TextTest.php b/tests/PhpWordTests/Shared/TextTest.php index ee49573722..1a9c1a7cab 100644 --- a/tests/PhpWordTests/Shared/TextTest.php +++ b/tests/PhpWordTests/Shared/TextTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Shared/ValidateTest.php b/tests/PhpWordTests/Shared/ValidateTest.php index b736427150..abaff878e7 100644 --- a/tests/PhpWordTests/Shared/ValidateTest.php +++ b/tests/PhpWordTests/Shared/ValidateTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Shared/XMLReaderTest.php b/tests/PhpWordTests/Shared/XMLReaderTest.php index cc15c85f01..212f20e1ba 100644 --- a/tests/PhpWordTests/Shared/XMLReaderTest.php +++ b/tests/PhpWordTests/Shared/XMLReaderTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Shared/XMLWriterTest.php b/tests/PhpWordTests/Shared/XMLWriterTest.php index ccb07c1a3d..476b8b3ba9 100644 --- a/tests/PhpWordTests/Shared/XMLWriterTest.php +++ b/tests/PhpWordTests/Shared/XMLWriterTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Shared/ZipArchiveTest.php b/tests/PhpWordTests/Shared/ZipArchiveTest.php index 41da9ae59d..3f998c26ef 100644 --- a/tests/PhpWordTests/Shared/ZipArchiveTest.php +++ b/tests/PhpWordTests/Shared/ZipArchiveTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -62,8 +63,6 @@ class ZipArchiveTest extends \PHPUnit\Framework\TestCase * Test all methods. * * @param string $zipClass - * - * @covers ::<public> */ public function testZipArchive($zipClass = 'ZipArchive'): void { @@ -107,8 +106,6 @@ public function testZipArchive($zipClass = 'ZipArchive'): void /** * Test PclZip. - * - * @covers ::<public> */ public function testPCLZip(): void { diff --git a/tests/PhpWordTests/Style/AbstractStyleTest.php b/tests/PhpWordTests/Style/AbstractStyleTest.php index 47c265738a..2f1585fd5a 100644 --- a/tests/PhpWordTests/Style/AbstractStyleTest.php +++ b/tests/PhpWordTests/Style/AbstractStyleTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/CellTest.php b/tests/PhpWordTests/Style/CellTest.php index d1874d2288..cd4ae7f85b 100644 --- a/tests/PhpWordTests/Style/CellTest.php +++ b/tests/PhpWordTests/Style/CellTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/ChartTest.php b/tests/PhpWordTests/Style/ChartTest.php index c756362fbd..cece336e0f 100644 --- a/tests/PhpWordTests/Style/ChartTest.php +++ b/tests/PhpWordTests/Style/ChartTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/FontTest.php b/tests/PhpWordTests/Style/FontTest.php index d2dba6b73e..4ba6a762f3 100644 --- a/tests/PhpWordTests/Style/FontTest.php +++ b/tests/PhpWordTests/Style/FontTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/ImageTest.php b/tests/PhpWordTests/Style/ImageTest.php index 49c737572f..1223069c67 100644 --- a/tests/PhpWordTests/Style/ImageTest.php +++ b/tests/PhpWordTests/Style/ImageTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -71,11 +72,11 @@ public function testSetStyleValue(): void 'marginTop' => 240, 'marginLeft' => 240, 'position' => 10, - 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_ABSOLUTE, - 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_CENTER, - 'posVertical' => \PhpOffice\PhpWord\Style\Image::POSITION_VERTICAL_TOP, - 'posHorizontalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_COLUMN, - 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_IMARGIN, + 'positioning' => Image::POSITION_ABSOLUTE, + 'posHorizontal' => Image::POSITION_HORIZONTAL_CENTER, + 'posVertical' => Image::POSITION_VERTICAL_TOP, + 'posHorizontalRel' => Image::POSITION_RELATIVE_TO_COLUMN, + 'posVerticalRel' => Image::POSITION_RELATIVE_TO_IMARGIN, 'wrapDistanceLeft' => 10, 'wrapDistanceRight' => 20, 'wrapDistanceTop' => 30, diff --git a/tests/PhpWordTests/Style/IndentationTest.php b/tests/PhpWordTests/Style/IndentationTest.php index 4de664477a..db13407ff3 100644 --- a/tests/PhpWordTests/Style/IndentationTest.php +++ b/tests/PhpWordTests/Style/IndentationTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/LanguageTest.php b/tests/PhpWordTests/Style/LanguageTest.php index a19546fd02..e6b6d1630a 100644 --- a/tests/PhpWordTests/Style/LanguageTest.php +++ b/tests/PhpWordTests/Style/LanguageTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/LineNumberingTest.php b/tests/PhpWordTests/Style/LineNumberingTest.php index bef754bc65..d91e7ccfbc 100644 --- a/tests/PhpWordTests/Style/LineNumberingTest.php +++ b/tests/PhpWordTests/Style/LineNumberingTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/LineTest.php b/tests/PhpWordTests/Style/LineTest.php index 5ace86750e..3e4db2438f 100644 --- a/tests/PhpWordTests/Style/LineTest.php +++ b/tests/PhpWordTests/Style/LineTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -36,10 +37,10 @@ public function testSetGetNormal(): void $object = new Line(); $properties = [ - 'connectorType' => \PhpOffice\PhpWord\Style\Line::CONNECTOR_TYPE_STRAIGHT, - 'beginArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_BLOCK, - 'endArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_OVAL, - 'dash' => \PhpOffice\PhpWord\Style\Line::DASH_STYLE_LONG_DASH_DOT_DOT, + 'connectorType' => Line::CONNECTOR_TYPE_STRAIGHT, + 'beginArrow' => Line::ARROW_STYLE_BLOCK, + 'endArrow' => Line::ARROW_STYLE_OVAL, + 'dash' => Line::DASH_STYLE_LONG_DASH_DOT_DOT, 'weight' => 10, 'color' => 'red', ]; @@ -59,10 +60,10 @@ public function testSetStyleValue(): void $object = new Line(); $properties = [ - 'connectorType' => \PhpOffice\PhpWord\Style\Line::CONNECTOR_TYPE_STRAIGHT, - 'beginArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_BLOCK, - 'endArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_OVAL, - 'dash' => \PhpOffice\PhpWord\Style\Line::DASH_STYLE_LONG_DASH_DOT_DOT, + 'connectorType' => Line::CONNECTOR_TYPE_STRAIGHT, + 'beginArrow' => Line::ARROW_STYLE_BLOCK, + 'endArrow' => Line::ARROW_STYLE_OVAL, + 'dash' => Line::DASH_STYLE_LONG_DASH_DOT_DOT, 'weight' => 10, 'color' => 'red', ]; @@ -89,7 +90,7 @@ public function testSetGetFlip(): void */ public function testSetGetConnectorType(): void { - $expected = \PhpOffice\PhpWord\Style\Line::CONNECTOR_TYPE_STRAIGHT; + $expected = Line::CONNECTOR_TYPE_STRAIGHT; $object = new Line(); $object->setConnectorType($expected); self::assertEquals($expected, $object->getConnectorType()); @@ -122,7 +123,7 @@ public function testSetGetColor(): void */ public function testSetGetDash(): void { - $expected = \PhpOffice\PhpWord\Style\Line::DASH_STYLE_LONG_DASH_DOT_DOT; + $expected = Line::DASH_STYLE_LONG_DASH_DOT_DOT; $object = new Line(); $object->setDash($expected); self::assertEquals($expected, $object->getDash()); @@ -133,7 +134,7 @@ public function testSetGetDash(): void */ public function testSetGetBeginArrow(): void { - $expected = \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_BLOCK; + $expected = Line::ARROW_STYLE_BLOCK; $object = new Line(); $object->setBeginArrow($expected); self::assertEquals($expected, $object->getBeginArrow()); @@ -144,7 +145,7 @@ public function testSetGetBeginArrow(): void */ public function testSetGetEndArrow(): void { - $expected = \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_CLASSIC; + $expected = Line::ARROW_STYLE_CLASSIC; $object = new Line(); $object->setEndArrow($expected); self::assertEquals($expected, $object->getEndArrow()); diff --git a/tests/PhpWordTests/Style/ListItemTest.php b/tests/PhpWordTests/Style/ListItemTest.php index bc1ad67014..59cdfeeda1 100644 --- a/tests/PhpWordTests/Style/ListItemTest.php +++ b/tests/PhpWordTests/Style/ListItemTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/NumberingLevelTest.php b/tests/PhpWordTests/Style/NumberingLevelTest.php index 5459e88412..07721408bf 100644 --- a/tests/PhpWordTests/Style/NumberingLevelTest.php +++ b/tests/PhpWordTests/Style/NumberingLevelTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/NumberingTest.php b/tests/PhpWordTests/Style/NumberingTest.php index 0c2c5280eb..ce39509d0b 100644 --- a/tests/PhpWordTests/Style/NumberingTest.php +++ b/tests/PhpWordTests/Style/NumberingTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/PaperTest.php b/tests/PhpWordTests/Style/PaperTest.php index 89890795f0..ea5a4fb674 100644 --- a/tests/PhpWordTests/Style/PaperTest.php +++ b/tests/PhpWordTests/Style/PaperTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/ParagraphTest.php b/tests/PhpWordTests/Style/ParagraphTest.php index 3f44c8eb2d..f99107a93b 100644 --- a/tests/PhpWordTests/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Style/ParagraphTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/RowTest.php b/tests/PhpWordTests/Style/RowTest.php index 6a53b9e25d..688a6b7b35 100644 --- a/tests/PhpWordTests/Style/RowTest.php +++ b/tests/PhpWordTests/Style/RowTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/SectionTest.php b/tests/PhpWordTests/Style/SectionTest.php index 24efcb919c..e03dbb7596 100644 --- a/tests/PhpWordTests/Style/SectionTest.php +++ b/tests/PhpWordTests/Style/SectionTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/ShadingTest.php b/tests/PhpWordTests/Style/ShadingTest.php index 950cab4596..a5fc7a89dd 100644 --- a/tests/PhpWordTests/Style/ShadingTest.php +++ b/tests/PhpWordTests/Style/ShadingTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/SpacingTest.php b/tests/PhpWordTests/Style/SpacingTest.php index 9e86b482cf..874fd5c5dd 100644 --- a/tests/PhpWordTests/Style/SpacingTest.php +++ b/tests/PhpWordTests/Style/SpacingTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/TOCTest.php b/tests/PhpWordTests/Style/TOCTest.php index cf0a72485d..118c8c4199 100644 --- a/tests/PhpWordTests/Style/TOCTest.php +++ b/tests/PhpWordTests/Style/TOCTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/TabTest.php b/tests/PhpWordTests/Style/TabTest.php index f89706b92a..a1a6a2e0db 100644 --- a/tests/PhpWordTests/Style/TabTest.php +++ b/tests/PhpWordTests/Style/TabTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/TablePositionTest.php b/tests/PhpWordTests/Style/TablePositionTest.php index 2c1279fec7..ba0bb9dd09 100644 --- a/tests/PhpWordTests/Style/TablePositionTest.php +++ b/tests/PhpWordTests/Style/TablePositionTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/TableTest.php b/tests/PhpWordTests/Style/TableTest.php index 2bdb48be1f..e53a51f5df 100644 --- a/tests/PhpWordTests/Style/TableTest.php +++ b/tests/PhpWordTests/Style/TableTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Style/TextBoxTest.php b/tests/PhpWordTests/Style/TextBoxTest.php index c6647c5084..30c01bd368 100644 --- a/tests/PhpWordTests/Style/TextBoxTest.php +++ b/tests/PhpWordTests/Style/TextBoxTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/StyleTest.php b/tests/PhpWordTests/StyleTest.php index 30f37ff416..6115e04426 100644 --- a/tests/PhpWordTests/StyleTest.php +++ b/tests/PhpWordTests/StyleTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/TemplateProcessorTest.php b/tests/PhpWordTests/TemplateProcessorTest.php index b8ad970ced..9ba6933e74 100644 --- a/tests/PhpWordTests/TemplateProcessorTest.php +++ b/tests/PhpWordTests/TemplateProcessorTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -863,15 +864,15 @@ public function testSetImageValue(): void // dynamic generated doc $testFileName = 'images-test-sample.docx'; - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $section = $phpWord->addSection(); $section->addText('${Test:width=100:ratio=true}'); - $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007'); + $objWriter = IOFactory::createWriter($phpWord, 'Word2007'); $objWriter->save($testFileName); self::assertFileExists($testFileName, "Generated file '{$testFileName}' not found!"); $resultFileName = 'images-test-result.docx'; - $templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor($testFileName); + $templateProcessor = new TemplateProcessor($testFileName); unlink($testFileName); $templateProcessor->setImageValue('Test', $imagePath); $templateProcessor->setImageValue('Test1', $imagePath); @@ -1025,7 +1026,7 @@ public function testCloneBlockCanCloneABlockTwice(): void // and the placeholders have been replaced correctly $phpWord = IOFactory::load($templatePath); $sections = $phpWord->getSections(); - /** @var \PhpOffice\PhpWord\Element\TextRun[] $actualElements */ + /** @var TextRun[] $actualElements */ $actualElements = $sections[0]->getElements(); unlink($templatePath); $expectedElements = [ @@ -1079,7 +1080,7 @@ public function testCloneBlockCanCloneABlockTwiceWithCustomMacro(): void // and the placeholders have been replaced correctly $phpWord = IOFactory::load($templatePath); $sections = $phpWord->getSections(); - /** @var \PhpOffice\PhpWord\Element\TextRun[] $actualElements */ + /** @var TextRun[] $actualElements */ $actualElements = $sections[0]->getElements(); unlink($templatePath); diff --git a/tests/PhpWordTests/TestHelperDOCX.php b/tests/PhpWordTests/TestHelperDOCX.php index de9f1a81b7..2a6fbabae0 100644 --- a/tests/PhpWordTests/TestHelperDOCX.php +++ b/tests/PhpWordTests/TestHelperDOCX.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -42,7 +43,7 @@ class TestHelperDOCX * * @param string $writerName * - * @return \PhpOffice\PhpWordTests\XmlDocument + * @return XmlDocument */ public static function getDocument(PhpWord $phpWord, $writerName = 'Word2007') { diff --git a/tests/PhpWordTests/TestableTemplateProcesor.php b/tests/PhpWordTests/TestableTemplateProcesor.php index 32657b14e4..9d6eb9904e 100644 --- a/tests/PhpWordTests/TestableTemplateProcesor.php +++ b/tests/PhpWordTests/TestableTemplateProcesor.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/HTML/DirectionTest.php b/tests/PhpWordTests/Writer/HTML/DirectionTest.php index 4f0755b87f..f3b5830d28 100644 --- a/tests/PhpWordTests/Writer/HTML/DirectionTest.php +++ b/tests/PhpWordTests/Writer/HTML/DirectionTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/HTML/Element/PageBreakTest.php b/tests/PhpWordTests/Writer/HTML/Element/PageBreakTest.php index 37ef71aa07..23f5890e9d 100644 --- a/tests/PhpWordTests/Writer/HTML/Element/PageBreakTest.php +++ b/tests/PhpWordTests/Writer/HTML/Element/PageBreakTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/HTML/Element/TableTest.php b/tests/PhpWordTests/Writer/HTML/Element/TableTest.php index 8dec922108..cd0bafaab0 100644 --- a/tests/PhpWordTests/Writer/HTML/Element/TableTest.php +++ b/tests/PhpWordTests/Writer/HTML/Element/TableTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/HTML/ElementTest.php b/tests/PhpWordTests/Writer/HTML/ElementTest.php index 3fee31a69b..3b2580381f 100644 --- a/tests/PhpWordTests/Writer/HTML/ElementTest.php +++ b/tests/PhpWordTests/Writer/HTML/ElementTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/HTML/FontTest.php b/tests/PhpWordTests/Writer/HTML/FontTest.php index 442c2639c9..d2519f962f 100644 --- a/tests/PhpWordTests/Writer/HTML/FontTest.php +++ b/tests/PhpWordTests/Writer/HTML/FontTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -85,21 +86,27 @@ public function testFontNames1(): void $style = Helper::getTextContent($xpath, '/html/head/style'); $prg = preg_match('/^[*][^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('* {font-family: \'Courier New\'; font-size: 12pt;}', $matches[0]); $prg = preg_match('/^[.]style1[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style1 {font-family: \'Tahoma\'; font-size: 10pt; color: #1B2232; font-weight: bold;}', $matches[0]); $prg = preg_match('/^[.]style2[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style2 {font-family: \'Arial\'; font-size: 10pt;}', $matches[0]); $prg = preg_match('/^[.]style3[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style3 {font-family: \'hack attempt'}; display:none\'; font-size: 10pt;}', $matches[0]); $prg = preg_match('/^[.]style4[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style4 {font-family: \'padmaa 1.1\'; font-size: 10pt; font-weight: bold;}', $matches[0]); $prg = preg_match('/^[.]style5[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style5 {font-family: \'MingLiU-ExtB\'; font-size: 10pt; font-weight: bold;}', $matches[0]); } @@ -135,18 +142,23 @@ public function testFontNames2(): void $style = Helper::getTextContent($xpath, '/html/head/style'); $prg = preg_match('/^[*][^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('* {font-family: \'Courier New\'; font-size: 12pt;}', $matches[0]); $prg = preg_match('/^[.]style1[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style1 {font-family: \'Tahoma\'; font-size: 10pt; color: #1B2232; font-weight: bold;}', $matches[0]); $prg = preg_match('/^[.]style2[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style2 {font-family: \'Arial\', sans-serif; font-size: 10pt;}', $matches[0]); $prg = preg_match('/^[.]style3[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style3 {font-family: \'DejaVu Sans Monospace\', monospace; font-size: 10pt;}', $matches[0]); $prg = preg_match('/^[.]style4[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style4 {font-family: \'Arial\'; font-size: 10pt;}', $matches[0]); } @@ -182,18 +194,23 @@ public function testFontNames3(): void $style = Helper::getTextContent($xpath, '/html/head/style'); $prg = preg_match('/^[*][^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('* {font-family: \'Courier New\', monospace; font-size: 12pt;}', $matches[0]); $prg = preg_match('/^[.]style1[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style1 {font-family: \'Tahoma\'; font-size: 10pt; color: #1B2232; font-weight: bold;}', $matches[0]); $prg = preg_match('/^[.]style2[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style2 {font-family: \'Arial\', sans-serif; font-size: 10pt;}', $matches[0]); $prg = preg_match('/^[.]style3[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style3 {font-family: \'DejaVu Sans Monospace\', monospace; font-size: 10pt;}', $matches[0]); $prg = preg_match('/^[.]style4[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style4 {font-family: \'Arial\'; font-size: 10pt;}', $matches[0]); } @@ -224,15 +241,19 @@ public function testWhiteSpace(): void self::assertNotFalse(preg_match('/^[*][^\\r\\n]*/m', $style, $matches)); self::assertEquals('* {font-family: \'Arial\'; font-size: 12pt; white-space: pre-wrap;}', $matches[0]); $prg = preg_match('/^[.]style1[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style1 {font-family: \'Courier New\'; font-size: 10pt; white-space: pre-wrap;}', $matches[0]); $prg = preg_match('/^[.]style2[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style2 {font-family: \'Courier New\'; font-size: 10pt;}', $matches[0]); $prg = preg_match('/^[.]style3[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style3 {font-family: \'Courier New\'; font-size: 10pt; white-space: normal;}', $matches[0]); $prg = preg_match('/^[.]style4[^\\r\\n]*/m', $style, $matches); + self::assertNotEmpty($matches); self::assertNotFalse($prg); self::assertEquals('.style4 {font-family: \'Courier New\'; font-size: 10pt;}', $matches[0]); } diff --git a/tests/PhpWordTests/Writer/HTML/Helper.php b/tests/PhpWordTests/Writer/HTML/Helper.php index b777d4be14..0fe390fd0d 100644 --- a/tests/PhpWordTests/Writer/HTML/Helper.php +++ b/tests/PhpWordTests/Writer/HTML/Helper.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/HTML/ParagraphTest.php b/tests/PhpWordTests/Writer/HTML/ParagraphTest.php index dc306df978..2b2724dba8 100644 --- a/tests/PhpWordTests/Writer/HTML/ParagraphTest.php +++ b/tests/PhpWordTests/Writer/HTML/ParagraphTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/HTML/PartTest.php b/tests/PhpWordTests/Writer/HTML/PartTest.php index 9515932ac8..b6748a58c5 100644 --- a/tests/PhpWordTests/Writer/HTML/PartTest.php +++ b/tests/PhpWordTests/Writer/HTML/PartTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/HTML/StyleTest.php b/tests/PhpWordTests/Writer/HTML/StyleTest.php index 0ad5dd46a0..6dcb12f630 100644 --- a/tests/PhpWordTests/Writer/HTML/StyleTest.php +++ b/tests/PhpWordTests/Writer/HTML/StyleTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/HTMLTest.php b/tests/PhpWordTests/Writer/HTMLTest.php index 700dd2ed3b..6dba003eb4 100644 --- a/tests/PhpWordTests/Writer/HTMLTest.php +++ b/tests/PhpWordTests/Writer/HTMLTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -21,14 +22,14 @@ use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\Writer\HTML; -use PhpOffice\PhpWordTests\AbstractWebServerEmbeddedTest; +use PhpOffice\PhpWordTests\AbstractWebServerEmbedded; /** * Test class for PhpOffice\PhpWord\Writer\HTML. * * @runTestsInSeparateProcesses */ -class HTMLTest extends AbstractWebServerEmbeddedTest +class HTMLTest extends AbstractWebServerEmbedded { /** * Construct. diff --git a/tests/PhpWordTests/Writer/ODText/Element/FieldTest.php b/tests/PhpWordTests/Writer/ODText/Element/FieldTest.php index 2d9bb7c87d..0f936d053e 100644 --- a/tests/PhpWordTests/Writer/ODText/Element/FieldTest.php +++ b/tests/PhpWordTests/Writer/ODText/Element/FieldTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/ODText/Element/FormulaTest.php b/tests/PhpWordTests/Writer/ODText/Element/FormulaTest.php index 9276372105..c834a465f0 100644 --- a/tests/PhpWordTests/Writer/ODText/Element/FormulaTest.php +++ b/tests/PhpWordTests/Writer/ODText/Element/FormulaTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/ODText/Element/ImageTest.php b/tests/PhpWordTests/Writer/ODText/Element/ImageTest.php index 367f9eee75..ff7788df26 100644 --- a/tests/PhpWordTests/Writer/ODText/Element/ImageTest.php +++ b/tests/PhpWordTests/Writer/ODText/Element/ImageTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/ODText/Element/ListItemRunTest.php b/tests/PhpWordTests/Writer/ODText/Element/ListItemRunTest.php index d0509035cc..9f531255fc 100644 --- a/tests/PhpWordTests/Writer/ODText/Element/ListItemRunTest.php +++ b/tests/PhpWordTests/Writer/ODText/Element/ListItemRunTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/ODText/ElementTest.php b/tests/PhpWordTests/Writer/ODText/ElementTest.php index 0ad0325656..56bbf025ed 100644 --- a/tests/PhpWordTests/Writer/ODText/ElementTest.php +++ b/tests/PhpWordTests/Writer/ODText/ElementTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -195,7 +196,7 @@ public function testTitleAndHeading(): void */ public function testTextRunTitle(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $phpWord->addTitleStyle(1, ['name' => 'Times New Roman', 'size' => 18, 'bold' => true]); $section = $phpWord->addSection(); $section->addTitle('Text Title', 1); @@ -275,7 +276,7 @@ public function testPageBreak(): void */ public function testTrackedChanges(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); // New portrait section $section = $phpWord->addSection(); diff --git a/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php b/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php index 3ebc534b21..6742b20ad5 100644 --- a/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php +++ b/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -33,7 +34,7 @@ class AbstractPartTest extends \PHPUnit\Framework\TestCase */ public function testSetGetParentWriter(): void { - $object = $this->getMockForAbstractClass(\PhpOffice\PhpWord\Writer\ODText\Part\AbstractPart::class); + $object = $this->getMockForAbstractClass(ODText\Part\AbstractPart::class); $object->setParentWriter(new ODText()); self::assertEquals(new ODText(), $object->getParentWriter()); } @@ -45,7 +46,7 @@ public function testSetGetParentWriterNull(): void { $this->expectException(Exception::class); $this->expectExceptionMessage('No parent WriterInterface assigned.'); - $object = $this->getMockForAbstractClass(\PhpOffice\PhpWord\Writer\ODText\Part\AbstractPart::class); + $object = $this->getMockForAbstractClass(ODText\Part\AbstractPart::class); $object->getParentWriter(); } } diff --git a/tests/PhpWordTests/Writer/ODText/Part/ContentTest.php b/tests/PhpWordTests/Writer/ODText/Part/ContentTest.php index f86507ce06..e1dc78a32b 100644 --- a/tests/PhpWordTests/Writer/ODText/Part/ContentTest.php +++ b/tests/PhpWordTests/Writer/ODText/Part/ContentTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/ODText/Part/ManifestTest.php b/tests/PhpWordTests/Writer/ODText/Part/ManifestTest.php index 01a8053c8f..bfe5253cda 100644 --- a/tests/PhpWordTests/Writer/ODText/Part/ManifestTest.php +++ b/tests/PhpWordTests/Writer/ODText/Part/ManifestTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/ODText/Style/FontTest.php b/tests/PhpWordTests/Writer/ODText/Style/FontTest.php index 34e5e506b4..5edef8fea6 100644 --- a/tests/PhpWordTests/Writer/ODText/Style/FontTest.php +++ b/tests/PhpWordTests/Writer/ODText/Style/FontTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -42,7 +43,7 @@ public function testColors(): void $section = $phpWord->addSection(); $section->addText('This is red (800) in rtf/html, default in docx/odt', ['color' => '800']); $section->addText('This should be cyanish (008787)', ['color' => '008787']); - $section->addText('This should be dark green (FGCOLOR_DARKGREEN)', ['color' => \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKGREEN]); + $section->addText('This should be dark green (FGCOLOR_DARKGREEN)', ['color' => Font::FGCOLOR_DARKGREEN]); $section->addText('This color is default (unknow)', ['color' => 'unknow']); $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); @@ -219,7 +220,7 @@ public function testFieldStyles(): void $fld->setFontStyle(['color' => '008000']); $textrun = $section->addTextRun(); $fld = $textrun->addField('DATE'); - $font = new \PhpOffice\PhpWord\Style\Font(); + $font = new Font(); $font->setColor('000080'); $fld->setFontStyle($font); $textrun = $section->addTextRun(); diff --git a/tests/PhpWordTests/Writer/ODText/Style/NumberingTest.php b/tests/PhpWordTests/Writer/ODText/Style/NumberingTest.php index 4b46637045..b06242706d 100644 --- a/tests/PhpWordTests/Writer/ODText/Style/NumberingTest.php +++ b/tests/PhpWordTests/Writer/ODText/Style/NumberingTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php b/tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php index b638b380b6..bc02ca8ea0 100644 --- a/tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php +++ b/tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/ODText/Style/ParagraphTest.php b/tests/PhpWordTests/Writer/ODText/Style/ParagraphTest.php index 778bb20b5f..ecadd387d5 100644 --- a/tests/PhpWordTests/Writer/ODText/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Writer/ODText/Style/ParagraphTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -363,7 +364,7 @@ public function testHeadingPageBreakBefore(): void */ public function testTextRun(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $phpWord->addParagraphStyle('parstyle1', ['align' => 'start']); $phpWord->addParagraphStyle('parstyle2', ['align' => 'end']); $section = $phpWord->addSection(); @@ -403,7 +404,7 @@ public function testTextRun(): void */ public function testTextRunUnnamed(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $parstyle1 = ['align' => 'start']; $parstyle2 = ['align' => 'end']; $section = $phpWord->addSection(); @@ -437,7 +438,7 @@ public function testTextRunUnnamed(): void */ public function testEmptyFontAndParagraphStyles(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $section = $phpWord->addSection(); $phpWord->addFontStyle('namedfont', ['name' => 'Courier New', 'size' => 8]); $phpWord->addParagraphStyle('namedpar', ['lineHeight' => 1.08]); diff --git a/tests/PhpWordTests/Writer/ODText/Style/SectionTest.php b/tests/PhpWordTests/Writer/ODText/Style/SectionTest.php index cbd58da455..83f5962944 100644 --- a/tests/PhpWordTests/Writer/ODText/Style/SectionTest.php +++ b/tests/PhpWordTests/Writer/ODText/Style/SectionTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -38,7 +39,7 @@ protected function tearDown(): void */ public function testHeaderFooterTabs(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $margins = \PhpOffice\PhpWord\Shared\Converter::INCH_TO_TWIP; $phpWord->addFontStyle('hdrstyle1', ['name' => 'Courier New', 'size' => 8]); $section = $phpWord->addSection(['paperSize' => 'Letter', 'marginTop' => $margins, 'marginBottom' => $margins]); diff --git a/tests/PhpWordTests/Writer/ODText/StyleTest.php b/tests/PhpWordTests/Writer/ODText/StyleTest.php index 0d36b4899c..21d4c8bb53 100644 --- a/tests/PhpWordTests/Writer/ODText/StyleTest.php +++ b/tests/PhpWordTests/Writer/ODText/StyleTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/ODTextTest.php b/tests/PhpWordTests/Writer/ODTextTest.php index 2405f9db7f..9746791379 100644 --- a/tests/PhpWordTests/Writer/ODTextTest.php +++ b/tests/PhpWordTests/Writer/ODTextTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/PDF/DomPDFTest.php b/tests/PhpWordTests/Writer/PDF/DomPDFTest.php index 789519ded1..37ea762802 100644 --- a/tests/PhpWordTests/Writer/PDF/DomPDFTest.php +++ b/tests/PhpWordTests/Writer/PDF/DomPDFTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/PDF/MPDFTest.php b/tests/PhpWordTests/Writer/PDF/MPDFTest.php index 0fe53456ba..dc779bd51f 100644 --- a/tests/PhpWordTests/Writer/PDF/MPDFTest.php +++ b/tests/PhpWordTests/Writer/PDF/MPDFTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/PDF/TCPDFTest.php b/tests/PhpWordTests/Writer/PDF/TCPDFTest.php index 00587cb7f3..16887507a9 100644 --- a/tests/PhpWordTests/Writer/PDF/TCPDFTest.php +++ b/tests/PhpWordTests/Writer/PDF/TCPDFTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/PDFTest.php b/tests/PhpWordTests/Writer/PDFTest.php index fc4064a23f..b9e31511cf 100644 --- a/tests/PhpWordTests/Writer/PDFTest.php +++ b/tests/PhpWordTests/Writer/PDFTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/RTF/Element/TableTest.php b/tests/PhpWordTests/Writer/RTF/Element/TableTest.php index 35cdfbec28..7c1ceac68e 100644 --- a/tests/PhpWordTests/Writer/RTF/Element/TableTest.php +++ b/tests/PhpWordTests/Writer/RTF/Element/TableTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -40,7 +41,7 @@ public function testTable(): void { Settings::setDefaultRtl(false); $parentWriter = new RTF(); - $element = new \PhpOffice\PhpWord\Element\Table(); + $element = new Table(); $width = 100; $width2 = 2 * $width; $element->addRow(); diff --git a/tests/PhpWordTests/Writer/RTF/Element2Test.php b/tests/PhpWordTests/Writer/RTF/Element2Test.php index 7d36fac869..2220d93b68 100644 --- a/tests/PhpWordTests/Writer/RTF/Element2Test.php +++ b/tests/PhpWordTests/Writer/RTF/Element2Test.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/RTF/ElementTest.php b/tests/PhpWordTests/Writer/RTF/ElementTest.php index fd0842cd6c..dbd937bc0d 100644 --- a/tests/PhpWordTests/Writer/RTF/ElementTest.php +++ b/tests/PhpWordTests/Writer/RTF/ElementTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -49,7 +50,7 @@ public function testFilenameField(): void { $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Field('FILENAME'); - $field = new \PhpOffice\PhpWord\Writer\RTF\Element\Field($parentWriter, $element); + $field = new RTF\Element\Field($parentWriter, $element); self::assertEquals("{\\field{\\*\\fldinst FILENAME}{\\fldrslt}}\\par\n", $this->removeCr($field)); } @@ -58,7 +59,7 @@ public function testFilenameFieldOptionsPath(): void { $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Field('FILENAME', [], ['Path']); - $field = new \PhpOffice\PhpWord\Writer\RTF\Element\Field($parentWriter, $element); + $field = new RTF\Element\Field($parentWriter, $element); self::assertEquals("{\\field{\\*\\fldinst FILENAME \\\\p}{\\fldrslt}}\\par\n", $this->removeCr($field)); } @@ -67,7 +68,7 @@ public function testPageField(): void { $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Field('PAGE'); - $field = new \PhpOffice\PhpWord\Writer\RTF\Element\Field($parentWriter, $element); + $field = new RTF\Element\Field($parentWriter, $element); self::assertEquals("{\\field{\\*\\fldinst PAGE}{\\fldrslt}}\\par\n", $this->removeCr($field)); } @@ -76,7 +77,7 @@ public function testNumpageField(): void { $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Field('NUMPAGES'); - $field = new \PhpOffice\PhpWord\Writer\RTF\Element\Field($parentWriter, $element); + $field = new RTF\Element\Field($parentWriter, $element); self::assertEquals("{\\field{\\*\\fldinst NUMPAGES}{\\fldrslt}}\\par\n", $this->removeCr($field)); } @@ -85,7 +86,7 @@ public function testDateField(): void { $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Field('DATE', ['dateformat' => 'd MM yyyy H:mm:ss']); - $field = new \PhpOffice\PhpWord\Writer\RTF\Element\Field($parentWriter, $element); + $field = new RTF\Element\Field($parentWriter, $element); self::assertEquals("{\\field{\\*\\fldinst DATE \\\\@ \"d MM yyyy H:mm:ss\"}{\\fldrslt}}\\par\n", $this->removeCr($field)); } @@ -94,7 +95,7 @@ public function testIndexField(): void { $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Field('INDEX'); - $field = new \PhpOffice\PhpWord\Writer\RTF\Element\Field($parentWriter, $element); + $field = new RTF\Element\Field($parentWriter, $element); self::assertEquals("{}\\par\n", $this->removeCr($field)); } @@ -115,7 +116,7 @@ public function testTable(): void $tce->addText('3'); $tce = $element->addCell($width); $tce->addText('4'); - $table = new \PhpOffice\PhpWord\Writer\RTF\Element\Table($parentWriter, $element); + $table = new RTF\Element\Table($parentWriter, $element); $expect = implode("\n", [ '\\pard', "\\trowd \\cellx$width \\cellx$width2 ", @@ -147,7 +148,7 @@ public function testTextRun(): void $element = new \PhpOffice\PhpWord\Element\TextRun(); $element->addText('Hello '); $element->addText('there.'); - $textrun = new \PhpOffice\PhpWord\Writer\RTF\Element\TextRun($parentWriter, $element); + $textrun = new RTF\Element\TextRun($parentWriter, $element); $expect = "\\pard\\nowidctlpar {{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } @@ -158,7 +159,7 @@ public function testTextRunParagraphStyle(): void $element = new \PhpOffice\PhpWord\Element\TextRun(['spaceBefore' => 0, 'spaceAfter' => 0]); $element->addText('Hello '); $element->addText('there.'); - $textrun = new \PhpOffice\PhpWord\Writer\RTF\Element\TextRun($parentWriter, $element); + $textrun = new RTF\Element\TextRun($parentWriter, $element); $expect = "\\pard\\nowidctlpar \\sb0\\sa0{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } @@ -170,7 +171,7 @@ public function testTitle(): void $phpWord->addTitleStyle(1, [], ['spaceBefore' => 0, 'spaceAfter' => 0]); $section = $phpWord->addSection(); $element = $section->addTitle('First Heading', 1); - $elwrite = new \PhpOffice\PhpWord\Writer\RTF\Element\Title($parentWriter, $element); + $elwrite = new RTF\Element\Title($parentWriter, $element); $expect = "\\pard\\nowidctlpar \\sb0\\sa0{\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}"; self::assertEquals($expect, $this->removeCr($elwrite)); } diff --git a/tests/PhpWordTests/Writer/RTF/HeaderFooterTest.php b/tests/PhpWordTests/Writer/RTF/HeaderFooterTest.php index ec71b2f078..3b4f86c7d7 100644 --- a/tests/PhpWordTests/Writer/RTF/HeaderFooterTest.php +++ b/tests/PhpWordTests/Writer/RTF/HeaderFooterTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/RTF/StyleTest.php b/tests/PhpWordTests/Writer/RTF/StyleTest.php index 8f09fec40c..8ba2bcb9c9 100644 --- a/tests/PhpWordTests/Writer/RTF/StyleTest.php +++ b/tests/PhpWordTests/Writer/RTF/StyleTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -76,7 +77,7 @@ public function testIndentation(): void $indentation->setRight(2); $indentation->setFirstLine(3); - $indentWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Indentation($indentation); + $indentWriter = new RTF\Style\Indentation($indentation); $indentWriter->setParentWriter(new RTF()); $result = $indentWriter->write(); @@ -89,7 +90,7 @@ public function testRightTab(): void $tabRight->setType(\PhpOffice\PhpWord\Style\Tab::TAB_STOP_RIGHT); $tabRight->setPosition(5); - $tabWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Tab($tabRight); + $tabWriter = new RTF\Style\Tab($tabRight); $tabWriter->setParentWriter(new RTF()); $result = $tabWriter->write(); @@ -101,7 +102,7 @@ public function testCenterTab(): void $tabRight = new \PhpOffice\PhpWord\Style\Tab(); $tabRight->setType(\PhpOffice\PhpWord\Style\Tab::TAB_STOP_CENTER); - $tabWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Tab($tabRight); + $tabWriter = new RTF\Style\Tab($tabRight); $tabWriter->setParentWriter(new RTF()); $result = $tabWriter->write(); @@ -113,7 +114,7 @@ public function testDecimalTab(): void $tabRight = new \PhpOffice\PhpWord\Style\Tab(); $tabRight->setType(\PhpOffice\PhpWord\Style\Tab::TAB_STOP_DECIMAL); - $tabWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Tab($tabRight); + $tabWriter = new RTF\Style\Tab($tabRight); $tabWriter->setParentWriter(new RTF()); $result = $tabWriter->write(); @@ -124,7 +125,7 @@ public function testRTL(): void { $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('אב גד', ['RTL' => true]); - $text = new \PhpOffice\PhpWord\Writer\RTF\Element\Text($parentWriter, $element); + $text = new RTF\Element\Text($parentWriter, $element); $expect = "\\pard\\nowidctlpar {\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } @@ -134,7 +135,7 @@ public function testRTL2(): void Settings::setDefaultRtl(true); $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('אב גד'); - $text = new \PhpOffice\PhpWord\Writer\RTF\Element\Text($parentWriter, $element); + $text = new RTF\Element\Text($parentWriter, $element); $expect = "\\pard\\nowidctlpar \\qr{\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } @@ -143,7 +144,7 @@ public function testPageBreakLineHeight(): void { $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('New page', null, ['lineHeight' => 1.08, 'pageBreakBefore' => true]); - $text = new \PhpOffice\PhpWord\Writer\RTF\Element\Text($parentWriter, $element); + $text = new RTF\Element\Text($parentWriter, $element); $expect = "\\pard\\nowidctlpar \\sl259\\slmult1\\page{\\cf0\\f0 New page}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } @@ -153,7 +154,7 @@ public function testPageBreakLineHeight2(): void Settings::setDefaultRtl(false); $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('New page', null, ['lineHeight' => 1.08, 'pageBreakBefore' => true]); - $text = new \PhpOffice\PhpWord\Writer\RTF\Element\Text($parentWriter, $element); + $text = new RTF\Element\Text($parentWriter, $element); $expect = "\\pard\\nowidctlpar \\ql\\sl259\\slmult1\\page{\\cf0\\f0 New page}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } @@ -163,7 +164,7 @@ public function testPageNumberRestart(): void //$parentWriter = new RTF(); $phpword = new \PhpOffice\PhpWord\PhpWord(); $section = $phpword->addSection(['pageNumberingStart' => 5]); - $styleWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Section($section->getStyle()); + $styleWriter = new RTF\Style\Section($section->getStyle()); $wstyle = $this->removeCr($styleWriter); // following have default values which might change so don't use them $wstyle = preg_replace('/\\\\pgwsxn\\d+/', '', $wstyle); diff --git a/tests/PhpWordTests/Writer/RTFTest.php b/tests/PhpWordTests/Writer/RTFTest.php index c56bc9f3dc..4f9f8944ac 100644 --- a/tests/PhpWordTests/Writer/RTFTest.php +++ b/tests/PhpWordTests/Writer/RTFTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Element/ChartTest.php b/tests/PhpWordTests/Writer/Word2007/Element/ChartTest.php index 0540c75021..4951da39ce 100644 --- a/tests/PhpWordTests/Writer/Word2007/Element/ChartTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Element/ChartTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Element/FieldTest.php b/tests/PhpWordTests/Writer/Word2007/Element/FieldTest.php index 30f875c08c..d3128e8007 100644 --- a/tests/PhpWordTests/Writer/Word2007/Element/FieldTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Element/FieldTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Element/FormFieldTest.php b/tests/PhpWordTests/Writer/Word2007/Element/FormFieldTest.php index 14e30d552d..52861900e7 100644 --- a/tests/PhpWordTests/Writer/Word2007/Element/FormFieldTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Element/FormFieldTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Element/FormulaTest.php b/tests/PhpWordTests/Writer/Word2007/Element/FormulaTest.php index b9acb1c226..dc0bd19e22 100644 --- a/tests/PhpWordTests/Writer/Word2007/Element/FormulaTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Element/FormulaTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php b/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php index 537fb93d1a..45973a4fed 100644 --- a/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Element/TableTest.php b/tests/PhpWordTests/Writer/Word2007/Element/TableTest.php index 57010893ae..8b9e5efee3 100644 --- a/tests/PhpWordTests/Writer/Word2007/Element/TableTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Element/TableTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php b/tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php index 180a319eb1..1d62ffa964 100644 --- a/tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/ElementTest.php b/tests/PhpWordTests/Writer/Word2007/ElementTest.php index 3ed3e7a91b..999e188e82 100644 --- a/tests/PhpWordTests/Writer/Word2007/ElementTest.php +++ b/tests/PhpWordTests/Writer/Word2007/ElementTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Part/AbstractPartTest.php b/tests/PhpWordTests/Writer/Word2007/Part/AbstractPartTest.php index 6e376f3e82..04cdb5ff52 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/AbstractPartTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/AbstractPartTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -31,7 +32,7 @@ class AbstractPartTest extends \PHPUnit\Framework\TestCase */ public function testSetGetParentWriter(): void { - $object = $this->getMockForAbstractClass(\PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart::class); + $object = $this->getMockForAbstractClass(Word2007\Part\AbstractPart::class); $object->setParentWriter(new Word2007()); self::assertEquals(new Word2007(), $object->getParentWriter()); } @@ -43,7 +44,7 @@ public function testSetGetParentWriterNull(): void { $this->expectException(Exception::class); $this->expectExceptionMessage('No parent WriterInterface assigned.'); - $object = $this->getMockForAbstractClass(\PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart::class); + $object = $this->getMockForAbstractClass(Word2007\Part\AbstractPart::class); $object->getParentWriter(); } } diff --git a/tests/PhpWordTests/Writer/Word2007/Part/CommentsTest.php b/tests/PhpWordTests/Writer/Word2007/Part/CommentsTest.php index 383203636b..8f8c8240a9 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/CommentsTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/CommentsTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php index 76c05786c0..ed38c57ac6 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Part/FooterTest.php b/tests/PhpWordTests/Writer/Word2007/Part/FooterTest.php index 0dc99e7e37..beb6e971e2 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/FooterTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/FooterTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Part/FootnotesTest.php b/tests/PhpWordTests/Writer/Word2007/Part/FootnotesTest.php index 526d3591e8..d8bf678541 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/FootnotesTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/FootnotesTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Part/HeaderTest.php b/tests/PhpWordTests/Writer/Word2007/Part/HeaderTest.php index 27e9bcb9ba..164365f113 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/HeaderTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/HeaderTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Part/NumberingTest.php b/tests/PhpWordTests/Writer/Word2007/Part/NumberingTest.php index 88de8f444a..1cf596fc85 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/NumberingTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/NumberingTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Part/SettingsTest.php b/tests/PhpWordTests/Writer/Word2007/Part/SettingsTest.php index db8f5198a4..107b94b1be 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/SettingsTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/SettingsTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Part/StylesTest.php b/tests/PhpWordTests/Writer/Word2007/Part/StylesTest.php index eafee33b50..6939c6fddc 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/StylesTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/StylesTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/PartTest.php b/tests/PhpWordTests/Writer/Word2007/PartTest.php index a3bc47b4c9..be69e587e3 100644 --- a/tests/PhpWordTests/Writer/Word2007/PartTest.php +++ b/tests/PhpWordTests/Writer/Word2007/PartTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Style/DirectionTest.php b/tests/PhpWordTests/Writer/Word2007/Style/DirectionTest.php index b5e93d2374..efd855af23 100644 --- a/tests/PhpWordTests/Writer/Word2007/Style/DirectionTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Style/DirectionTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Style/FontTest.php b/tests/PhpWordTests/Writer/Word2007/Style/FontTest.php index a8214ec35b..c0e2653a7c 100644 --- a/tests/PhpWordTests/Writer/Word2007/Style/FontTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Style/FontTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -43,7 +44,7 @@ protected function tearDown(): void */ public function testFontRTL(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $section = $phpWord->addSection(); $textrun = $section->addTextRun(); $textrun->addText('سلام این یک پاراگراف راست به چپ است', ['rtl' => true, 'lang' => 'ar-DZ']); @@ -56,7 +57,7 @@ public function testFontRTL(): void public function testFontRTLNamed(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $stnam = 'fstyle'; $phpWord->addFontStyle($stnam, [ 'rtl' => true, @@ -81,7 +82,7 @@ public function testFontRTLNamed(): void public function testFontNotRTLNamed(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $stnam = 'fstyle'; $phpWord->addFontStyle($stnam, [ //'rtl' => true, @@ -106,7 +107,7 @@ public function testFontNotRTLNamed(): void public function testNoProof(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $fontStyle = [ 'noProof' => true, 'name' => 'Courier New', @@ -133,7 +134,7 @@ public function testNoProof(): void */ public function testFontWithLang(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $section = $phpWord->addSection(); $section->addText('Ce texte-ci est en français.', ['lang' => \PhpOffice\PhpWord\Style\Language::FR_BE]); $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); @@ -148,7 +149,7 @@ public function testFontWithLang(): void */ public function testPosition(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $section = $phpWord->addSection(); $section->addText('This text is lowered', ['position' => -20]); $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); diff --git a/tests/PhpWordTests/Writer/Word2007/Style/ImageTest.php b/tests/PhpWordTests/Writer/Word2007/Style/ImageTest.php index 53ecba2dd9..2b5c25e01f 100644 --- a/tests/PhpWordTests/Writer/Word2007/Style/ImageTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Style/ImageTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Style/ParagraphTest.php b/tests/PhpWordTests/Writer/Word2007/Style/ParagraphTest.php index 759a0003c7..c1f985ccd2 100644 --- a/tests/PhpWordTests/Writer/Word2007/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Style/ParagraphTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/Style/SectionTest.php b/tests/PhpWordTests/Writer/Word2007/Style/SectionTest.php index e8f2dc67a7..f527ded190 100644 --- a/tests/PhpWordTests/Writer/Word2007/Style/SectionTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Style/SectionTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -40,7 +41,7 @@ protected function tearDown(): void public function testMarginInInches(): void { $unit = Settings::getMeasurementUnit(); - Settings::setMeasurementUnit(\PhpOffice\PhpWord\Settings::UNIT_INCH); + Settings::setMeasurementUnit(Settings::UNIT_INCH); $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); diff --git a/tests/PhpWordTests/Writer/Word2007/Style/TableTest.php b/tests/PhpWordTests/Writer/Word2007/Style/TableTest.php index b072bb8ab2..b10d836568 100644 --- a/tests/PhpWordTests/Writer/Word2007/Style/TableTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Style/TableTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007/StyleTest.php b/tests/PhpWordTests/Writer/Word2007/StyleTest.php index 0db61e8cfb..d458ea45e7 100644 --- a/tests/PhpWordTests/Writer/Word2007/StyleTest.php +++ b/tests/PhpWordTests/Writer/Word2007/StyleTest.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/PhpWordTests/Writer/Word2007Test.php b/tests/PhpWordTests/Writer/Word2007Test.php index 0965222fb3..64f6a29b52 100644 --- a/tests/PhpWordTests/Writer/Word2007Test.php +++ b/tests/PhpWordTests/Writer/Word2007Test.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -22,7 +23,7 @@ use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\Writer\Word2007; -use PhpOffice\PhpWordTests\AbstractWebServerEmbeddedTest; +use PhpOffice\PhpWordTests\AbstractWebServerEmbedded; use PhpOffice\PhpWordTests\TestHelperDOCX; /** @@ -30,7 +31,7 @@ * * @runTestsInSeparateProcesses */ -class Word2007Test extends AbstractWebServerEmbeddedTest +class Word2007Test extends AbstractWebServerEmbedded { /** * Tear down after each test. diff --git a/tests/PhpWordTests/XmlDocument.php b/tests/PhpWordTests/XmlDocument.php index 1b309d0c71..8c865932ba 100644 --- a/tests/PhpWordTests/XmlDocument.php +++ b/tests/PhpWordTests/XmlDocument.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 845e59db70..e6dabe8f7f 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,4 +1,5 @@ <?php + /** * This file is part of PHPWord - A pure PHP library for reading and writing * word processing documents. @@ -44,7 +45,7 @@ function phpunit10ErrorHandler(int $errno, string $errstr, string $filename, int return true; // message suppressed - stop error handling } - throw new \Exception("$errstr $filename $lineno"); + throw new Exception("$errstr $filename $lineno"); } return false; // continue error handling @@ -55,7 +56,7 @@ function utf8decode(string $value, string $toEncoding = 'ISO-8859-1'): string return function_exists('mb_convert_encoding') ? mb_convert_encoding($value, $toEncoding, 'UTF-8') : utf8_decode($value); } -if (!method_exists(\PHPUnit\Framework\TestCase::class, 'setOutputCallback')) { +if (!method_exists(PHPUnit\Framework\TestCase::class, 'setOutputCallback')) { ini_set('error_reporting', (string) E_ALL); set_error_handler('phpunit10ErrorHandler'); } From 639f39635ab2c84a5e75b23a9e0c0127a61a320a Mon Sep 17 00:00:00 2001 From: Progi1984 <progi1984@gmail.com> Date: Wed, 8 Jan 2025 13:09:14 +0100 Subject: [PATCH 220/246] Autoload : Allow to use PHPWord without Composer (#2722) --- README.md | 1 - bootstrap.php | 28 -------- composer.json | 3 +- docs/changes/1.x/1.4.0.md | 1 + docs/install.md | 6 +- docs/usage/introduction.md | 1 - samples/Sample_45_Autoloader.php | 93 +++++++++++++++++++++++++++ samples/Sample_Header.php | 35 +++++----- src/PhpWord/Autoloader.php | 47 ++++++++++++++ tests/PhpWordTests/AutoloaderTest.php | 56 ++++++++++++++++ tests/bootstrap.php | 3 +- 11 files changed, 221 insertions(+), 53 deletions(-) delete mode 100644 bootstrap.php create mode 100644 samples/Sample_45_Autoloader.php create mode 100644 src/PhpWord/Autoloader.php create mode 100644 tests/PhpWordTests/AutoloaderTest.php diff --git a/README.md b/README.md index 96dd989970..e080d32da8 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,6 @@ The following is a basic usage example of the PHPWord library. ```php <?php -require_once 'bootstrap.php'; // Creating the new document... $phpWord = new \PhpOffice\PhpWord\PhpWord(); diff --git a/bootstrap.php b/bootstrap.php deleted file mode 100644 index 740e3d044c..0000000000 --- a/bootstrap.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php -/** - * This file is part of PHPWord - A pure PHP library for reading and writing - * word processing documents. - * - * PHPWord is free software distributed under the terms of the GNU Lesser - * General Public License version 3 as published by the Free Software Foundation. - * - * For the full copyright and license information, please read the LICENSE - * file that was distributed with this source code. For the full list of - * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. test bootstrap - * - * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2018 PHPWord contributors - * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 - */ - -$vendorDirPath = realpath(__DIR__ . '/vendor'); -if (file_exists($vendorDirPath . '/autoload.php')) { - require $vendorDirPath . '/autoload.php'; -} else { - throw new Exception( - sprintf( - 'Could not find file \'%s\'. It is generated by Composer. Use \'install --prefer-source\' or \'update --prefer-source\' Composer commands to move forward.', - $vendorDirPath . '/autoload.php' - ) - ); -} diff --git a/composer.json b/composer.json index eb4c83f1a3..efebe941e7 100644 --- a/composer.json +++ b/composer.json @@ -95,7 +95,8 @@ "php samples/Sample_41_TemplateSetChart.php", "php samples/Sample_42_TemplateSetCheckbox.php", "php samples/Sample_43_RTLDefault.php", - "php samples/Sample_44_ExtractVariablesFromReaderWord2007.php" + "php samples/Sample_44_ExtractVariablesFromReaderWord2007.php", + "php samples/Sample_45_Autoloader.php" ] }, "scripts-descriptions": { diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index a6461fba14..0a08848037 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -7,6 +7,7 @@ - Writer ODText: Support for ListItemRun by [@Progi1984](https://github.com/Progi1984) fixing [#2159](https://github.com/PHPOffice/PHPWord/issues/2159), [#2620](https://github.com/PHPOffice/PHPWord/issues/2620) in [#2669](https://github.com/PHPOffice/PHPWord/pull/2669) - Writer HTML: Support for vAlign in Tables by [@SpraxDev](https://github.com/SpraxDev) in [#2675](https://github.com/PHPOffice/PHPWord/pull/2675) - Added support for PHP 8.4 by [@Progi1984](https://github.com/Progi1984) in [#2660](https://github.com/PHPOffice/PHPWord/pull/2660) +- Autoload : Allow to use PHPWord without Composer fixing [#2543](https://github.com/PHPOffice/PHPWord/issues/2543), [#2552](https://github.com/PHPOffice/PHPWord/issues/2552), [#2716](https://github.com/PHPOffice/PHPWord/issues/2716), [#2717](https://github.com/PHPOffice/PHPWord/issues/2717) in [#2722](https://github.com/PHPOffice/PHPWord/pull/2722) ### Bug fixes diff --git a/docs/install.md b/docs/install.md index 1b54a3173f..a4d61b104d 100644 --- a/docs/install.md +++ b/docs/install.md @@ -32,7 +32,6 @@ To install via Composer, add the following lines to your `composer.json`: To install manually: * [download PHPOffice\PHPWord package from GitHub](https://github.com/PHPOffice/PHPWord/archive/master.zip) -* [download PHPOffice\Common package from GitHub](https://github.com/PHPOffice/Common/archive/master.zip) * extract the package and put the contents to your machine. @@ -42,11 +41,10 @@ To install manually: require_once 'path/to/PHPWord/src/PhpWord/Autoloader.php'; \PhpOffice\PhpWord\Autoloader::register(); -require_once 'path/to/PhpOffice/Common/src/Common/Autoloader.php'; -\PhpOffice\Common\Autoloader::register(); - ``` +The preferred method is the Composer one. + ## Samples After installation, you can browse and use the samples that we've provided, either by command line or using browser. If you can access your PhpWord library folder using browser, point your browser to the `samples` folder, e.g. `http://localhost/PhpWord/samples/`. diff --git a/docs/usage/introduction.md b/docs/usage/introduction.md index b3a101ab0d..7a3d153d95 100644 --- a/docs/usage/introduction.md +++ b/docs/usage/introduction.md @@ -7,7 +7,6 @@ are provided in the [samples folder](https://github.com/PHPOffice/PHPWord/tree/m ``` php <?php -require_once 'bootstrap.php'; // Creating the new document... $phpWord = new \PhpOffice\PhpWord\PhpWord(); diff --git a/samples/Sample_45_Autoloader.php b/samples/Sample_45_Autoloader.php new file mode 100644 index 0000000000..71f443f770 --- /dev/null +++ b/samples/Sample_45_Autoloader.php @@ -0,0 +1,93 @@ +<?php + +use PhpOffice\PhpWord\Style\Font; + +define('USE_AUTOLOADER', true); + +include_once 'Sample_Header.php'; + +// New Word Document +echo date('H:i:s') , ' Create new PhpWord object' , EOL; + +$languageEnGb = new PhpOffice\PhpWord\Style\Language(PhpOffice\PhpWord\Style\Language::EN_GB); + +$phpWord = new PhpOffice\PhpWord\PhpWord(); +$phpWord->getSettings()->setThemeFontLang($languageEnGb); + +$fontStyleName = 'rStyle'; +$phpWord->addFontStyle($fontStyleName, ['bold' => true, 'italic' => true, 'size' => 16, 'allCaps' => true, 'doubleStrikethrough' => true]); + +$paragraphStyleName = 'pStyle'; +$phpWord->addParagraphStyle($paragraphStyleName, ['alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER, 'spaceAfter' => 100]); + +$phpWord->addTitleStyle(1, ['bold' => true], ['spaceAfter' => 240]); + +// New portrait section +$section = $phpWord->addSection(); + +// Simple text +$section->addTitle('Welcome to PhpWord', 1); +$section->addText('Hello World!'); + +// $pStyle = new Font(); +// $pStyle->setLang() +$section->addText('Ce texte-ci est en français.', ['lang' => PhpOffice\PhpWord\Style\Language::FR_BE]); + +// Two text break +$section->addTextBreak(2); + +// Define styles +$section->addText('I am styled by a font style definition.', $fontStyleName); +$section->addText('I am styled by a paragraph style definition.', null, $paragraphStyleName); +$section->addText('I am styled by both font and paragraph style.', $fontStyleName, $paragraphStyleName); + +$section->addTextBreak(); + +// Inline font style +$fontStyle['name'] = 'Times New Roman'; +$fontStyle['size'] = 20; + +$textrun = $section->addTextRun(); +$textrun->addText('I am inline styled ', $fontStyle); +$textrun->addText('with '); +$textrun->addText('color', ['color' => '996699']); +$textrun->addText(', '); +$textrun->addText('bold', ['bold' => true]); +$textrun->addText(', '); +$textrun->addText('italic', ['italic' => true]); +$textrun->addText(', '); +$textrun->addText('underline', ['underline' => 'dash']); +$textrun->addText(', '); +$textrun->addText('strikethrough', ['strikethrough' => true]); +$textrun->addText(', '); +$textrun->addText('doubleStrikethrough', ['doubleStrikethrough' => true]); +$textrun->addText(', '); +$textrun->addText('superScript', ['superScript' => true]); +$textrun->addText(', '); +$textrun->addText('subScript', ['subScript' => true]); +$textrun->addText(', '); +$textrun->addText('smallCaps', ['smallCaps' => true]); +$textrun->addText(', '); +$textrun->addText('allCaps', ['allCaps' => true]); +$textrun->addText(', '); +$textrun->addText('fgColor', ['fgColor' => 'yellow']); +$textrun->addText(', '); +$textrun->addText('scale', ['scale' => 200]); +$textrun->addText(', '); +$textrun->addText('spacing', ['spacing' => 120]); +$textrun->addText(', '); +$textrun->addText('kerning', ['kerning' => 10]); +$textrun->addText('. '); + +// Link +$section->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub'); +$section->addTextBreak(); + +// Image +$section->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 18, 'height' => 18]); + +// Save file +echo write($phpWord, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/samples/Sample_Header.php b/samples/Sample_Header.php index 679848ad83..eab7033275 100644 --- a/samples/Sample_Header.php +++ b/samples/Sample_Header.php @@ -1,5 +1,19 @@ <?php -require_once __DIR__ . '/../bootstrap.php'; + +$vendorDirPath = realpath(__DIR__ . '/../vendor'); + +if ((defined('USE_AUTOLOADER') && USE_AUTOLOADER == true) + || !file_exists($vendorDirPath . '/autoload.php')) { + // PhpWord + require_once __DIR__ . '/../src/PhpWord/Autoloader.php'; + PhpOffice\PhpWord\Autoloader::register(); +} else { + require $vendorDirPath . '/autoload.php'; + $dompdfPath = $vendorDirPath . '/dompdf/dompdf'; + if (file_exists($dompdfPath)) { + define('DOMPDF_ENABLE_AUTOLOAD', false); + } +} use PhpOffice\PhpWord\Settings; @@ -12,9 +26,7 @@ Settings::loadConfig(); -$dompdfPath = $vendorDirPath . '/dompdf/dompdf'; -if (file_exists($dompdfPath)) { - define('DOMPDF_ENABLE_AUTOLOAD', false); +if (defined('DOMPDF_ENABLE_AUTOLOAD')) { Settings::setPdfRenderer(Settings::PDF_RENDERER_DOMPDF, $vendorDirPath . '/dompdf/dompdf'); } @@ -60,14 +72,8 @@ /** * Write documents. - * - * @param PhpOffice\PhpWord\PhpWord $phpWord - * @param string $filename - * @param array $writers - * - * @return string */ -function write($phpWord, $filename, $writers) +function write(PhpOffice\PhpWord\PhpWord $phpWord, string $filename, array $writers): string { $result = ''; @@ -90,13 +96,8 @@ function write($phpWord, $filename, $writers) /** * Get ending notes. - * - * @param array $writers - * @param mixed $filename - * - * @return string */ -function getEndingNotes($writers, $filename) +function getEndingNotes(array $writers, string $filename): string { $result = ''; diff --git a/src/PhpWord/Autoloader.php b/src/PhpWord/Autoloader.php new file mode 100644 index 0000000000..122d9c05fd --- /dev/null +++ b/src/PhpWord/Autoloader.php @@ -0,0 +1,47 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ +declare(strict_types=1); + +namespace PhpOffice\PhpWord; + +class Autoloader +{ + /** @const string */ + const NAMESPACE_PREFIX = 'PhpOffice\\PhpWord\\'; + + public static function register(): void + { + spl_autoload_register([new self(), 'autoload']); + } + + public static function autoload(string $class): void + { + $prefixLength = strlen(self::NAMESPACE_PREFIX); + if (0 === strncmp(self::NAMESPACE_PREFIX, $class, $prefixLength)) { + $file = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, $prefixLength)); + $file = realpath(__DIR__ . (empty($file) ? '' : DIRECTORY_SEPARATOR) . $file . '.php'); + if (!$file) { + return; + } + if (file_exists($file)) { + /** @noinspection PhpIncludeInspection Dynamic includes */ + require_once $file; + } + } + } +} diff --git a/tests/PhpWordTests/AutoloaderTest.php b/tests/PhpWordTests/AutoloaderTest.php new file mode 100644 index 0000000000..076bc8ebca --- /dev/null +++ b/tests/PhpWordTests/AutoloaderTest.php @@ -0,0 +1,56 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWordTests; + +use PhpOffice\PhpWord\Autoloader; +use PHPUnit\Framework\TestCase; + +/** + * Test class for PhpOffice\PhpWord\Autoloader. + */ +class AutoloaderTest extends TestCase +{ + public function testRegister(): void + { + Autoloader::register(); + $splFunctions = spl_autoload_functions(); + // @phpstan-ignore-next-line spl_autoload_functions return false < PHP 8.0 + if ($splFunctions === false) { + $splFunctions = []; + } + + self::assertContains( + ['PhpOffice\\PhpWord\\Autoloader', 'autoload'], + $splFunctions + ); + } + + public function testAutoload(): void + { + $declared = get_declared_classes(); + $declaredCount = count($declared); + Autoloader::autoload('Foo'); + self::assertCount( + $declaredCount, + get_declared_classes(), + 'PhpOffice\\PhpWord\\Autoloader::autoload() is trying to load ' . + 'classes outside of the PhpOffice\\PhpWord namespace' + ); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index e6dabe8f7f..7c4e0a3e1b 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -15,7 +15,8 @@ * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ -require_once __DIR__ . '/../bootstrap.php'; + +require dirname(__DIR__) . '/vendor/autoload.php'; date_default_timezone_set('UTC'); From f9da10ecd51696fe3e9291c5bbe44d3ba737cff8 Mon Sep 17 00:00:00 2001 From: Progi1984 <progi1984@gmail.com> Date: Tue, 14 Jan 2025 13:19:05 +0100 Subject: [PATCH 221/246] Reader HTML: Support for differents size units for table (#2725) --- docs/changes/1.x/1.4.0.md | 1 + src/PhpWord/Shared/Html.php | 52 +++++++++++------------ tests/PhpWordTests/Shared/HtmlTest.php | 57 ++++++++++++++++++++------ 3 files changed, 68 insertions(+), 42 deletions(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 0a08848037..c191fea948 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -13,6 +13,7 @@ - Writer ODText: Support for images inside a textRun by [@Progi1984](https://github.com/Progi1984) fixing [#2240](https://github.com/PHPOffice/PHPWord/issues/2240) in [#2668](https://github.com/PHPOffice/PHPWord/pull/2668) - Allow vAlign and vMerge on Style\Cell to be set to null by [@SpraxDev](https://github.com/SpraxDev) fixing [#2673](https://github.com/PHPOffice/PHPWord/issues/2673) in [#2676](https://github.com/PHPOffice/PHPWord/pull/2676) +- Reader HTML: Support for differents size units for table by [@Progi1984](https://github.com/Progi1984) fixing [#2384](https://github.com/PHPOffice/PHPWord/issues/2384), [#2701](https://github.com/PHPOffice/PHPWord/issues/2701) in [#2725](https://github.com/PHPOffice/PHPWord/pull/2725) ### Miscellaneous diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 36a66f4110..11a6b39d54 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -128,21 +128,21 @@ protected static function parseInlineStyle($node, $styles = []) break; case 'width': // tables, cells + $val = $val === 'auto' ? '100%' : $val; if (false !== strpos($val, '%')) { // e.g. <table width="100%"> or <td width="50%"> $styles['width'] = (int) $val * 50; $styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::PERCENT; } else { // e.g. <table width="250> where "250" = 250px (always pixels) - $styles['width'] = Converter::pixelToTwip($val); + $styles['width'] = Converter::pixelToTwip(self::convertHtmlSize($val)); $styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::TWIP; } break; case 'cellspacing': // tables e.g. <table cellspacing="2">, where "2" = 2px (always pixels) - $val = (int) $val . 'px'; - $styles['cellSpacing'] = Converter::cssToTwip($val); + $styles['cellSpacing'] = Converter::pixelToTwip(self::convertHtmlSize($val)); break; case 'bgcolor': @@ -902,36 +902,12 @@ protected static function parseImage($node, $element) break; case 'width': - $width = $attribute->value; - - // pt - if (false !== strpos($width, 'pt')) { - $width = Converter::pointToPixel((float) str_replace('pt', '', $width)); - } - - // px - if (false !== strpos($width, 'px')) { - $width = str_replace('px', '', $width); - } - - $style['width'] = $width; + $style['width'] = self::convertHtmlSize($attribute->value); $style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX; break; case 'height': - $height = $attribute->value; - - // pt - if (false !== strpos($height, 'pt')) { - $height = Converter::pointToPixel((float) str_replace('pt', '', $height)); - } - - // px - if (false !== strpos($height, 'px')) { - $height = str_replace('px', '', $height); - } - - $style['height'] = $height; + $style['height'] = self::convertHtmlSize($attribute->value); $style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX; break; @@ -1211,4 +1187,22 @@ private static function convertRgb(string $rgb): string return trim($rgb, '# '); } + + /** + * Transform HTML sizes (pt, px) in pixels. + */ + protected static function convertHtmlSize(string $size): float + { + // pt + if (false !== strpos($size, 'pt')) { + return Converter::pointToPixel((float) str_replace('pt', '', $size)); + } + + // px + if (false !== strpos($size, 'px')) { + return (float) str_replace('px', '', $size); + } + + return (float) $size; + } } diff --git a/tests/PhpWordTests/Shared/HtmlTest.php b/tests/PhpWordTests/Shared/HtmlTest.php index e6a0bd4953..3869f9608d 100644 --- a/tests/PhpWordTests/Shared/HtmlTest.php +++ b/tests/PhpWordTests/Shared/HtmlTest.php @@ -25,6 +25,7 @@ use PhpOffice\PhpWord\Shared\Html; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\SimpleType\LineSpacingRule; +use PhpOffice\PhpWord\SimpleType\TblWidth; use PhpOffice\PhpWord\Style\Paragraph; use PhpOffice\PhpWordTests\AbstractWebServerEmbedded; use PhpOffice\PhpWordTests\TestHelperDOCX; @@ -156,11 +157,11 @@ public function testParseStyleTableClassName(): void } /** - * Test underline. + * Test text-decoration style. */ - public function testParseUnderline(): void + public function testParseTextDecoration(): void { - $html = '<u>test</u>'; + $html = '<span style="text-decoration: underline;">test</span>'; $phpWord = new PhpWord(); $section = $phpWord->addSection(); Html::addHtml($section, $html); @@ -171,11 +172,11 @@ public function testParseUnderline(): void } /** - * Test text-decoration style. + * Test underline. */ - public function testParseTextDecoration(): void + public function testParseUnderline(): void { - $html = '<span style="text-decoration: underline;">test</span>'; + $html = '<u>test</u>'; $phpWord = new PhpWord(); $section = $phpWord->addSection(); Html::addHtml($section, $html); @@ -185,6 +186,25 @@ public function testParseTextDecoration(): void self::assertEquals('single', $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:rPr/w:u', 'w:val')); } + /** + * Test width. + * + * @dataProvider providerParseWidth + */ + public function testParseWidth(string $htmlSize, float $docxSize, string $docxUnit): void + { + $html = '<table width="' . $htmlSize . '"><tr><td>A</td></tr></table>'; + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + + Html::addHtml($section, $html); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + $xpath = '/w:document/w:body/w:tbl/w:tblPr/w:tblW'; + self::assertTrue($doc->elementExists($xpath)); + self::assertEquals($docxSize, $doc->getElement($xpath)->getAttribute('w:w')); + self::assertEquals($docxUnit, $doc->getElement($xpath)->getAttribute('w:type')); + } + /** * Test font-variant style. */ @@ -461,31 +481,31 @@ public function testParseTableAndCellWidth(): void $xpath = '/w:document/w:body/w:tbl/w:tblGrid/w:gridCol'; self::assertTrue($doc->elementExists($xpath)); self::assertEquals(25 * 50, $doc->getElement($xpath)->getAttribute('w:w')); - self::assertEquals('dxa', $doc->getElement($xpath)->getAttribute('w:type')); + self::assertEquals(TblWidth::TWIP, $doc->getElement($xpath)->getAttribute('w:type')); // <td style="width: 25%; ... $xpath = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tcPr/w:tcW'; self::assertTrue($doc->elementExists($xpath)); self::assertEquals(25 * 50, $doc->getElement($xpath)->getAttribute('w:w')); - self::assertEquals('pct', $doc->getElement($xpath)->getAttribute('w:type')); + self::assertEquals(TblWidth::PERCENT, $doc->getElement($xpath)->getAttribute('w:type')); // <table width="400" .. 400px = 6000 twips (400 / 96 * 1440) $xpath = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tbl/w:tr/w:tc/w:tcPr/w:tcW'; self::assertTrue($doc->elementExists($xpath)); self::assertEquals(6000, $doc->getElement($xpath)->getAttribute('w:w')); - self::assertEquals('dxa', $doc->getElement($xpath)->getAttribute('w:type')); + self::assertEquals(TblWidth::TWIP, $doc->getElement($xpath)->getAttribute('w:type')); // <th style="width: 50pt; .. 50pt = 750 twips (50 / 72 * 1440) $xpath = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tbl/w:tr[2]/w:tc[2]/w:tcPr/w:tcW'; self::assertTrue($doc->elementExists($xpath)); self::assertEquals(1000, $doc->getElement($xpath)->getAttribute('w:w')); - self::assertEquals('dxa', $doc->getElement($xpath)->getAttribute('w:type')); + self::assertEquals(TblWidth::TWIP, $doc->getElement($xpath)->getAttribute('w:type')); // <th width="300" .. 300px = 4500 twips (300 / 96 * 1440) $xpath = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tbl/w:tr[3]/w:tc/w:tcPr/w:tcW'; self::assertTrue($doc->elementExists($xpath)); self::assertEquals(4500, $doc->getElement($xpath)->getAttribute('w:w')); - self::assertEquals('dxa', $doc->getElement($xpath)->getAttribute('w:type')); + self::assertEquals(TblWidth::TWIP, $doc->getElement($xpath)->getAttribute('w:type')); } /** @@ -599,7 +619,7 @@ public function testParseTableCellspacingRowBgColor(): void $xpath = '/w:document/w:body/w:tbl/w:tblPr/w:tblCellSpacing'; self::assertTrue($doc->elementExists($xpath)); self::assertEquals(3 * 15, $doc->getElement($xpath)->getAttribute('w:w')); - self::assertEquals('dxa', $doc->getElement($xpath)->getAttribute('w:type')); + self::assertEquals(TblWidth::TWIP, $doc->getElement($xpath)->getAttribute('w:type')); $xpath = '/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:tcPr/w:shd'; self::assertTrue($doc->elementExists($xpath)); @@ -632,7 +652,7 @@ public function testParseTableStyleAttributeInlineStyle(): void $xpath = '/w:document/w:body/w:tbl/w:tblPr/w:tblW'; self::assertTrue($doc->elementExists($xpath)); self::assertEquals(100 * 50, $doc->getElement($xpath)->getAttribute('w:w')); - self::assertEquals('pct', $doc->getElement($xpath)->getAttribute('w:type')); + self::assertEquals(TblWidth::PERCENT, $doc->getElement($xpath)->getAttribute('w:type')); $xpath = '/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:tcPr/w:shd'; self::assertTrue($doc->elementExists($xpath)); @@ -1225,4 +1245,15 @@ public function testDontDecodeAlreadyEncodedDoubleQuotes(): void $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); self::assertIsObject($doc); } + + public static function providerParseWidth(): array + { + return [ + ['auto', 5000, TblWidth::PERCENT], + ['100%', 5000, TblWidth::PERCENT], + ['200pt', 3999.999999999999, TblWidth::TWIP], + ['300px', 4500, TblWidth::TWIP], + ['400', 6000, TblWidth::TWIP], + ]; + } } From 337dc27f4b08ffce1aae0f749ebeae942dd4806a Mon Sep 17 00:00:00 2001 From: Jui-Nan Lin <jnlinn@gmail.com> Date: Wed, 15 Jan 2025 14:25:15 +0800 Subject: [PATCH 222/246] feat(font): add default asian font name (#2714) * feat(font): add default asian font name * doc: examples and changes * test: add test for DefaultAsianFontName * fix: specify the return value type Co-authored-by: Progi1984 <progi1984@gmail.com> * test: test set/get function in PHPWord * style: removed unused annotiation --------- Co-authored-by: Jui-Nan Lin <eric@writepath.co> Co-authored-by: Progi1984 <progi1984@gmail.com> --- docs/changes/1.x/1.4.0.md | 2 ++ docs/usage/introduction.md | 10 +++++++- src/PhpWord/PhpWord.php | 18 ++++++++++++++ src/PhpWord/Settings.php | 26 +++++++++++++++++++++ src/PhpWord/Writer/Word2007/Part/Styles.php | 3 ++- tests/PhpWordTests/PhpWordTest.php | 12 ++++++++++ tests/PhpWordTests/SettingsTest.php | 14 +++++++++++ 7 files changed, 83 insertions(+), 2 deletions(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index c191fea948..1c1557a940 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -4,6 +4,8 @@ ## Enhancements +- Default Font: Allow specify Asisn font and Latin font separately + - Writer ODText: Support for ListItemRun by [@Progi1984](https://github.com/Progi1984) fixing [#2159](https://github.com/PHPOffice/PHPWord/issues/2159), [#2620](https://github.com/PHPOffice/PHPWord/issues/2620) in [#2669](https://github.com/PHPOffice/PHPWord/pull/2669) - Writer HTML: Support for vAlign in Tables by [@SpraxDev](https://github.com/SpraxDev) in [#2675](https://github.com/PHPOffice/PHPWord/pull/2675) - Added support for PHP 8.4 by [@Progi1984](https://github.com/Progi1984) in [#2660](https://github.com/PHPOffice/PHPWord/pull/2660) diff --git a/docs/usage/introduction.md b/docs/usage/introduction.md index 7a3d153d95..6aa42aaae0 100644 --- a/docs/usage/introduction.md +++ b/docs/usage/introduction.md @@ -137,6 +137,14 @@ $phpWord->setDefaultFontName('Times New Roman'); $phpWord->setDefaultFontSize(12); ``` +Or you can specify Asian Font + +``` php +<?php + +$phpWord->setDefaultAsianFontName('標楷體'); +``` + ## Document settings Settings for the generated document can be set using ``$phpWord->getSettings()`` @@ -380,4 +388,4 @@ To control whether or not words in all capital letters shall be hyphenated use t <?php $phpWord->getSettings()->setDoNotHyphenateCaps(true); -``` \ No newline at end of file +``` diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index f96bdcf401..aa62a76f0d 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -257,6 +257,24 @@ public function setDefaultFontName($fontName): void Settings::setDefaultFontName($fontName); } + /** + * Get default asian font name. + */ + public function getDefaultAsianFontName(): string + { + return Settings::getDefaultAsianFontName(); + } + + /** + * Set default font name. + * + * @param string $fontName + */ + public function setDefaultAsianFontName($fontName): void + { + Settings::setDefaultAsianFontName($fontName); + } + /** * Get default font size. * diff --git a/src/PhpWord/Settings.php b/src/PhpWord/Settings.php index a2c461e29a..0cbfed7988 100644 --- a/src/PhpWord/Settings.php +++ b/src/PhpWord/Settings.php @@ -118,6 +118,13 @@ class Settings */ private static $defaultFontName = self::DEFAULT_FONT_NAME; + /** + * Default font name. + * + * @var string + */ + private static $defaultAsianFontName = self::DEFAULT_FONT_NAME; + /** * Default font size. * @@ -355,6 +362,14 @@ public static function getDefaultFontName(): string return self::$defaultFontName; } + /** + * Get default font name. + */ + public static function getDefaultAsianFontName(): string + { + return self::$defaultAsianFontName; + } + /** * Set default font name. */ @@ -369,6 +384,17 @@ public static function setDefaultFontName(string $value): bool return false; } + public static function setDefaultAsianFontName(string $value): bool + { + if (trim($value) !== '') { + self::$defaultAsianFontName = $value; + + return true; + } + + return false; + } + /** * Get default font size. * diff --git a/src/PhpWord/Writer/Word2007/Part/Styles.php b/src/PhpWord/Writer/Word2007/Part/Styles.php index bda1e653b7..c57c1e58be 100644 --- a/src/PhpWord/Writer/Word2007/Part/Styles.php +++ b/src/PhpWord/Writer/Word2007/Part/Styles.php @@ -84,6 +84,7 @@ private function writeDefaultStyles(XMLWriter $xmlWriter, $styles): void { $phpWord = $this->getParentWriter()->getPhpWord(); $fontName = $phpWord->getDefaultFontName(); + $asianFontName = $phpWord->getDefaultAsianFontName(); $fontSize = $phpWord->getDefaultFontSize(); $language = $phpWord->getSettings()->getThemeFontLang(); $latinLanguage = ($language == null || $language->getLatin() === null) ? 'en-US' : $language->getLatin(); @@ -95,7 +96,7 @@ private function writeDefaultStyles(XMLWriter $xmlWriter, $styles): void $xmlWriter->startElement('w:rFonts'); $xmlWriter->writeAttribute('w:ascii', $fontName); $xmlWriter->writeAttribute('w:hAnsi', $fontName); - $xmlWriter->writeAttribute('w:eastAsia', $fontName); + $xmlWriter->writeAttribute('w:eastAsia', $asianFontName); $xmlWriter->writeAttribute('w:cs', $fontName); $xmlWriter->endElement(); // w:rFonts $xmlWriter->startElement('w:sz'); diff --git a/tests/PhpWordTests/PhpWordTest.php b/tests/PhpWordTests/PhpWordTest.php index 9ad7b02574..d194f4895d 100644 --- a/tests/PhpWordTests/PhpWordTest.php +++ b/tests/PhpWordTests/PhpWordTest.php @@ -83,6 +83,18 @@ public function testSetGetDefaultFontSize(): void self::assertEquals($fontSize, $phpWord->getDefaultFontSize()); } + /** + * Test set/get default asian font name. + */ + public function testSetGetDefaultAsianFontName(): void + { + $phpWord = new PhpWord(); + $fontName = 'Times New Roman'; + self::assertEquals(Settings::DEFAULT_FONT_NAME, $phpWord->getDefaultAsianFontName()); + $phpWord->setDefaultAsianFontName($fontName); + self::assertEquals($fontName, $phpWord->getDefaultAsianFontName()); + } + /** * Test set default paragraph style. */ diff --git a/tests/PhpWordTests/SettingsTest.php b/tests/PhpWordTests/SettingsTest.php index 67099650aa..cf8e12b205 100644 --- a/tests/PhpWordTests/SettingsTest.php +++ b/tests/PhpWordTests/SettingsTest.php @@ -217,6 +217,20 @@ public function testSetGetDefaultFontName(): void self::assertEquals('Times New Roman', Settings::getDefaultFontName()); } + /** + * Test set/get default font name. + */ + public function testSetGetDefaultAsianFontName(): void + { + self::assertEquals(Settings::DEFAULT_FONT_NAME, Settings::getDefaultAsianFontName()); + self::assertFalse(Settings::setDefaultAsianFontName(' ')); + self::assertEquals(Settings::DEFAULT_FONT_NAME, Settings::getDefaultAsianFontName()); + self::assertTrue(Settings::setDefaultAsianFontName('Times New Roman')); + self::assertEquals('Times New Roman', Settings::getDefaultAsianFontName()); + self::assertFalse(Settings::setDefaultAsianFontName(' ')); + self::assertEquals('Times New Roman', Settings::getDefaultAsianFontName()); + } + /** * Test set/get default font size. */ From 136f5499fc2ada425f5742127683af6f336cc309 Mon Sep 17 00:00:00 2001 From: Progi1984 <progi1984@gmail.com> Date: Wed, 22 Jan 2025 13:22:21 +0100 Subject: [PATCH 223/246] Reader Word2007 : Respect paragraph indent units (#2726) Co-authored-by: Maksim Tiugaev <tugmaks@yandex.ru> --- docs/changes/1.x/1.4.0.md | 6 + src/PhpWord/Reader/Word2007/AbstractPart.php | 6 +- src/PhpWord/Style/AbstractStyle.php | 3 +- src/PhpWord/Style/Indentation.php | 58 ++----- src/PhpWord/Style/Paragraph.php | 114 ++++++++++---- .../Reader/Word2007/StyleTest.php | 47 +++++- tests/PhpWordTests/Style/ParagraphTest.php | 149 ++++++++++++++++++ 7 files changed, 308 insertions(+), 75 deletions(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 1c1557a940..d1fa6cba99 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -16,10 +16,16 @@ - Writer ODText: Support for images inside a textRun by [@Progi1984](https://github.com/Progi1984) fixing [#2240](https://github.com/PHPOffice/PHPWord/issues/2240) in [#2668](https://github.com/PHPOffice/PHPWord/pull/2668) - Allow vAlign and vMerge on Style\Cell to be set to null by [@SpraxDev](https://github.com/SpraxDev) fixing [#2673](https://github.com/PHPOffice/PHPWord/issues/2673) in [#2676](https://github.com/PHPOffice/PHPWord/pull/2676) - Reader HTML: Support for differents size units for table by [@Progi1984](https://github.com/Progi1984) fixing [#2384](https://github.com/PHPOffice/PHPWord/issues/2384), [#2701](https://github.com/PHPOffice/PHPWord/issues/2701) in [#2725](https://github.com/PHPOffice/PHPWord/pull/2725) +- Reader Word2007 : Respect paragraph indent units by [@tugmaks](https://github.com/tugmaks) & [@Progi1984](https://github.com/Progi1984) fixing [#507](https://github.com/PHPOffice/PHPWord/issues/507) in [#2726](https://github.com/PHPOffice/PHPWord/pull/2726) ### Miscellaneous - Bump dompdf/dompdf from 2.0.4 to 3.0.0 by [@dependabot](https://github.com/dependabot) fixing [#2621](https://github.com/PHPOffice/PHPWord/issues/2621) in [#2666](https://github.com/PHPOffice/PHPWord/pull/2666) - Add test case to make sure vMerge defaults to 'continue' by [@SpraxDev](https://github.com/SpraxDev) in [#2677](https://github.com/PHPOffice/PHPWord/pull/2677) +### Deprecations +- Deprecate `PhpOffice\PhpWord\Style\Paragraph::getIndent()` : Use `PhpOffice\PhpWord\Style\Paragraph::getIndentLeft()` +- Deprecate `PhpOffice\PhpWord\Style\Paragraph::setHanging()` : Use `PhpOffice\PhpWord\Style\Paragraph::setIndentHanging()` +- Deprecate `PhpOffice\PhpWord\Style\Paragraph::setIndent()` : Use `PhpOffice\PhpWord\Style\Paragraph::setIndentLeft()` + ### BC Breaks diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 12ef96d287..d14ca603e7 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -662,8 +662,10 @@ protected function readParagraphStyle(XMLReader $xmlReader, DOMElement $domNode) 'alignment' => [self::READ_VALUE, 'w:jc'], 'basedOn' => [self::READ_VALUE, 'w:basedOn'], 'next' => [self::READ_VALUE, 'w:next'], - 'indent' => [self::READ_VALUE, 'w:ind', 'w:left'], - 'hanging' => [self::READ_VALUE, 'w:ind', 'w:hanging'], + 'indentLeft' => [self::READ_VALUE, 'w:ind', 'w:left'], + 'indentRight' => [self::READ_VALUE, 'w:ind', 'w:right'], + 'indentHanging' => [self::READ_VALUE, 'w:ind', 'w:hanging'], + 'indentFirstLine' => [self::READ_VALUE, 'w:ind', 'w:firstLine'], 'spaceAfter' => [self::READ_VALUE, 'w:spacing', 'w:after'], 'spaceBefore' => [self::READ_VALUE, 'w:spacing', 'w:before'], 'widowControl' => [self::READ_FALSE, 'w:widowControl'], diff --git a/src/PhpWord/Style/AbstractStyle.php b/src/PhpWord/Style/AbstractStyle.php index 3d883978dd..338ae6a5ef 100644 --- a/src/PhpWord/Style/AbstractStyle.php +++ b/src/PhpWord/Style/AbstractStyle.php @@ -317,12 +317,11 @@ protected function setEnumVal($value = null, $enum = [], $default = null) * Set object value. * * @param mixed $value - * @param string $styleName * @param mixed &$style * * @return mixed */ - protected function setObjectVal($value, $styleName, &$style) + protected function setObjectVal($value, string $styleName, &$style) { $styleClass = substr(static::class, 0, (int) strrpos(static::class, '\\')) . '\\' . $styleName; if (is_array($value)) { diff --git a/src/PhpWord/Style/Indentation.php b/src/PhpWord/Style/Indentation.php index 22b8f44c0b..c2032dd22f 100644 --- a/src/PhpWord/Style/Indentation.php +++ b/src/PhpWord/Style/Indentation.php @@ -29,30 +29,30 @@ class Indentation extends AbstractStyle /** * Left indentation (twip). * - * @var float|int + * @var null|float */ private $left = 0; /** * Right indentation (twip). * - * @var float|int + * @var null|float */ private $right = 0; /** * Additional first line indentation (twip). * - * @var float|int + * @var null|float */ private $firstLine = 0; /** * Indentation removed from first line (twip). * - * @var float|int + * @var null|float */ - private $hanging; + private $hanging = 0; /** * Create a new instance. @@ -66,96 +66,72 @@ public function __construct($style = []) /** * Get left. - * - * @return float|int */ - public function getLeft() + public function getLeft(): ?float { return $this->left; } /** * Set left. - * - * @param float|int $value - * - * @return self */ - public function setLeft($value) + public function setLeft(?float $value): self { - $this->left = $this->setNumericVal($value, $this->left); + $this->left = $this->setNumericVal($value); return $this; } /** * Get right. - * - * @return float|int */ - public function getRight() + public function getRight(): ?float { return $this->right; } /** * Set right. - * - * @param float|int $value - * - * @return self */ - public function setRight($value) + public function setRight(?float $value): self { - $this->right = $this->setNumericVal($value, $this->right); + $this->right = $this->setNumericVal($value); return $this; } /** * Get first line. - * - * @return float|int */ - public function getFirstLine() + public function getFirstLine(): ?float { return $this->firstLine; } /** * Set first line. - * - * @param float|int $value - * - * @return self */ - public function setFirstLine($value) + public function setFirstLine(?float $value): self { - $this->firstLine = $this->setNumericVal($value, $this->firstLine); + $this->firstLine = $this->setNumericVal($value); return $this; } /** * Get hanging. - * - * @return float|int */ - public function getHanging() + public function getHanging(): ?float { return $this->hanging; } /** * Set hanging. - * - * @param float|int $value - * - * @return self */ - public function setHanging($value = null) + public function setHanging(?float $value = null): self { - $this->hanging = $this->setNumericVal($value, $this->hanging); + $this->hanging = $this->setNumericVal($value); return $this; } diff --git a/src/PhpWord/Style/Paragraph.php b/src/PhpWord/Style/Paragraph.php index 43acedaee2..5dda985fe5 100644 --- a/src/PhpWord/Style/Paragraph.php +++ b/src/PhpWord/Style/Paragraph.php @@ -322,74 +322,132 @@ public function setNext($value = null) return $this; } + /** + * Get hanging. + */ + public function getHanging(): ?float + { + return $this->getChildStyleValue($this->indentation, 'hanging'); + } + /** * Get indentation. * - * @return null|Indentation + * @deprecated 1.4.0 Use getIndentLeft */ - public function getIndentation() + public function getIndent(): ?float + { + return $this->getChildStyleValue($this->indentation, 'left'); + } + + /** + * Get indentation. + */ + public function getIndentation(): ?Indentation { return $this->indentation; } /** - * Set shading. - * - * @param mixed $value - * - * @return self + * Get firstLine. */ - public function setIndentation($value = null) + public function getIndentFirstLine(): ?float { - $this->setObjectVal($value, 'Indentation', $this->indentation); + return $this->getChildStyleValue($this->indentation, 'firstLine'); + } - return $this; + /** + * Get left indentation. + */ + public function getIndentLeft(): ?float + { + return $this->getChildStyleValue($this->indentation, 'left'); } /** - * Get indentation. + * Get right indentation. + */ + public function getIndentRight(): ?float + { + return $this->getChildStyleValue($this->indentation, 'right'); + } + + /** + * Set hanging. * - * @return int + * @deprecated 1.4.0 Use setIndentHanging */ - public function getIndent() + public function setHanging(?float $value = null): self { - return $this->getChildStyleValue($this->indentation, 'left'); + return $this->setIndentation(['hanging' => $value]); } /** * Set indentation. * - * @param int $value - * - * @return self + * @deprecated 1.4.0 Use setIndentLeft */ - public function setIndent($value = null) + public function setIndent(?float $value = null): self { return $this->setIndentation(['left' => $value]); } /** - * Get hanging. + * Set indentation. * - * @return int + * @param array{ + * left?:null|float|int|numeric-string, + * right?:null|float|int|numeric-string, + * hanging?:null|float|int|numeric-string, + * firstLine?:null|float|int|numeric-string + * } $value */ - public function getHanging() + public function setIndentation(array $value = []): self { - return $this->getChildStyleValue($this->indentation, 'hanging'); + $value = array_map(function ($indent) { + if (is_string($indent) || is_numeric($indent)) { + $indent = $this->setFloatVal($indent); + } + + return $indent; + }, $value); + $this->setObjectVal($value, 'Indentation', $this->indentation); + + return $this; } /** - * Set hanging. - * - * @param int $value - * - * @return self + * Set hanging indentation. */ - public function setHanging($value = null) + public function setIndentHanging(?float $value = null): self { return $this->setIndentation(['hanging' => $value]); } + /** + * Set firstline indentation. + */ + public function setIndentFirstLine(?float $value = null): self + { + return $this->setIndentation(['firstLine' => $value]); + } + + /** + * Set left indentation. + */ + public function setIndentLeft(?float $value = null): self + { + return $this->setIndentation(['left' => $value]); + } + + /** + * Set right indentation. + */ + public function setIndentRight(?float $value = null): self + { + return $this->setIndentation(['right' => $value]); + } + /** * Get spacing. * diff --git a/tests/PhpWordTests/Reader/Word2007/StyleTest.php b/tests/PhpWordTests/Reader/Word2007/StyleTest.php index 006e6ff01f..347c0350f9 100644 --- a/tests/PhpWordTests/Reader/Word2007/StyleTest.php +++ b/tests/PhpWordTests/Reader/Word2007/StyleTest.php @@ -18,6 +18,8 @@ namespace PhpOffice\PhpWordTests\Reader\Word2007; +use Generator; +use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\SimpleType\Border; use PhpOffice\PhpWord\SimpleType\TblWidth; use PhpOffice\PhpWord\SimpleType\VerticalJc; @@ -221,7 +223,7 @@ public function testReadPosition(): void $phpWord = $this->getDocumentFromString(['document' => $documentXml]); $elements = $phpWord->getSection(0)->getElements(); - /** @var \PhpOffice\PhpWord\Element\TextRun $elements */ + /** @var TextRun $elements */ $textRun = $elements[0]; self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $textRun); self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(0)); @@ -282,7 +284,7 @@ public function testReadHidden(): void $phpWord = $this->getDocumentFromString(['document' => $documentXml]); $elements = $phpWord->getSection(0)->getElements(); - /** @var \PhpOffice\PhpWord\Element\TextRun $elements */ + /** @var TextRun $elements */ $textRun = $elements[0]; self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $textRun); self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(0)); @@ -328,4 +330,45 @@ public function testPageVerticalAlign(): void $sectionStyle = $phpWord->getSection(0)->getStyle(); self::assertEquals(VerticalJc::CENTER, $sectionStyle->getVAlign()); } + + /** + * @dataProvider providerIndentation + */ + public function testIndentation(string $indent, float $left, float $right, ?float $hanging, float $firstLine): void + { + $documentXml = "<w:p> + <w:pPr> + $indent + </w:pPr> + <w:r> + <w:t>1.</w:t> + </w:r> + </w:p>"; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $section = $phpWord->getSection(0); + $textRun = $section->getElements()[0]; + self::assertInstanceOf(TextRun::class, $textRun); + + $paragraphStyle = $textRun->getParagraphStyle(); + self::assertInstanceOf(Style\Paragraph::class, $paragraphStyle); + + $indentation = $paragraphStyle->getIndentation(); + self::assertSame($left, $indentation->getLeft()); + self::assertSame($right, $indentation->getRight()); + self::assertSame($hanging, $indentation->getHanging()); + self::assertSame($firstLine, $indentation->getFirstLine()); + } + + /** + * @return Generator<array{0:string, 1:float, 2:float, 3:null|float, 4: float}> + */ + public static function providerIndentation() + { + yield ['<w:ind w:left="709" w:right="488" w:hanging="10" w:firstLine="490"/>', 709.00, 488.00, 10.0, 490.00]; + yield ['<w:ind w:hanging="10" w:firstLine="490"/>', 0, 0, 10.0, 490.00]; + yield ['<w:ind w:left="709"/>', 709.00, 0, 0, 0]; + yield ['<w:ind w:right="488"/>', 0, 488.00, 0, 0]; + } } diff --git a/tests/PhpWordTests/Style/ParagraphTest.php b/tests/PhpWordTests/Style/ParagraphTest.php index f99107a93b..6a6e777cfc 100644 --- a/tests/PhpWordTests/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Style/ParagraphTest.php @@ -144,6 +144,155 @@ public function testTabs(): void self::assertCount(2, $object->getTabs()); } + public function testHanging(): void + { + $rand = mt_rand(0, 255); + + $object = new Paragraph(); + self::assertNull($object->getHanging()); + self::assertInstanceOf(Paragraph::class, $object->setHanging($rand)); + self::assertEquals($rand, $object->getHanging()); + self::assertInstanceOf(Paragraph::class, $object->setHanging(null)); + self::assertNull($object->getHanging()); + self::assertInstanceOf(Paragraph::class, $object->setHanging($rand)); + self::assertEquals($rand, $object->getHanging()); + self::assertInstanceOf(Paragraph::class, $object->setHanging()); + self::assertNull($object->getHanging()); + } + + public function testIndent(): void + { + $rand = mt_rand(0, 255); + + $object = new Paragraph(); + self::assertNull($object->getIndent()); + self::assertInstanceOf(Paragraph::class, $object->setIndent($rand)); + self::assertEquals($rand, $object->getIndent()); + self::assertInstanceOf(Paragraph::class, $object->setIndent(null)); + self::assertNull($object->getIndent()); + self::assertInstanceOf(Paragraph::class, $object->setIndent($rand)); + self::assertEquals($rand, $object->getIndent()); + self::assertInstanceOf(Paragraph::class, $object->setIndent()); + self::assertNull($object->getIndent()); + } + + public function testIndentation(): void + { + $rand = mt_rand(0, 255); + $rand2 = mt_rand(0, 255); + + $object = new Paragraph(); + self::assertNull($object->getIndentation()); + // Set Basic indentation + self::assertInstanceOf(Paragraph::class, $object->setIndentation([])); + self::assertNotNull($object->getIndentation()); + self::assertEquals(0, $object->getIndentation()->getLeft()); + self::assertEquals(0, $object->getIndentation()->getRight()); + self::assertEquals(0, $object->getIndentation()->getHanging()); + self::assertEquals(0, $object->getIndentation()->getFirstLine()); + // Set indentation : left + self::assertInstanceOf(Paragraph::class, $object->setIndentation([ + 'left' => $rand, + ])); + self::assertNotNull($object->getIndentation()); + self::assertEquals($rand, $object->getIndentation()->getLeft()); + self::assertEquals(0, $object->getIndentation()->getRight()); + self::assertEquals(0, $object->getIndentation()->getHanging()); + self::assertEquals(0, $object->getIndentation()->getFirstLine()); + // Set indentation : right + self::assertInstanceOf(Paragraph::class, $object->setIndentation([ + 'right' => $rand, + ])); + self::assertNotNull($object->getIndentation()); + self::assertEquals($rand, $object->getIndentation()->getLeft()); + self::assertEquals($rand, $object->getIndentation()->getRight()); + self::assertEquals(0, $object->getIndentation()->getHanging()); + self::assertEquals(0, $object->getIndentation()->getFirstLine()); + // Set indentation : hanging + self::assertInstanceOf(Paragraph::class, $object->setIndentation([ + 'hanging' => $rand, + ])); + self::assertNotNull($object->getIndentation()); + self::assertEquals($rand, $object->getIndentation()->getLeft()); + self::assertEquals($rand, $object->getIndentation()->getRight()); + self::assertEquals($rand, $object->getIndentation()->getHanging()); + self::assertEquals(0, $object->getIndentation()->getFirstLine()); + // Set indentation : firstline + self::assertInstanceOf(Paragraph::class, $object->setIndentation([ + 'firstline' => $rand, + ])); + self::assertNotNull($object->getIndentation()); + self::assertEquals($rand, $object->getIndentation()->getLeft()); + self::assertEquals($rand, $object->getIndentation()->getRight()); + self::assertEquals($rand, $object->getIndentation()->getHanging()); + self::assertEquals($rand, $object->getIndentation()->getFirstLine()); + // Replace indentation : left & firstline + self::assertInstanceOf(Paragraph::class, $object->setIndentation([ + 'left' => $rand2, + 'firstline' => $rand2, + ])); + self::assertNotNull($object->getIndentation()); + self::assertEquals($rand2, $object->getIndentation()->getLeft()); + self::assertEquals($rand, $object->getIndentation()->getRight()); + self::assertEquals($rand, $object->getIndentation()->getHanging()); + self::assertEquals($rand2, $object->getIndentation()->getFirstLine()); + // Replace indentation : N/A + self::assertInstanceOf(Paragraph::class, $object->setIndentation()); + self::assertNotNull($object->getIndentation()); + self::assertEquals($rand2, $object->getIndentation()->getLeft()); + self::assertEquals($rand, $object->getIndentation()->getRight()); + self::assertEquals($rand, $object->getIndentation()->getHanging()); + self::assertEquals($rand2, $object->getIndentation()->getFirstLine()); + } + + public function testIndentFirstLine(): void + { + $rand = mt_rand(0, 255); + + $object = new Paragraph(); + self::assertNull($object->getIndentFirstLine()); + self::assertInstanceOf(Paragraph::class, $object->setIndentFirstLine($rand)); + self::assertEquals($rand, $object->getIndentFirstLine()); + self::assertInstanceOf(Paragraph::class, $object->setIndentFirstLine(null)); + self::assertNull($object->getIndentFirstLine()); + self::assertInstanceOf(Paragraph::class, $object->setIndentFirstLine($rand)); + self::assertEquals($rand, $object->getIndentFirstLine()); + self::assertInstanceOf(Paragraph::class, $object->setIndentFirstLine()); + self::assertNull($object->getIndentFirstLine()); + } + + public function testIndentLeft(): void + { + $rand = mt_rand(0, 255); + + $object = new Paragraph(); + self::assertNull($object->getIndentLeft()); + self::assertInstanceOf(Paragraph::class, $object->setIndentLeft($rand)); + self::assertEquals($rand, $object->getIndentLeft()); + self::assertInstanceOf(Paragraph::class, $object->setIndentLeft(null)); + self::assertNull($object->getIndentLeft()); + self::assertInstanceOf(Paragraph::class, $object->setIndentLeft($rand)); + self::assertEquals($rand, $object->getIndentLeft()); + self::assertInstanceOf(Paragraph::class, $object->setIndentLeft()); + self::assertNull($object->getIndentLeft()); + } + + public function testIndentRight(): void + { + $rand = mt_rand(0, 255); + + $object = new Paragraph(); + self::assertNull($object->getIndentRight()); + self::assertInstanceOf(Paragraph::class, $object->setIndentRight($rand)); + self::assertEquals($rand, $object->getIndentRight()); + self::assertInstanceOf(Paragraph::class, $object->setIndentRight(null)); + self::assertNull($object->getIndentRight()); + self::assertInstanceOf(Paragraph::class, $object->setIndentRight($rand)); + self::assertEquals($rand, $object->getIndentRight()); + self::assertInstanceOf(Paragraph::class, $object->setIndentRight()); + self::assertNull($object->getIndentRight()); + } + /** * Line height. */ From 21ac083b62e64aa1a18ac484b32637820e79b545 Mon Sep 17 00:00:00 2001 From: Christian Koop <c.koop@ryze-digital.de> Date: Wed, 22 Jan 2025 21:30:15 +0100 Subject: [PATCH 224/246] Reader Word2007 : Support Header elements within Title elements (#2674) * fix: Support Header element within Title elements We encountered issues with a Word document where this is a valid combination. * docs(changelog): Add note about supporting Header elements within Title --- docs/changes/1.x/1.4.0.md | 1 + src/PhpWord/Element/AbstractContainer.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index d1fa6cba99..a68114ea84 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -17,6 +17,7 @@ - Allow vAlign and vMerge on Style\Cell to be set to null by [@SpraxDev](https://github.com/SpraxDev) fixing [#2673](https://github.com/PHPOffice/PHPWord/issues/2673) in [#2676](https://github.com/PHPOffice/PHPWord/pull/2676) - Reader HTML: Support for differents size units for table by [@Progi1984](https://github.com/Progi1984) fixing [#2384](https://github.com/PHPOffice/PHPWord/issues/2384), [#2701](https://github.com/PHPOffice/PHPWord/issues/2701) in [#2725](https://github.com/PHPOffice/PHPWord/pull/2725) - Reader Word2007 : Respect paragraph indent units by [@tugmaks](https://github.com/tugmaks) & [@Progi1984](https://github.com/Progi1984) fixing [#507](https://github.com/PHPOffice/PHPWord/issues/507) in [#2726](https://github.com/PHPOffice/PHPWord/pull/2726) +- Reader Word2007 : Support Header elements within Title elements by [@SpraxDev](https://github.com/SpraxDev) fixing [#2616](https://github.com/PHPOffice/PHPWord/issues/2616), [#2426](https://github.com/PHPOffice/PHPWord/issues/2426) in [#2674](https://github.com/PHPOffice/PHPWord/pull/2674) ### Miscellaneous diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index f989e1069c..f311d68206 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -254,7 +254,7 @@ private function checkValidity($method) 'Footnote' => ['Section', 'TextRun', 'Cell', 'ListItemRun'], 'Endnote' => ['Section', 'TextRun', 'Cell'], 'PreserveText' => ['Section', 'Header', 'Footer', 'Cell'], - 'Title' => ['Section', 'Cell'], + 'Title' => ['Section', 'Cell', 'Header'], 'TOC' => ['Section'], 'PageBreak' => ['Section'], 'Chart' => ['Section', 'Cell'], From 10ae49963c9b0c8a74bebfc0124b7b16d47ca460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=B7=D0=B0=D0=BC=D0=B0=D1=828405?= <azamat8405@yandex.ru> Date: Wed, 22 Jan 2025 23:35:39 +0300 Subject: [PATCH 225/246] Writer Word2007: Support for padding in Table Cell (#2697) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Support for padding in a table cell * Support for padding in a table cell. fix code style * feat: Support for padding in a table cell. Addition for changelog * feat: Support for padding in a table cell. Test file * feat: Support for padding in a table cell. Test file fix code style * feat: Support for padding in a table cell. More test file * Update composer.json azamat8405/phpword * Update composer.json azamat8405/phpword * Update composer.json fix renaming * feat: Сhanges for the code review * feat: Сhanges for the code review 2 * feat: feat: Сhanges for the code review 3 * feat: feat: Сhanges for the code review 4 * feat: feat: Сhanges for the code review 5 --------- Co-authored-by: OlisaevAG <A.Olisaev@soccard.ru> --- docs/changes/1.x/1.4.0.md | 1 + src/PhpWord/Shared/Html.php | 52 +++++++++ src/PhpWord/Style/Cell.php | 100 ++++++++++++++++++ src/PhpWord/Writer/Word2007/Style/Cell.php | 34 ++++++ tests/PhpWordTests/Shared/HtmlTest.php | 61 +++++++++++ tests/PhpWordTests/Style/CellTest.php | 21 ++++ .../Writer/Word2007/Style/TableCellTest.php | 86 +++++++++++++++ 7 files changed, 355 insertions(+) create mode 100644 tests/PhpWordTests/Writer/Word2007/Style/TableCellTest.php diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index a68114ea84..32f5ba47c9 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -8,6 +8,7 @@ - Writer ODText: Support for ListItemRun by [@Progi1984](https://github.com/Progi1984) fixing [#2159](https://github.com/PHPOffice/PHPWord/issues/2159), [#2620](https://github.com/PHPOffice/PHPWord/issues/2620) in [#2669](https://github.com/PHPOffice/PHPWord/pull/2669) - Writer HTML: Support for vAlign in Tables by [@SpraxDev](https://github.com/SpraxDev) in [#2675](https://github.com/PHPOffice/PHPWord/pull/2675) +- Writer Word2007: Support for padding in Table Cell by [@Azamat8405](https://github.com/Azamat8405) in [#2697](https://github.com/PHPOffice/PHPWord/pull/2697) - Added support for PHP 8.4 by [@Progi1984](https://github.com/Progi1984) in [#2660](https://github.com/PHPOffice/PHPWord/pull/2660) - Autoload : Allow to use PHPWord without Composer fixing [#2543](https://github.com/PHPOffice/PHPWord/issues/2543), [#2552](https://github.com/PHPOffice/PHPWord/issues/2552), [#2716](https://github.com/PHPOffice/PHPWord/issues/2716), [#2717](https://github.com/PHPOffice/PHPWord/issues/2717) in [#2722](https://github.com/PHPOffice/PHPWord/pull/2722) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 11a6b39d54..d94c13fdf7 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -804,6 +804,58 @@ protected static function parseStyleDeclarations(array $selectors, array $styles $styles['spaceAfter'] = Converter::cssToTwip($value); break; + + case 'padding': + $valueTop = $valueRight = $valueBottom = $valueLeft = null; + $cValue = preg_replace('# +#', ' ', trim($value)); + $paddingArr = explode(' ', $cValue); + $countParams = count($paddingArr); + if ($countParams == 1) { + $valueTop = $valueRight = $valueBottom = $valueLeft = $paddingArr[0]; + } elseif ($countParams == 2) { + $valueTop = $valueBottom = $paddingArr[0]; + $valueRight = $valueLeft = $paddingArr[1]; + } elseif ($countParams == 3) { + $valueTop = $paddingArr[0]; + $valueRight = $valueLeft = $paddingArr[1]; + $valueBottom = $paddingArr[2]; + } elseif ($countParams == 4) { + $valueTop = $paddingArr[0]; + $valueRight = $paddingArr[1]; + $valueBottom = $paddingArr[2]; + $valueLeft = $paddingArr[3]; + } + if ($valueTop !== null) { + $styles['paddingTop'] = Converter::cssToTwip($valueTop); + } + if ($valueRight !== null) { + $styles['paddingRight'] = Converter::cssToTwip($valueRight); + } + if ($valueBottom !== null) { + $styles['paddingBottom'] = Converter::cssToTwip($valueBottom); + } + if ($valueLeft !== null) { + $styles['paddingLeft'] = Converter::cssToTwip($valueLeft); + } + + break; + case 'padding-top': + $styles['paddingTop'] = Converter::cssToTwip($value); + + break; + case 'padding-right': + $styles['paddingRight'] = Converter::cssToTwip($value); + + break; + case 'padding-bottom': + $styles['paddingBottom'] = Converter::cssToTwip($value); + + break; + case 'padding-left': + $styles['paddingLeft'] = Converter::cssToTwip($value); + + break; + case 'border-color': self::mapBorderColor($styles, $value); diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index f102bfa862..e2b59f417d 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -74,6 +74,26 @@ class Cell extends Border */ private $vAlign; + /** + * @var null|int + */ + private $paddingTop; + + /** + * @var null|int + */ + private $paddingBottom; + + /** + * @var null|int + */ + private $paddingLeft; + + /** + * @var null|int + */ + private $paddingRight; + /** * Text Direction. * @@ -357,4 +377,84 @@ public function getNoWrap(): bool { return $this->noWrap; } + + /** + * Get style padding-top. + */ + public function getPaddingTop(): ?int + { + return $this->paddingTop; + } + + /** + * Set style padding-top. + * + * @return $this + */ + public function setPaddingTop(int $value): self + { + $this->paddingTop = $value; + + return $this; + } + + /** + * Get style padding-bottom. + */ + public function getPaddingBottom(): ?int + { + return $this->paddingBottom; + } + + /** + * Set style padding-bottom. + * + * @return $this + */ + public function setPaddingBottom(int $value): self + { + $this->paddingBottom = $value; + + return $this; + } + + /** + * Get style padding-left. + */ + public function getPaddingLeft(): ?int + { + return $this->paddingLeft; + } + + /** + * Set style padding-left. + * + * @return $this + */ + public function setPaddingLeft(int $value): self + { + $this->paddingLeft = $value; + + return $this; + } + + /** + * Get style padding-right. + */ + public function getPaddingRight(): ?int + { + return $this->paddingRight; + } + + /** + * Set style padding-right. + * + * @return $this + */ + public function setPaddingRight(int $value): self + { + $this->paddingRight = $value; + + return $this; + } } diff --git a/src/PhpWord/Writer/Word2007/Style/Cell.php b/src/PhpWord/Writer/Word2007/Style/Cell.php index ea6fba6d7c..bb0d6d71b0 100644 --- a/src/PhpWord/Writer/Word2007/Style/Cell.php +++ b/src/PhpWord/Writer/Word2007/Style/Cell.php @@ -55,6 +55,40 @@ public function write(): void $xmlWriter->endElement(); // w:tcW } + $paddingTop = $style->getPaddingTop(); + $paddingLeft = $style->getPaddingLeft(); + $paddingBottom = $style->getPaddingBottom(); + $paddingRight = $style->getPaddingRight(); + + if ($paddingTop !== null || $paddingLeft !== null || $paddingBottom !== null || $paddingRight !== null) { + $xmlWriter->startElement('w:tcMar'); + if ($paddingTop !== null) { + $xmlWriter->startElement('w:top'); + $xmlWriter->writeAttribute('w:w', $paddingTop); + $xmlWriter->writeAttribute('w:type', \PhpOffice\PhpWord\SimpleType\TblWidth::TWIP); + $xmlWriter->endElement(); // w:top + } + if ($paddingLeft !== null) { + $xmlWriter->startElement('w:start'); + $xmlWriter->writeAttribute('w:w', $paddingLeft); + $xmlWriter->writeAttribute('w:type', \PhpOffice\PhpWord\SimpleType\TblWidth::TWIP); + $xmlWriter->endElement(); // w:start + } + if ($paddingBottom !== null) { + $xmlWriter->startElement('w:bottom'); + $xmlWriter->writeAttribute('w:w', $paddingBottom); + $xmlWriter->writeAttribute('w:type', \PhpOffice\PhpWord\SimpleType\TblWidth::TWIP); + $xmlWriter->endElement(); // w:bottom + } + if ($paddingRight !== null) { + $xmlWriter->startElement('w:end'); + $xmlWriter->writeAttribute('w:w', $paddingRight); + $xmlWriter->writeAttribute('w:type', \PhpOffice\PhpWord\SimpleType\TblWidth::TWIP); + $xmlWriter->endElement(); // w:end + } + $xmlWriter->endElement(); // w:tcMar + } + // Text direction $textDir = $style->getTextDirection(); $xmlWriter->writeElementIf(null !== $textDir, 'w:textDirection', 'w:val', $textDir); diff --git a/tests/PhpWordTests/Shared/HtmlTest.php b/tests/PhpWordTests/Shared/HtmlTest.php index 3869f9608d..4edc5432b1 100644 --- a/tests/PhpWordTests/Shared/HtmlTest.php +++ b/tests/PhpWordTests/Shared/HtmlTest.php @@ -22,6 +22,7 @@ use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\Element\Table; use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Shared\Converter; use PhpOffice\PhpWord\Shared\Html; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\SimpleType\LineSpacingRule; @@ -270,6 +271,66 @@ public function testParseLineHeight(): void self::assertEquals(LineSpacingRule::AUTO, $doc->getElementAttribute('/w:document/w:body/w:p[5]/w:pPr/w:spacing', 'w:lineRule')); } + public function testParseCellPaddingStyle(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + + $top = 10; + $right = 11; + $bottom = 12; + $left = 13; + + $testValTop = Converter::pixelToTwip($top); + $testValRight = Converter::pixelToTwip($right); + $testValBottom = Converter::pixelToTwip($bottom); + $testValLeft = Converter::pixelToTwip($left); + + $html = '<table> + <tbody> + <tr> + <td style="padding:' . $top . 'px ' . $right . 'px ' . $bottom . 'px ' . $left . 'px;">full</td> + <td style="padding:' . $top . 'px 0px ' . $bottom . 'px ' . $left . 'px;padding-right:' . $right . 'px;">mix</td> + <td style="padding-top:' . $top . 'px;">top</td> + <td style="padding-bottom:' . $bottom . 'px;">bottom</td> + <td style="padding-left:' . $left . 'px;">left</td> + </tr> + </tbody> + </table>'; + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $path = '/w:document/w:body/w:tbl/w:tr/w:tc[1]/w:tcPr/w:tcMar/w:top'; + self::assertTrue($doc->elementExists($path)); + $path = '/w:document/w:body/w:tbl/w:tr/w:tc[1]/w:tcPr/w:tcMar/w:bottom'; + self::assertTrue($doc->elementExists($path)); + $path = '/w:document/w:body/w:tbl/w:tr/w:tc[1]/w:tcPr/w:tcMar/w:end'; + self::assertTrue($doc->elementExists($path)); + $path = '/w:document/w:body/w:tbl/w:tr/w:tc[1]/w:tcPr/w:tcMar/w:start'; + self::assertTrue($doc->elementExists($path)); + + $path = '/w:document/w:body/w:tbl/w:tr/w:tc[2]/w:tcPr/w:tcMar/w:end'; + self::assertTrue($doc->elementExists($path)); + self::assertEquals($testValRight, $doc->getElementAttribute($path, 'w:w')); + self::assertEquals(TblWidth::TWIP, $doc->getElementAttribute($path, 'w:type')); + + $path = '/w:document/w:body/w:tbl/w:tr/w:tc[3]/w:tcPr/w:tcMar/w:top'; + self::assertTrue($doc->elementExists($path)); + self::assertEquals($testValTop, $doc->getElementAttribute($path, 'w:w')); + self::assertEquals(TblWidth::TWIP, $doc->getElementAttribute($path, 'w:type')); + + $path = '/w:document/w:body/w:tbl/w:tr/w:tc[4]/w:tcPr/w:tcMar/w:bottom'; + self::assertTrue($doc->elementExists($path)); + self::assertEquals($testValBottom, $doc->getElementAttribute($path, 'w:w')); + self::assertEquals(TblWidth::TWIP, $doc->getElementAttribute($path, 'w:type')); + + $path = '/w:document/w:body/w:tbl/w:tr/w:tc[5]/w:tcPr/w:tcMar/w:start'; + self::assertTrue($doc->elementExists($path)); + self::assertEquals($testValLeft, $doc->getElementAttribute($path, 'w:w')); + self::assertEquals(TblWidth::TWIP, $doc->getElementAttribute($path, 'w:type')); + } + /** * Test text-indent style. */ diff --git a/tests/PhpWordTests/Style/CellTest.php b/tests/PhpWordTests/Style/CellTest.php index cd4ae7f85b..9015d0feea 100644 --- a/tests/PhpWordTests/Style/CellTest.php +++ b/tests/PhpWordTests/Style/CellTest.php @@ -90,4 +90,25 @@ public function testBorderSize(): void $object->setStyleValue('borderSize', $value); self::assertEquals($expected, $object->getBorderSize()); } + + /** + * Test cell padding. + */ + public function testPadding(): void + { + $object = new Cell(); + $methods = [ + 'paddingTop' => 10, + 'paddingBottom' => 20, + 'paddingLeft' => 30, + 'paddingRight' => 40, + ]; + + foreach ($methods as $methodName => $methodValue) { + $object->setStyleValue($methodName, $methodValue); + $getterName = 'get' . ucfirst($methodName); + + self::assertEquals($methodValue, $object->$getterName()); + } + } } diff --git a/tests/PhpWordTests/Writer/Word2007/Style/TableCellTest.php b/tests/PhpWordTests/Writer/Word2007/Style/TableCellTest.php new file mode 100644 index 0000000000..bd3f587b75 --- /dev/null +++ b/tests/PhpWordTests/Writer/Word2007/Style/TableCellTest.php @@ -0,0 +1,86 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWordTests\Writer\Word2007\Style; + +use PhpOffice\PhpWord\Shared\Converter; +use PhpOffice\PhpWord\SimpleType\TblWidth; +use PhpOffice\PhpWordTests\TestHelperDOCX; + +/** + * Test class for PhpOffice\PhpWord\Writer\Word2007\Style\Table. + * + * @coversDefaultClass \PhpOffice\PhpWord\Writer\Word2007\Style\Table + * + * @runTestsInSeparateProcesses + */ +class TableCellTest extends \PHPUnit\Framework\TestCase +{ + /** + * Executed before each method of the class. + */ + protected function tearDown(): void + { + TestHelperDOCX::clear(); + } + + /** + * Test write styles. + */ + public function testCellPadding(): void + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $table = $section->addTable(); + $table->addRow(); + + $testValTop = Converter::pixelToTwip(10); + $testValRight = Converter::pixelToTwip(11); + $testValBottom = Converter::pixelToTwip(12); + $testValLeft = Converter::pixelToTwip(13); + + $cellStyle = [ + 'paddingTop' => $testValTop, + 'paddingRight' => $testValRight, + 'paddingBottom' => $testValBottom, + 'paddingLeft' => $testValLeft, + ]; + $table->addCell(null, $cellStyle)->addText('Some text'); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $path = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tcPr/w:tcMar/w:top'; + self::assertTrue($doc->elementExists($path)); + self::assertEquals($testValTop, $doc->getElementAttribute($path, 'w:w')); + self::assertEquals(TblWidth::TWIP, $doc->getElementAttribute($path, 'w:type')); + + $path = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tcPr/w:tcMar/w:start'; + self::assertTrue($doc->elementExists($path)); + self::assertEquals($testValLeft, $doc->getElementAttribute($path, 'w:w')); + self::assertEquals(TblWidth::TWIP, $doc->getElementAttribute($path, 'w:type')); + + $path = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tcPr/w:tcMar/w:bottom'; + self::assertTrue($doc->elementExists($path)); + self::assertEquals($testValBottom, $doc->getElementAttribute($path, 'w:w')); + self::assertEquals(TblWidth::TWIP, $doc->getElementAttribute($path, 'w:type')); + + $path = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tcPr/w:tcMar/w:end'; + self::assertTrue($doc->elementExists($path)); + self::assertEquals($testValRight, $doc->getElementAttribute($path, 'w:w')); + self::assertEquals(TblWidth::TWIP, $doc->getElementAttribute($path, 'w:type')); + } +} From f1470d005e583aecbe064e8286c1312857792699 Mon Sep 17 00:00:00 2001 From: Collie-IT <40590185+Collie-IT@users.noreply.github.com> Date: Sun, 26 Jan 2025 16:51:52 +0100 Subject: [PATCH 226/246] Add default font color for Word (.docx) (#2700) * Add default font color for Word (.docx) Adds the abillity to add a default font color for generated .docx. * fix format * Update 1.4.0.md Add default font color * Update introduction.md Add documentation default font color * Update introduction.md Correct default value * add tests for SetGetDefaultFontColor * debug test * add defaultFontColor to FontTest * Update src/PhpWord/PhpWord.php As suggested Co-authored-by: Progi1984 <progi1984@gmail.com> * Update src/PhpWord/PhpWord.php As suggested Co-authored-by: Progi1984 <progi1984@gmail.com> * Update 1.4.0.md Add default font color * Update introduction.md Add documentation default font color * Update introduction.md Correct default value * add tests for SetGetDefaultFontColor * debug test * add defaultFontColor to FontTest * Update src/PhpWord/PhpWord.php As suggested Co-authored-by: Progi1984 <progi1984@gmail.com> * Update src/PhpWord/PhpWord.php As suggested Co-authored-by: Progi1984 <progi1984@gmail.com> * fix format * add test for default color * clean up * cs fixer --------- Co-authored-by: MichaelFrey <michael.frey@gmx.ch> Co-authored-by: Progi1984 <progi1984@gmail.com> --- docs/changes/1.x/1.4.0.md | 1 + docs/usage/introduction.md | 5 ++- phpword.ini.dist | 1 + src/PhpWord/PhpWord.php | 18 ++++++++- src/PhpWord/Reader/Word2007/Styles.php | 3 ++ src/PhpWord/Settings.php | 31 ++++++++++++++- src/PhpWord/Writer/Word2007/Part/Styles.php | 4 ++ tests/PhpWordTests/PhpWordTest.php | 12 ++++++ tests/PhpWordTests/SettingsTest.php | 20 ++++++++++ tests/PhpWordTests/Writer/HTML/FontTest.php | 5 +++ .../Writer/Word2007/Part/StylesTest.php | 38 +++++++++++++++++++ 11 files changed, 134 insertions(+), 4 deletions(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 32f5ba47c9..cb12a3f68a 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -11,6 +11,7 @@ - Writer Word2007: Support for padding in Table Cell by [@Azamat8405](https://github.com/Azamat8405) in [#2697](https://github.com/PHPOffice/PHPWord/pull/2697) - Added support for PHP 8.4 by [@Progi1984](https://github.com/Progi1984) in [#2660](https://github.com/PHPOffice/PHPWord/pull/2660) - Autoload : Allow to use PHPWord without Composer fixing [#2543](https://github.com/PHPOffice/PHPWord/issues/2543), [#2552](https://github.com/PHPOffice/PHPWord/issues/2552), [#2716](https://github.com/PHPOffice/PHPWord/issues/2716), [#2717](https://github.com/PHPOffice/PHPWord/issues/2717) in [#2722](https://github.com/PHPOffice/PHPWord/pull/2722) +- Add Default font color for Word by [@Collie-IT](https://github.com/Collie-IT) in [#2700](https://github.com/PHPOffice/PHPWord/pull/2700) ### Bug fixes diff --git a/docs/usage/introduction.md b/docs/usage/introduction.md index 6aa42aaae0..19d6aff51f 100644 --- a/docs/usage/introduction.md +++ b/docs/usage/introduction.md @@ -127,13 +127,14 @@ You can alter the default paper by using the following function: ### Default font -By default, every text appears in Arial 10 point. You can alter the -default font by using the following two functions: +By default, every text appears in Arial 10 point in the color black (000000). +You can alter the default font by using the following functions: ``` php <?php $phpWord->setDefaultFontName('Times New Roman'); +$phpWord->setDefaultFontColor('FF0000'); $phpWord->setDefaultFontSize(12); ``` diff --git a/phpword.ini.dist b/phpword.ini.dist index f3f66dbe2e..21d3b50609 100644 --- a/phpword.ini.dist +++ b/phpword.ini.dist @@ -14,6 +14,7 @@ outputEscapingEnabled = false defaultFontName = Arial defaultFontSize = 10 +defaultFontColor = 000000 [Paper] diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index aa62a76f0d..c3200fe857 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -266,7 +266,7 @@ public function getDefaultAsianFontName(): string } /** - * Set default font name. + * Set default asian font name. * * @param string $fontName */ @@ -275,6 +275,22 @@ public function setDefaultAsianFontName($fontName): void Settings::setDefaultAsianFontName($fontName); } + /** + * Set default font color. + */ + public function setDefaultFontColor(string $fontColor): void + { + Settings::setDefaultFontColor($fontColor); + } + + /** + * Get default font color. + */ + public function getDefaultFontColor(): string + { + return Settings::getDefaultFontColor(); + } + /** * Get default font size. * diff --git a/src/PhpWord/Reader/Word2007/Styles.php b/src/PhpWord/Reader/Word2007/Styles.php index b327ff3346..d0777c3026 100644 --- a/src/PhpWord/Reader/Word2007/Styles.php +++ b/src/PhpWord/Reader/Word2007/Styles.php @@ -47,6 +47,9 @@ public function read(PhpWord $phpWord): void if (array_key_exists('size', $fontDefaultStyle)) { $phpWord->setDefaultFontSize($fontDefaultStyle['size']); } + if (array_key_exists('color', $fontDefaultStyle)) { + $phpWord->setDefaultFontColor($fontDefaultStyle['color']); + } if (array_key_exists('lang', $fontDefaultStyle)) { $phpWord->getSettings()->setThemeFontLang(new Language($fontDefaultStyle['lang'])); } diff --git a/src/PhpWord/Settings.php b/src/PhpWord/Settings.php index 0cbfed7988..16f49166fa 100644 --- a/src/PhpWord/Settings.php +++ b/src/PhpWord/Settings.php @@ -119,12 +119,19 @@ class Settings private static $defaultFontName = self::DEFAULT_FONT_NAME; /** - * Default font name. + * Default asian font name. * * @var string */ private static $defaultAsianFontName = self::DEFAULT_FONT_NAME; + /** + * Default font color. + * + * @var string + */ + private static $defaultFontColor = self::DEFAULT_FONT_COLOR; + /** * Default font size. * @@ -395,6 +402,28 @@ public static function setDefaultAsianFontName(string $value): bool return false; } + /** + * Get default font color. + */ + public static function getDefaultFontColor(): string + { + return self::$defaultFontColor; + } + + /** + * Set default font color. + */ + public static function setDefaultFontColor(string $value): bool + { + if (trim($value) !== '') { + self::$defaultFontColor = $value; + + return true; + } + + return false; + } + /** * Get default font size. * diff --git a/src/PhpWord/Writer/Word2007/Part/Styles.php b/src/PhpWord/Writer/Word2007/Part/Styles.php index c57c1e58be..edf0314cc2 100644 --- a/src/PhpWord/Writer/Word2007/Part/Styles.php +++ b/src/PhpWord/Writer/Word2007/Part/Styles.php @@ -86,6 +86,7 @@ private function writeDefaultStyles(XMLWriter $xmlWriter, $styles): void $fontName = $phpWord->getDefaultFontName(); $asianFontName = $phpWord->getDefaultAsianFontName(); $fontSize = $phpWord->getDefaultFontSize(); + $fontColor = $phpWord->getDefaultFontColor(); $language = $phpWord->getSettings()->getThemeFontLang(); $latinLanguage = ($language == null || $language->getLatin() === null) ? 'en-US' : $language->getLatin(); @@ -99,6 +100,9 @@ private function writeDefaultStyles(XMLWriter $xmlWriter, $styles): void $xmlWriter->writeAttribute('w:eastAsia', $asianFontName); $xmlWriter->writeAttribute('w:cs', $fontName); $xmlWriter->endElement(); // w:rFonts + $xmlWriter->startElement('w:color'); + $xmlWriter->writeAttribute('w:val', $fontColor); + $xmlWriter->endElement(); $xmlWriter->startElement('w:sz'); $xmlWriter->writeAttribute('w:val', $fontSize * 2); $xmlWriter->endElement(); // w:sz diff --git a/tests/PhpWordTests/PhpWordTest.php b/tests/PhpWordTests/PhpWordTest.php index d194f4895d..76919bbdf3 100644 --- a/tests/PhpWordTests/PhpWordTest.php +++ b/tests/PhpWordTests/PhpWordTest.php @@ -95,6 +95,18 @@ public function testSetGetDefaultAsianFontName(): void self::assertEquals($fontName, $phpWord->getDefaultAsianFontName()); } + /** + * Test set/get default font color. + */ + public function testSetGetDefaultFontColor(): void + { + $phpWord = new PhpWord(); + $fontColor = 'FF0000'; + self::assertEquals(Settings::DEFAULT_FONT_COLOR, $phpWord->getDefaultFontColor()); + $phpWord->setDefaultFontColor($fontColor); + self::assertEquals($fontColor, $phpWord->getDefaultFontColor()); + } + /** * Test set default paragraph style. */ diff --git a/tests/PhpWordTests/SettingsTest.php b/tests/PhpWordTests/SettingsTest.php index cf8e12b205..13b32e1293 100644 --- a/tests/PhpWordTests/SettingsTest.php +++ b/tests/PhpWordTests/SettingsTest.php @@ -31,6 +31,9 @@ class SettingsTest extends TestCase { private $compatibility; + /** @var string */ + private $defaultFontColor; + private $defaultFontSize; private $defaultFontName; @@ -60,6 +63,7 @@ class SettingsTest extends TestCase protected function setUp(): void { $this->compatibility = Settings::hasCompatibility(); + $this->defaultFontColor = Settings::getDefaultFontColor(); $this->defaultFontSize = Settings::getDefaultFontSize(); $this->defaultFontName = Settings::getDefaultFontName(); $this->defaultPaper = Settings::getDefaultPaper(); @@ -76,6 +80,7 @@ protected function setUp(): void protected function tearDown(): void { Settings::setCompatibility($this->compatibility); + Settings::setDefaultFontColor($this->defaultFontColor); Settings::setDefaultFontSize($this->defaultFontSize); Settings::setDefaultFontName($this->defaultFontName); Settings::setDefaultPaper($this->defaultPaper); @@ -251,6 +256,20 @@ public function testSetGetDefaultFontSize(): void self::assertEquals(12.5, Settings::getDefaultFontSize()); } + /** + * Test set/get default font color. + */ + public function testSetGetDefaultFontColor(): void + { + self::assertEquals(Settings::DEFAULT_FONT_COLOR, Settings::getDefaultFontColor()); + self::assertFalse(Settings::setDefaultFontColor(' ')); + self::assertEquals(Settings::DEFAULT_FONT_COLOR, Settings::getDefaultFontColor()); + self::assertTrue(Settings::setDefaultFontColor('FF0000')); + self::assertEquals('FF0000', Settings::getDefaultFontColor()); + self::assertFalse(Settings::setDefaultFontColor(' ')); + self::assertEquals('FF0000', Settings::getDefaultFontColor()); + } + /** * Test set/get default paper. */ @@ -286,6 +305,7 @@ public function testLoadConfig(): void 'pdfRendererPath' => '', 'defaultFontName' => 'Arial', 'defaultFontSize' => 10, + 'defaultFontColor' => '000000', 'outputEscapingEnabled' => false, 'defaultPaper' => 'A4', ]; diff --git a/tests/PhpWordTests/Writer/HTML/FontTest.php b/tests/PhpWordTests/Writer/HTML/FontTest.php index d2519f962f..17f82a26be 100644 --- a/tests/PhpWordTests/Writer/HTML/FontTest.php +++ b/tests/PhpWordTests/Writer/HTML/FontTest.php @@ -34,6 +34,9 @@ class FontTest extends \PHPUnit\Framework\TestCase /** @var float|int */ private $defaultFontSize; + /** @var string */ + private $defaultFontColor; + /** * Executed before each method of the class. */ @@ -41,6 +44,7 @@ protected function setUp(): void { $this->defaultFontName = Settings::getDefaultFontName(); $this->defaultFontSize = Settings::getDefaultFontSize(); + $this->defaultFontColor = Settings::getDefaultFontColor(); } /** @@ -50,6 +54,7 @@ protected function tearDown(): void { Settings::setDefaultFontName($this->defaultFontName); Settings::setDefaultFontSize($this->defaultFontSize); + Settings::setDefaultFontColor($this->defaultFontColor); } /** diff --git a/tests/PhpWordTests/Writer/Word2007/Part/StylesTest.php b/tests/PhpWordTests/Writer/Word2007/Part/StylesTest.php index 6939c6fddc..09936d6d33 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/StylesTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/StylesTest.php @@ -145,4 +145,42 @@ public function testFontStyleBasedOnOtherFontStyle(): void $element = $doc->getElement($path, $file); self::assertEquals('Generation', $element->getAttribute('w:val')); } + + /** + * Test default font color. + */ + public function testDefaultDefaultFontColor(): void + { + $phpWord = new PhpWord(); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $file = 'word/styles.xml'; + + $path = '/w:styles/w:docDefaults/w:rPrDefault/w:rPr/w:color'; + self::assertTrue($doc->elementExists($path, $file)); + $element = $doc->getElement($path, $file); + + self::assertEquals('000000', $element->getAttribute('w:val')); + } + + /** + * Test default font color. + */ + public function testDefaultFontColor(): void + { + $phpWord = new PhpWord(); + $defaultFontColor = '00FF00'; + $phpWord->setDefaultFontColor($defaultFontColor); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $file = 'word/styles.xml'; + + $path = '/w:styles/w:docDefaults/w:rPrDefault/w:rPr/w:color'; + self::assertTrue($doc->elementExists($path, $file)); + $element = $doc->getElement($path, $file); + + self::assertEquals($defaultFontColor, $element->getAttribute('w:val')); + } } From a4468f29099365a892d582e51ed9abd558f7e118 Mon Sep 17 00:00:00 2001 From: Michael Frey <michael.frey@gmx.ch> Date: Tue, 28 Jan 2025 12:15:34 +0100 Subject: [PATCH 227/246] Writer HTML: Support Default font color (#2731) * Writer HTML: Support Default font color * the reader should already support default font color --- docs/changes/1.x/1.4.0.md | 1 + src/PhpWord/Writer/HTML/Part/Body.php | 2 +- src/PhpWord/Writer/HTML/Part/Head.php | 5 +-- tests/PhpWordTests/Writer/HTML/FontTest.php | 39 ++++++++++++++++++--- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index cb12a3f68a..e733a5b2e2 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -12,6 +12,7 @@ - Added support for PHP 8.4 by [@Progi1984](https://github.com/Progi1984) in [#2660](https://github.com/PHPOffice/PHPWord/pull/2660) - Autoload : Allow to use PHPWord without Composer fixing [#2543](https://github.com/PHPOffice/PHPWord/issues/2543), [#2552](https://github.com/PHPOffice/PHPWord/issues/2552), [#2716](https://github.com/PHPOffice/PHPWord/issues/2716), [#2717](https://github.com/PHPOffice/PHPWord/issues/2717) in [#2722](https://github.com/PHPOffice/PHPWord/pull/2722) - Add Default font color for Word by [@Collie-IT](https://github.com/Collie-IT) in [#2700](https://github.com/PHPOffice/PHPWord/pull/2700) +- Writer HTML: Support Default font color by [@MichaelPFrey](https://github.com/MichaelPFrey) ### Bug fixes diff --git a/src/PhpWord/Writer/HTML/Part/Body.php b/src/PhpWord/Writer/HTML/Part/Body.php index 4a391b53ef..bad1415c21 100644 --- a/src/PhpWord/Writer/HTML/Part/Body.php +++ b/src/PhpWord/Writer/HTML/Part/Body.php @@ -23,7 +23,7 @@ use PhpOffice\PhpWord\Writer\PDF\TCPDF; /** - * RTF body part writer. + * HTML body part writer. * * @since 0.11.0 */ diff --git a/src/PhpWord/Writer/HTML/Part/Head.php b/src/PhpWord/Writer/HTML/Part/Head.php index 32761a7959..79235e1c4a 100644 --- a/src/PhpWord/Writer/HTML/Part/Head.php +++ b/src/PhpWord/Writer/HTML/Part/Head.php @@ -30,7 +30,7 @@ use PhpOffice\PhpWord\Writer\HTML\Style\Table as TableStyleWriter; /** - * RTF head part writer. + * HTML head part writer. * * @since 0.11.0 */ @@ -85,11 +85,12 @@ public function write() private function writeStyles(): string { $css = '<style>' . PHP_EOL; - + $defaultFontColor = Settings::getDefaultFontColor(); // Default styles $astarray = [ 'font-family' => $this->getFontFamily(Settings::getDefaultFontName(), $this->getParentWriter()->getDefaultGenericFont()), 'font-size' => Settings::getDefaultFontSize() . 'pt', + 'color' => "#{$defaultFontColor}", ]; // Mpdf sometimes needs separate tag for body; doesn't harm others. $bodyarray = $astarray; diff --git a/tests/PhpWordTests/Writer/HTML/FontTest.php b/tests/PhpWordTests/Writer/HTML/FontTest.php index 17f82a26be..0a203b7237 100644 --- a/tests/PhpWordTests/Writer/HTML/FontTest.php +++ b/tests/PhpWordTests/Writer/HTML/FontTest.php @@ -57,6 +57,37 @@ protected function tearDown(): void Settings::setDefaultFontColor($this->defaultFontColor); } + public function testDefaultDefaults(): void + { + $phpWord = new PhpWord(); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + $style = Helper::getTextContent($xpath, '/html/head/style[1]'); + + $prg = preg_match('/body {(.*?)}/', $style, $matches); + self::assertNotEmpty($matches); + self::assertNotFalse($prg); + self::assertEquals('body {font-family: \'Arial\'; font-size: 12pt; color: #000000;}', $matches[0]); + } + + public function testSettingDefaultFontColor(): void + { + $phpWord = new PhpWord(); + + $defaultFontColor = '00FF00'; + $phpWord->setDefaultFontColor($defaultFontColor); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + $style = Helper::getTextContent($xpath, '/html/head/style[1]'); + + $prg = preg_match('/body {(.*?)}/', $style, $matches); + self::assertNotEmpty($matches); + self::assertNotFalse($prg); + self::assertEquals('body {font-family: \'Arial\'; font-size: 12pt; color: #00FF00;}', $matches[0]); + } + /** * Tests font names - without generics. */ @@ -93,7 +124,7 @@ public function testFontNames1(): void $prg = preg_match('/^[*][^\\r\\n]*/m', $style, $matches); self::assertNotEmpty($matches); self::assertNotFalse($prg); - self::assertEquals('* {font-family: \'Courier New\'; font-size: 12pt;}', $matches[0]); + self::assertEquals('* {font-family: \'Courier New\'; font-size: 12pt; color: #000000;}', $matches[0]); $prg = preg_match('/^[.]style1[^\\r\\n]*/m', $style, $matches); self::assertNotEmpty($matches); self::assertNotFalse($prg); @@ -149,7 +180,7 @@ public function testFontNames2(): void $prg = preg_match('/^[*][^\\r\\n]*/m', $style, $matches); self::assertNotEmpty($matches); self::assertNotFalse($prg); - self::assertEquals('* {font-family: \'Courier New\'; font-size: 12pt;}', $matches[0]); + self::assertEquals('* {font-family: \'Courier New\'; font-size: 12pt; color: #000000;}', $matches[0]); $prg = preg_match('/^[.]style1[^\\r\\n]*/m', $style, $matches); self::assertNotEmpty($matches); self::assertNotFalse($prg); @@ -201,7 +232,7 @@ public function testFontNames3(): void $prg = preg_match('/^[*][^\\r\\n]*/m', $style, $matches); self::assertNotEmpty($matches); self::assertNotFalse($prg); - self::assertEquals('* {font-family: \'Courier New\', monospace; font-size: 12pt;}', $matches[0]); + self::assertEquals('* {font-family: \'Courier New\', monospace; font-size: 12pt; color: #000000;}', $matches[0]); $prg = preg_match('/^[.]style1[^\\r\\n]*/m', $style, $matches); self::assertNotEmpty($matches); self::assertNotFalse($prg); @@ -244,7 +275,7 @@ public function testWhiteSpace(): void $style = Helper::getTextContent($xpath, '/html/head/style'); self::assertNotFalse(preg_match('/^[*][^\\r\\n]*/m', $style, $matches)); - self::assertEquals('* {font-family: \'Arial\'; font-size: 12pt; white-space: pre-wrap;}', $matches[0]); + self::assertEquals('* {font-family: \'Arial\'; font-size: 12pt; color: #000000; white-space: pre-wrap;}', $matches[0]); $prg = preg_match('/^[.]style1[^\\r\\n]*/m', $style, $matches); self::assertNotEmpty($matches); self::assertNotFalse($prg); From 2d2759585d11627fcd2475be0ee39b24cd4837eb Mon Sep 17 00:00:00 2001 From: Deadpikle <Deadpikle@users.noreply.github.com> Date: Wed, 29 Jan 2025 05:46:32 +0900 Subject: [PATCH 228/246] Feature: Ruby (phonetic guide) text - Word2007 Read/Write, HTML Read/Write, RTF write, ODT basic write (#2727) * Allow reading ruby text in from Word2007 docs * Rename ruby language to language Id * Add basic ruby Word2007 writer * Update changelog * Add ruby element docs * Run PHP CS Fixer * Fix PHPStan errors * Run PHP CS Fixer again * Fix ruby in titles when reading * Add/tweak tests for reading/writing Title with ruby * Use elementExists to try and fix PHP7.1 * Review: add missing type hints; refine types * Add setters to Ruby class * Add basic sample for ruby text * Add base constructor to RubyProperties * Add basic ruby tests * Run PHP CS Fixer * Update sample to handle properties better * Add Ruby HTML output including tests * Update changelog * Update PhpStand baseline * Forgot to run php-cs-fixer again * Update 1.4.0.md * Fix TextRun::getText not working with Ruby element * Add test for TextRun ruby element * Add RTF ruby output * Add ruby HTML reading * Tweak param calls in testRubyWriting * Update changelog * Update sample 46 to be less confusing with ruby output * Move ODText/Element/Text::replaceTabs method Moved to parent AbstractElement so other classes could make use of it * Add very basic ODT Ruby output * Run PHP CS Fixer * Update 1.4.0.md * Try to fix unexpected EOF in HtmlTest * Add missing tests for RubyProperties --- docs/changes/1.x/1.4.0.md | 1 + docs/usage/elements/ruby.md | 57 ++++++ mkdocs.yml | 1 + phpstan-baseline.neon | 20 +- samples/Sample_46_RubyPhoneticGuide.php | 70 +++++++ src/PhpWord/ComplexType/RubyProperties.php | 188 ++++++++++++++++++ src/PhpWord/Element/AbstractContainer.php | 3 +- src/PhpWord/Element/Ruby.php | 114 +++++++++++ src/PhpWord/Element/TextRun.php | 3 + src/PhpWord/Reader/Word2007/AbstractPart.php | 44 +++- src/PhpWord/Shared/Html.php | 83 +++++++- src/PhpWord/Writer/HTML/Element/Ruby.php | 130 ++++++++++++ .../Writer/ODText/Element/AbstractElement.php | 28 +++ src/PhpWord/Writer/ODText/Element/Ruby.php | 64 ++++++ src/PhpWord/Writer/ODText/Element/Text.php | 29 --- src/PhpWord/Writer/RTF/Element/Ruby.php | 59 ++++++ src/PhpWord/Writer/RTF/Element/Title.php | 9 +- src/PhpWord/Writer/Word2007/Element/Ruby.php | 81 ++++++++ .../ComplexType/RubyPropertiesTest.php | 141 +++++++++++++ tests/PhpWordTests/Element/RubyTest.php | 104 ++++++++++ tests/PhpWordTests/Element/TextRunTest.php | 21 ++ .../Reader/Word2007/ElementTest.php | 132 ++++++++++++ tests/PhpWordTests/Shared/HtmlTest.php | 48 +++++ .../Writer/HTML/Element/RubyTest.php | 99 +++++++++ tests/PhpWordTests/Writer/HTML/Helper.php | 32 ++- .../Writer/ODText/ElementTest.php | 36 +++- tests/PhpWordTests/Writer/RTF/ElementTest.php | 41 ++++ .../Writer/Word2007/ElementTest.php | 130 ++++++++++++ 28 files changed, 1725 insertions(+), 43 deletions(-) create mode 100644 docs/usage/elements/ruby.md create mode 100644 samples/Sample_46_RubyPhoneticGuide.php create mode 100644 src/PhpWord/ComplexType/RubyProperties.php create mode 100644 src/PhpWord/Element/Ruby.php create mode 100644 src/PhpWord/Writer/HTML/Element/Ruby.php create mode 100644 src/PhpWord/Writer/ODText/Element/Ruby.php create mode 100644 src/PhpWord/Writer/RTF/Element/Ruby.php create mode 100644 src/PhpWord/Writer/Word2007/Element/Ruby.php create mode 100644 tests/PhpWordTests/ComplexType/RubyPropertiesTest.php create mode 100644 tests/PhpWordTests/Element/RubyTest.php create mode 100644 tests/PhpWordTests/Writer/HTML/Element/RubyTest.php diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index e733a5b2e2..c8a019115d 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -13,6 +13,7 @@ - Autoload : Allow to use PHPWord without Composer fixing [#2543](https://github.com/PHPOffice/PHPWord/issues/2543), [#2552](https://github.com/PHPOffice/PHPWord/issues/2552), [#2716](https://github.com/PHPOffice/PHPWord/issues/2716), [#2717](https://github.com/PHPOffice/PHPWord/issues/2717) in [#2722](https://github.com/PHPOffice/PHPWord/pull/2722) - Add Default font color for Word by [@Collie-IT](https://github.com/Collie-IT) in [#2700](https://github.com/PHPOffice/PHPWord/pull/2700) - Writer HTML: Support Default font color by [@MichaelPFrey](https://github.com/MichaelPFrey) +- Add basic ruby text (phonetic guide) support for Word2007 and HTML Reader/Writer, RTF Writer, basic support for ODT writing by [@Deadpikle](https://github.com/Deadpikle) in [#2727](https://github.com/PHPOffice/PHPWord/pull/2727) ### Bug fixes diff --git a/docs/usage/elements/ruby.md b/docs/usage/elements/ruby.md new file mode 100644 index 0000000000..508b97cd84 --- /dev/null +++ b/docs/usage/elements/ruby.md @@ -0,0 +1,57 @@ +# Ruby + +Ruby (phonetic guide) text can be added by using the ``addRuby`` method. Ruby elements require a ``RubyProperties`` object, a ``TextRun`` for the base text, and a ``TextRun`` for the actual ruby (phonetic guide) text. + +Here is one example for a complete ruby element setup: + +``` php +<?php +$phpWord = new PhpWord(); + +$section = $phpWord->addSection(); +$properties = new RubyProperties(); +$properties->setAlignment(RubyProperties::ALIGNMENT_RIGHT_VERTICAL); +$properties->setFontFaceSize(10); +$properties->setFontPointsAboveBaseText(4); +$properties->setFontSizeForBaseText(18); +$properties->setLanguageId('ja-JP'); + +$baseTextRun = new TextRun(null); +$baseTextRun->addText('私'); +$rubyTextRun = new TextRun(null); +$rubyTextRun->addText('わたし'); + +$section->addRuby($baseTextRun, $rubyTextRun, $properties); +``` + +- ``$baseTextRun``. ``TextRun`` to be used for the base text. +- ``$rubyTextRun``. ``TextRun`` to be used for the ruby text. +- ``$properties``. ``RubyProperties`` properties object for the ruby text. + +A title with a phonetic guide is a little more complex, but still possible. Make sure you add the appropraite title style to your document. + +```php +$phpWord = new PhpWord(); +$fontStyle = new Font(); +$fontStyle->setAllCaps(true); +$fontStyle->setBold(true); +$fontStyle->setSize(24); +$phpWord->addTitleStyle(1, ['name' => 'Arial', 'size' => 24, 'bold' => true, 'color' => '990000']); + +$section = $phpWord->addSection(); +$properties = new RubyProperties(); +$properties->setAlignment(RubyProperties::ALIGNMENT_RIGHT_VERTICAL); +$properties->setFontFaceSize(10); +$properties->setFontPointsAboveBaseText(4); +$properties->setFontSizeForBaseText(18); +$properties->setLanguageId('ja-JP'); + +$baseTextRun = new TextRun(null); +$baseTextRun->addText('私'); +$rubyTextRun = new TextRun(null); +$rubyTextRun->addText('わたし'); + +$textRun = new TextRun(); +$textRun->addRuby($baseTextRun, $rubyTextRun, $properties); +$section->addTitle($textRun, 1); +``` \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 6b2c1b7fa6..0462c9c8a4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -63,6 +63,7 @@ nav: - OLE Object: 'usage/elements/oleobject.md' - Page Break: 'usage/elements/pagebreak.md' - Preserve Text: 'usage/elements/preservetext.md' + - Ruby: 'usage/elements/ruby.md' - Text: 'usage/elements/text.md' - TextBox: 'usage/elements/textbox.md' - Text Break: 'usage/elements/textbreak.md' diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 901888024d..86a542769a 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -430,6 +430,11 @@ parameters: count: 1 path: src/PhpWord/Shared/Html.php + - + message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:parseRuby\\(\\) has no return type specified\\.$#" + count: 1 + path: src/PhpWord/Shared/Html.php + - message: "#^Method PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:parseStyleDeclarations\\(\\) has no return type specified\\.$#" count: 1 @@ -442,7 +447,7 @@ parameters: - message: "#^Parameter \\#1 \\$attribute of static method PhpOffice\\\\PhpWord\\\\Shared\\\\Html\\:\\:parseStyle\\(\\) expects DOMAttr, DOMNode given\\.$#" - count: 1 + count: 3 path: src/PhpWord/Shared/Html.php - @@ -1051,14 +1056,14 @@ parameters: path: src/PhpWord/Writer/ODText/Element/Table.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Element\\\\Text\\:\\:replacetabs\\(\\) has parameter \\$text with no type specified\\.$#" + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Element\\\\AbstractElement\\:\\:replaceTabs\\(\\) has parameter \\$text with no type specified\\.$#" count: 1 - path: src/PhpWord/Writer/ODText/Element/Text.php + path: src/PhpWord/Writer/ODText/Element/AbstractElement.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Element\\\\Text\\:\\:replacetabs\\(\\) has parameter \\$xmlWriter with no type specified\\.$#" + message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Element\\\\AbstractElement\\:\\:replaceTabs\\(\\) has parameter \\$xmlWriter with no type specified\\.$#" count: 1 - path: src/PhpWord/Writer/ODText/Element/Text.php + path: src/PhpWord/Writer/ODText/Element/AbstractElement.php - message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Element\\\\Text\\:\\:writeChangeInsertion\\(\\) has parameter \\$start with no type specified\\.$#" @@ -1689,6 +1694,11 @@ parameters: message: "#^Cannot access property \\$length on DOMNodeList\\<DOMNode\\>\\|false\\.$#" count: 9 path: tests/PhpWordTests/Writer/HTML/ElementTest.php + + - + message: "#^Cannot access property \\$length on DOMNodeList\\<DOMNode\\>\\|false\\.$#" + count: 2 + path: tests/PhpWordTests/Writer/HTML/Element/RubyTest.php - message: "#^Cannot call method item\\(\\) on DOMNodeList\\<DOMNode\\>\\|false\\.$#" diff --git a/samples/Sample_46_RubyPhoneticGuide.php b/samples/Sample_46_RubyPhoneticGuide.php new file mode 100644 index 0000000000..0d991de756 --- /dev/null +++ b/samples/Sample_46_RubyPhoneticGuide.php @@ -0,0 +1,70 @@ +<?php + +use PhpOffice\PhpWord\ComplexType\RubyProperties; +use PhpOffice\PhpWord\Element\TextRun; + +include_once 'Sample_Header.php'; + +// New Word Document +echo date('H:i:s'), ' Create sample for Ruby (Phonetic Guide) use', EOL; +$phpWord = new PhpOffice\PhpWord\PhpWord(); + +// Section for demonstrating ruby (phonetic guide) features +$section = $phpWord->addSection(); + +$section->addText('Here is some normal text with no ruby, also known as "phonetic guide", text.'); + +$properties = new RubyProperties(); +$properties->setAlignment(RubyProperties::ALIGNMENT_CENTER); +$properties->setFontFaceSize(10); +$properties->setFontPointsAboveBaseText(20); +$properties->setFontSizeForBaseText(18); +$properties->setLanguageId('en-US'); + +$textRun = $section->addTextRun(); +$textRun->addText('Here is a demonstration of ruby text for '); +$baseTextRun = new TextRun(null); +$baseTextRun->addText('this'); +$rubyTextRun = new TextRun(null); +$rubyTextRun->addText('ruby-text'); +$textRun->addRuby($baseTextRun, $rubyTextRun, $properties); +$textRun->addText(' word.'); + +$textRun = $section->addTextRun(); +$properties = new RubyProperties(); +$properties->setAlignment(RubyProperties::ALIGNMENT_CENTER); +$properties->setFontFaceSize(10); +$properties->setFontPointsAboveBaseText(20); +$properties->setFontSizeForBaseText(18); +$properties->setLanguageId('ja-JP'); +$textRun->addText('Here is a demonstration of ruby text for Japanese text: '); +$baseTextRun = new TextRun(null); +$baseTextRun->addText('私'); +$rubyTextRun = new TextRun(null); +$rubyTextRun->addText('わたし'); +$textRun->addRuby($baseTextRun, $rubyTextRun, $properties); + +$section->addText('You can also have ruby text for titles:'); + +$phpWord->addTitleStyle(1, ['name' => 'Arial', 'size' => 24, 'bold' => true, 'color' => '000099']); + +$properties = new RubyProperties(); +$properties->setAlignment(RubyProperties::ALIGNMENT_CENTER); +$properties->setFontFaceSize(10); +$properties->setFontPointsAboveBaseText(50); +$properties->setFontSizeForBaseText(18); +$properties->setLanguageId('ja-JP'); + +$baseTextRun = new TextRun(null); +$baseTextRun->addText('私'); +$rubyTextRun = new TextRun(null); +$rubyTextRun->addText('わたし'); +$textRun = new TextRun(); +$textRun->addRuby($baseTextRun, $rubyTextRun, $properties); +$section->addTitle($textRun, 1); + +// Save file +echo write($phpWord, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/src/PhpWord/ComplexType/RubyProperties.php b/src/PhpWord/ComplexType/RubyProperties.php new file mode 100644 index 0000000000..2409151644 --- /dev/null +++ b/src/PhpWord/ComplexType/RubyProperties.php @@ -0,0 +1,188 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\ComplexType; + +use InvalidArgumentException; + +/** + * Ruby properties. + * + * @see https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.rubyproperties?view=openxml-3.0.1 + */ +class RubyProperties +{ + const ALIGNMENT_CENTER = 'center'; + const ALIGNMENT_DISTRIBUTE_LETTER = 'distributeLetter'; + const ALIGNMENT_DISTRIBUTE_SPACE = 'distributeSpace'; + const ALIGNMENT_LEFT = 'left'; + const ALIGNMENT_RIGHT = 'right'; + const ALIGNMENT_RIGHT_VERTICAL = 'rightVertical'; + + /** + * Ruby alignment (w:rubyAlign). + * + * @var string + */ + private $alignment; + + /** + * Ruby font face size (w:hps). + * + * @var float + */ + private $fontFaceSize; + + /** + * Ruby font points above base text (w:hpsRaise). + * + * @var float + */ + private $fontPointsAboveText; + + /** + * Ruby font size for base text (w:hpsBaseText). + * + * @var float + */ + private $baseTextFontSize; + + /** + * Ruby type/language id (w:lid). + * + * @var string + */ + private $languageId; + + /** + * Create a new RubyProperties object. + */ + public function __construct() + { + // these defaults came from opening a new Word doc, adding some ruby text to some + // Japanese text, and copying out the defaults. + $this->alignment = self::ALIGNMENT_DISTRIBUTE_SPACE; + $this->fontFaceSize = 12; + $this->fontPointsAboveText = 22; + $this->languageId = 'ja-JP'; + $this->baseTextFontSize = 24; + } + + /** + * Get the ruby alignment. + */ + public function getAlignment(): string + { + return $this->alignment; + } + + /** + * Set the Ruby Alignment (center, distributeLetter, distributeSpace, left, right, rightVertical). + */ + public function setAlignment(string $alignment): self + { + $alignmentTypes = [ + self::ALIGNMENT_CENTER, + self::ALIGNMENT_DISTRIBUTE_LETTER, + self::ALIGNMENT_DISTRIBUTE_SPACE, + self::ALIGNMENT_LEFT, + self::ALIGNMENT_RIGHT, + self::ALIGNMENT_RIGHT_VERTICAL, + ]; + + if (in_array($alignment, $alignmentTypes)) { + $this->alignment = $alignment; + } else { + throw new InvalidArgumentException('Invalid value, alignments of ' . implode(', ', $alignmentTypes) . ' possible'); + } + + return $this; + } + + /** + * Get the ruby font face size. + */ + public function getFontFaceSize(): float + { + return $this->fontFaceSize; + } + + /** + * Set the ruby font face size. + */ + public function setFontFaceSize(float $size): self + { + $this->fontFaceSize = $size; + + return $this; + } + + /** + * Get the ruby font points above base text. + */ + public function getFontPointsAboveBaseText(): float + { + return $this->fontPointsAboveText; + } + + /** + * Set the ruby font points above base text. + */ + public function setFontPointsAboveBaseText(float $size): self + { + $this->fontPointsAboveText = $size; + + return $this; + } + + /** + * Get the ruby font size for base text. + */ + public function getFontSizeForBaseText(): float + { + return $this->baseTextFontSize; + } + + /** + * Set the ruby font size for base text. + */ + public function setFontSizeForBaseText(float $size): self + { + $this->baseTextFontSize = $size; + + return $this; + } + + /** + * Get the ruby language id. + */ + public function getLanguageId(): string + { + return $this->languageId; + } + + /** + * Set the ruby language id. + */ + public function setLanguageId(string $langId): self + { + $this->languageId = $langId; + + return $this; + } +} diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index f311d68206..37140b4582 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -50,6 +50,7 @@ * @method FormField addFormField(string $type, mixed $fStyle = null, mixed $pStyle = null) * @method SDT addSDT(string $type) * @method Formula addFormula(Math $math) + * @method Ruby addRuby(TextRun $baseText, TextRun $rubyText, \PhpOffice\PhpWord\ComplexType\RubyProperties $properties) * @method \PhpOffice\PhpWord\Element\OLEObject addObject(string $source, mixed $style = null) deprecated, use addOLEObject instead * * @since 0.10.0 @@ -91,7 +92,7 @@ public function __call($function, $args) 'Footnote', 'Endnote', 'CheckBox', 'TextBox', 'Field', 'Line', 'Shape', 'Title', 'TOC', 'PageBreak', 'Chart', 'FormField', 'SDT', 'Comment', - 'Formula', + 'Formula', 'Ruby', ]; $functions = []; foreach ($elements as $element) { diff --git a/src/PhpWord/Element/Ruby.php b/src/PhpWord/Element/Ruby.php new file mode 100644 index 0000000000..4b032a220d --- /dev/null +++ b/src/PhpWord/Element/Ruby.php @@ -0,0 +1,114 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Element; + +use PhpOffice\PhpWord\ComplexType\RubyProperties; + +/** + * Ruby element. + * + * @see https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.ruby?view=openxml-3.0.1 + */ +class Ruby extends AbstractElement +{ + /** + * Ruby properties. + * + * @var RubyProperties + */ + protected $properties; + + /** + * Ruby text run. + * + * @var TextRun + */ + protected $rubyTextRun; + + /** + * Ruby base text run. + * + * @var TextRun + */ + protected $baseTextRun; + + /** + * Create a new Ruby Element. + */ + public function __construct(TextRun $baseTextRun, TextRun $rubyTextRun, RubyProperties $properties) + { + $this->baseTextRun = $baseTextRun; + $this->rubyTextRun = $rubyTextRun; + $this->properties = $properties; + } + + /** + * Get base text run. + */ + public function getBaseTextRun(): TextRun + { + return $this->baseTextRun; + } + + /** + * Set the base text run. + */ + public function setBaseTextRun(TextRun $textRun): self + { + $this->baseTextRun = $textRun; + + return $this; + } + + /** + * Get ruby text run. + */ + public function getRubyTextRun(): TextRun + { + return $this->rubyTextRun; + } + + /** + * Set the ruby text run. + */ + public function setRubyTextRun(TextRun $textRun): self + { + $this->rubyTextRun = $textRun; + + return $this; + } + + /** + * Get ruby properties. + */ + public function getProperties(): RubyProperties + { + return $this->properties; + } + + /** + * Set the ruby properties. + */ + public function setProperties(RubyProperties $properties): self + { + $this->properties = $properties; + + return $this; + } +} diff --git a/src/PhpWord/Element/TextRun.php b/src/PhpWord/Element/TextRun.php index 5dc8ef53c7..0c9a2322a7 100644 --- a/src/PhpWord/Element/TextRun.php +++ b/src/PhpWord/Element/TextRun.php @@ -86,6 +86,9 @@ public function getText(): string foreach ($this->getElements() as $element) { if ($element instanceof Text) { $outstr .= $element->getText(); + } elseif ($element instanceof Ruby) { + $outstr .= $element->getBaseTextRun()->getText() . + ' (' . $element->getRubyTextRun()->getText() . ')'; } } diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index d14ca603e7..96d4a46f8a 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -22,10 +22,13 @@ use DOMElement; use InvalidArgumentException; use PhpOffice\Math\Reader\OfficeMathML; +use PhpOffice\PhpWord\ComplexType\RubyProperties; use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType; use PhpOffice\PhpWord\Element\AbstractContainer; use PhpOffice\PhpWord\Element\AbstractElement; use PhpOffice\PhpWord\Element\FormField; +use PhpOffice\PhpWord\Element\Ruby; +use PhpOffice\PhpWord\Element\Text; use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\PhpWord; @@ -297,7 +300,8 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par if ($headingDepth !== null) { $textContent = null; $nodes = $xmlReader->getElements('w:r|w:hyperlink', $domNode); - if ($nodes->length === 1) { + $hasRubyElement = $xmlReader->elementExists('w:r/w:ruby', $domNode); + if ($nodes->length === 1 && !$hasRubyElement) { $textContent = htmlspecialchars($xmlReader->getValue('w:t', $nodes->item(0)), ENT_QUOTES, 'UTF-8'); } else { $textContent = new TextRun($paragraphStyle); @@ -585,9 +589,47 @@ protected function readRunChild(XMLReader $xmlReader, DOMElement $node, Abstract } } elseif ($node->nodeName == 'w:softHyphen') { $element = $parent->addText("\u{200c}", $fontStyle, $paragraphStyle); + } elseif ($node->nodeName == 'w:ruby') { + $rubyPropertiesNode = $xmlReader->getElement('w:rubyPr', $node); + $properties = $this->readRubyProperties($xmlReader, $rubyPropertiesNode); + // read base text node + $baseText = new TextRun($paragraphStyle); + $baseTextNode = $xmlReader->getElement('w:rubyBase/w:r', $node); + $this->readRun($xmlReader, $baseTextNode, $baseText, $docPart, $paragraphStyle); + // read the actual ruby text (e.g. furigana in Japanese) + $rubyText = new TextRun($paragraphStyle); + $rubyTextNode = $xmlReader->getElement('w:rt/w:r', $node); + $this->readRun($xmlReader, $rubyTextNode, $rubyText, $docPart, $paragraphStyle); + // add element to parent + $parent->addRuby($baseText, $rubyText, $properties); } } + /** + * Read w:rubyPr element. + * + * @param XMLReader $xmlReader reader for XML + * @param DOMElement $domNode w:RubyPr element + * + * @return RubyProperties ruby properties from element + */ + protected function readRubyProperties(XMLReader $xmlReader, DOMElement $domNode): RubyProperties + { + $rubyAlignment = $xmlReader->getElement('w:rubyAlign', $domNode)->getAttribute('w:val'); + $rubyHps = $xmlReader->getElement('w:hps', $domNode)->getAttribute('w:val'); // font face + $rubyHpsRaise = $xmlReader->getElement('w:hpsRaise', $domNode)->getAttribute('w:val'); // pts above base text + $rubyHpsBaseText = $xmlReader->getElement('w:hpsBaseText', $domNode)->getAttribute('w:val'); // base text size + $rubyLid = $xmlReader->getElement('w:lid', $domNode)->getAttribute('w:val'); // type of ruby + $properties = new RubyProperties(); + $properties->setAlignment($rubyAlignment); + $properties->setFontFaceSize((float) $rubyHps); + $properties->setFontPointsAboveBaseText((float) $rubyHpsRaise); + $properties->setFontSizeForBaseText((float) $rubyHpsBaseText); + $properties->setLanguageId($rubyLid); + + return $properties; + } + /** * Read w:tbl. * diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index d94c13fdf7..4573daf2a9 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -23,9 +23,11 @@ use DOMNode; use DOMXPath; use Exception; +use PhpOffice\PhpWord\ComplexType\RubyProperties; use PhpOffice\PhpWord\Element\AbstractContainer; use PhpOffice\PhpWord\Element\Row; use PhpOffice\PhpWord\Element\Table; +use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\SimpleType\NumberFormat; @@ -239,6 +241,7 @@ protected static function parseNode($node, $element, $styles = [], $data = []): 'a' => ['Link', $node, $element, $styles, null, null, null], 'input' => ['Input', $node, $element, $styles, null, null, null], 'hr' => ['HorizRule', $node, $element, $styles, null, null, null], + 'ruby' => ['Ruby', $node, $element, $styles, null, null, null], ]; $newElement = null; @@ -302,7 +305,7 @@ protected static function parseChildNodes($node, $element, $styles, $data): void * @param AbstractContainer $element * @param array &$styles * - * @return \PhpOffice\PhpWord\Element\PageBreak|\PhpOffice\PhpWord\Element\TextRun + * @return \PhpOffice\PhpWord\Element\PageBreak|TextRun */ protected static function parseParagraph($node, $element, &$styles) { @@ -346,7 +349,7 @@ protected static function parseInput($node, $element, &$styles): void * @param array &$styles * @param string $argument1 Name of heading style * - * @return \PhpOffice\PhpWord\Element\TextRun + * @return TextRun * * @todo Think of a clever way of defining header styles, now it is only based on the assumption, that * Heading1 - Heading6 are already defined somewhere @@ -464,7 +467,7 @@ protected static function parseRow($node, $element, &$styles) * @param Table $element * @param array &$styles * - * @return \PhpOffice\PhpWord\Element\Cell|\PhpOffice\PhpWord\Element\TextRun $element + * @return \PhpOffice\PhpWord\Element\Cell|TextRun $element */ protected static function parseCell($node, $element, &$styles) { @@ -705,6 +708,10 @@ protected static function parseStyleDeclarations(array $selectors, array $styles case 'text-align': $styles['alignment'] = self::mapAlign($value, $bidi); + break; + case 'ruby-align': + $styles['rubyAlignment'] = self::mapRubyAlign($value); + break; case 'display': $styles['hidden'] = $value === 'none' || $value === 'hidden'; @@ -1103,6 +1110,23 @@ protected static function mapAlign($cssAlignment, $bidi) } } + /** + * Transforms a HTML/CSS ruby alignment into a \PhpOffice\PhpWord\SimpleType\Jc. + */ + protected static function mapRubyAlign(string $cssRubyAlignment): string + { + switch ($cssRubyAlignment) { + case 'center': + return RubyProperties::ALIGNMENT_CENTER; + case 'start': + return RubyProperties::ALIGNMENT_LEFT; + case 'space-between': + return RubyProperties::ALIGNMENT_DISTRIBUTE_SPACE; + default: + return ''; + } + } + /** * Transforms a HTML/CSS vertical alignment. * @@ -1231,6 +1255,59 @@ protected static function parseHorizRule($node, $element): void // - repeated text, e.g. underline "_", because of unpredictable line wrapping } + /** + * Parse ruby node. + * + * @param DOMNode $node + * @param AbstractContainer $element + * @param array $styles + */ + protected static function parseRuby($node, $element, &$styles) + { + $rubyProperties = new RubyProperties(); + $baseTextRun = new TextRun($styles['paragraph']); + $rubyTextRun = new TextRun(null); + if ($node->hasAttributes()) { + $langAttr = $node->attributes->getNamedItem('lang'); + if ($langAttr !== null) { + $rubyProperties->setLanguageId($langAttr->textContent); + } + $styleAttr = $node->attributes->getNamedItem('style'); + if ($styleAttr !== null) { + $styles = self::parseStyle($styleAttr, $styles['paragraph']); + if (isset($styles['rubyAlignment']) && $styles['rubyAlignment'] !== '') { + $rubyProperties->setAlignment($styles['rubyAlignment']); + } + if (isset($styles['size']) && $styles['size'] !== '') { + $rubyProperties->setFontSizeForBaseText($styles['size']); + } + $baseTextRun->setParagraphStyle($styles); + } + } + foreach ($node->childNodes as $child) { + if ($child->nodeName === '#text') { + $content = trim($child->textContent); + if ($content !== '') { + $baseTextRun->addText($content); + } + } elseif ($child->nodeName === 'rt') { + $rubyTextRun->addText(trim($child->textContent)); + if ($child->hasAttributes()) { + $styleAttr = $child->attributes->getNamedItem('style'); + if ($styleAttr !== null) { + $styles = self::parseStyle($styleAttr, []); + if (isset($styles['size']) && $styles['size'] !== '') { + $rubyProperties->setFontFaceSize($styles['size']); + } + $rubyTextRun->setParagraphStyle($styles); + } + } + } + } + + return $element->addRuby($baseTextRun, $rubyTextRun, $rubyProperties); + } + private static function convertRgb(string $rgb): string { if (preg_match(self::RGB_REGEXP, $rgb, $matches) === 1) { diff --git a/src/PhpWord/Writer/HTML/Element/Ruby.php b/src/PhpWord/Writer/HTML/Element/Ruby.php new file mode 100644 index 0000000000..b3ab13c35e --- /dev/null +++ b/src/PhpWord/Writer/HTML/Element/Ruby.php @@ -0,0 +1,130 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\HTML\Element; + +use PhpOffice\PhpWord\ComplexType\RubyProperties; +use PhpOffice\PhpWord\Element\TextRun; +use PhpOffice\PhpWord\Style\Paragraph; +use PhpOffice\PhpWord\Writer\HTML\Style\Paragraph as ParagraphStyleWriter; + +/** + * Ruby element HTML writer. + */ +class Ruby extends AbstractElement +{ + /** + * Write text. + * + * @return string + */ + public function write() + { + // $this->processFontStyle(); + + /** @var \PhpOffice\PhpWord\Element\Ruby $element Type hint */ + $element = $this->element; + + $baseText = $this->parentWriter->escapeHTML($element->getBaseTextRun()->getText()); + $rubyText = $this->parentWriter->escapeHTML($element->getRubyTextRun()->getText()); + + $rubyTagPropertyCSS = $this->getPropertyCssForRubyTag($element->getProperties()); + $lang = $element->getProperties()->getLanguageId(); + $content = "<ruby {$this->getParagraphStyleForTextRun($element->getBaseTextRun(), $rubyTagPropertyCSS)} lang=\"{$lang}\">"; + $content .= $baseText; + $content .= ' <rp>(</rp>'; + $rtTagPropertyCSS = $this->getPropertyCssForRtTag($element->getProperties()); + $content .= "<rt {$this->getParagraphStyleForTextRun($element->getRubyTextRun(), $rtTagPropertyCSS)}>"; + $content .= $rubyText; + $content .= '</rt>'; + $content .= '<rp>)</rp>'; + $content .= '</ruby>'; + + return $content; + } + + /** + * Get property CSS for the <ruby> tag. + */ + private function getPropertyCssForRubyTag(RubyProperties $properties): string + { + // alignment CSS: https://developer.mozilla.org/en-US/docs/Web/CSS/ruby-align + $alignment = 'space-between'; + switch ($properties->getAlignment()) { + case RubyProperties::ALIGNMENT_CENTER: + $alignment = 'center'; + + break; + case RubyProperties::ALIGNMENT_LEFT: + $alignment = 'start'; + + break; + default: + $alignment = 'space-between'; + + break; + } + + return + 'font-size:' . $properties->getFontSizeForBaseText() . 'pt' . ';' . + 'ruby-align:' . $alignment . ';'; + } + + /** + * Get property CSS for the <rt> tag. + */ + private function getPropertyCssForRtTag(RubyProperties $properties): string + { + // alignment CSS: https://developer.mozilla.org/en-US/docs/Web/CSS/ruby-align + return 'font-size:' . $properties->getFontFaceSize() . 'pt' . ';'; + } + + /** + * Write paragraph style for a given TextRun. + */ + private function getParagraphStyleForTextRun(TextRun $textRun, string $extraCSS): string + { + $style = ''; + if (!method_exists($textRun, 'getParagraphStyle')) { + return $style; + } + + $paragraphStyle = $textRun->getParagraphStyle(); + $pStyleIsObject = ($paragraphStyle instanceof Paragraph); + if ($pStyleIsObject) { + $styleWriter = new ParagraphStyleWriter($paragraphStyle); + $styleWriter->setParentWriter($this->parentWriter); + $style = $styleWriter->write(); + } elseif (is_string($paragraphStyle)) { + $style = $paragraphStyle; + } + if ($style !== null && $style !== '') { + if ($pStyleIsObject) { + // CSS pairs (style="...") + $style = " style=\"{$style}{$extraCSS}\""; + } else { + // class name; need to append extra styles manually + $style = " class=\"{$style}\" style=\"{$extraCSS}\""; + } + } elseif ($extraCSS !== '') { + $style = " style=\"{$extraCSS}\""; + } + + return $style; + } +} diff --git a/src/PhpWord/Writer/ODText/Element/AbstractElement.php b/src/PhpWord/Writer/ODText/Element/AbstractElement.php index ff3a6569de..97d1875cd1 100644 --- a/src/PhpWord/Writer/ODText/Element/AbstractElement.php +++ b/src/PhpWord/Writer/ODText/Element/AbstractElement.php @@ -27,4 +27,32 @@ */ abstract class AbstractElement extends Word2007AbstractElement { + protected function replaceTabs($text, $xmlWriter): void + { + if (preg_match('/^ +/', $text, $matches)) { + $num = strlen($matches[0]); + $xmlWriter->startElement('text:s'); + $xmlWriter->writeAttributeIf($num > 1, 'text:c', "$num"); + $xmlWriter->endElement(); + $text = preg_replace('/^ +/', '', $text); + } + preg_match_all('/([\\s\\S]*?)(\\t| +| ?$)/', $text, $matches, PREG_SET_ORDER); + foreach ($matches as $match) { + $this->writeText($match[1]); + if ($match[2] === '') { + break; + } elseif ($match[2] === "\t") { + $xmlWriter->writeElement('text:tab'); + } elseif ($match[2] === ' ') { + $xmlWriter->writeElement('text:s'); + + break; + } else { + $num = strlen($match[2]); + $xmlWriter->startElement('text:s'); + $xmlWriter->writeAttributeIf($num > 1, 'text:c', "$num"); + $xmlWriter->endElement(); + } + } + } } diff --git a/src/PhpWord/Writer/ODText/Element/Ruby.php b/src/PhpWord/Writer/ODText/Element/Ruby.php new file mode 100644 index 0000000000..41a86776d4 --- /dev/null +++ b/src/PhpWord/Writer/ODText/Element/Ruby.php @@ -0,0 +1,64 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\ODText\Element; + +/** + * Ruby element writer. + * NOTE: This class will write out a Ruby element in the format {baseText} ({rubyText}) + * just like RTF; however, ODT files natively support Ruby text elements. + * This implementation should be changed in the future to support ODT's native + * Ruby elements and usage. + */ +class Ruby extends AbstractElement +{ + /** + * Write element. + */ + public function write(): void + { + $xmlWriter = $this->getXmlWriter(); + $element = $this->getElement(); + if (!$element instanceof \PhpOffice\PhpWord\Element\Ruby) { + return; + } + $paragraphStyle = $element->getBaseTextRun()->getParagraphStyle(); + + if (!$this->withoutP) { + $xmlWriter->startElement('text:p'); // text:p + } + if (empty($paragraphStyle)) { + if (!$this->withoutP) { + $xmlWriter->writeAttribute('text:style-name', 'Normal'); + } + } elseif (is_string($paragraphStyle)) { + if (!$this->withoutP) { + $xmlWriter->writeAttribute('text:style-name', $paragraphStyle); + } + } + + $this->replaceTabs($element->getBaseTextRun()->getText(), $xmlWriter); + $this->writeText(' ('); + $this->replaceTabs($element->getRubyTextRun()->getText(), $xmlWriter); + $this->writeText(')'); + + if (!$this->withoutP) { + $xmlWriter->endElement(); // text:p + } + } +} diff --git a/src/PhpWord/Writer/ODText/Element/Text.php b/src/PhpWord/Writer/ODText/Element/Text.php index 65909fce0c..3996972387 100644 --- a/src/PhpWord/Writer/ODText/Element/Text.php +++ b/src/PhpWord/Writer/ODText/Element/Text.php @@ -89,35 +89,6 @@ public function write(): void } } - private function replacetabs($text, $xmlWriter): void - { - if (preg_match('/^ +/', $text, $matches)) { - $num = strlen($matches[0]); - $xmlWriter->startElement('text:s'); - $xmlWriter->writeAttributeIf($num > 1, 'text:c', "$num"); - $xmlWriter->endElement(); - $text = preg_replace('/^ +/', '', $text); - } - preg_match_all('/([\\s\\S]*?)(\\t| +| ?$)/', $text, $matches, PREG_SET_ORDER); - foreach ($matches as $match) { - $this->writeText($match[1]); - if ($match[2] === '') { - break; - } elseif ($match[2] === "\t") { - $xmlWriter->writeElement('text:tab'); - } elseif ($match[2] === ' ') { - $xmlWriter->writeElement('text:s'); - - break; - } else { - $num = strlen($match[2]); - $xmlWriter->startElement('text:s'); - $xmlWriter->writeAttributeIf($num > 1, 'text:c', "$num"); - $xmlWriter->endElement(); - } - } - } - private function writeChangeInsertion($start = true, ?TrackChange $trackChange = null): void { if ($trackChange == null || $trackChange->getChangeType() != TrackChange::INSERTED) { diff --git a/src/PhpWord/Writer/RTF/Element/Ruby.php b/src/PhpWord/Writer/RTF/Element/Ruby.php new file mode 100644 index 0000000000..e2b617c556 --- /dev/null +++ b/src/PhpWord/Writer/RTF/Element/Ruby.php @@ -0,0 +1,59 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\RTF\Element; + +/** + * Ruby element RTF writer. Writes {baseText} ({rubyText}) in current paragraph style + * because RTF does not natively support ruby text. + */ +class Ruby extends AbstractElement +{ + /** + * Write element. + * + * @return string + */ + public function write() + { + /** @var \PhpOffice\PhpWord\Element\Ruby $element */ + $element = $this->element; + $elementClass = str_replace('\\Writer\\RTF', '', static::class); + if (!$element instanceof $elementClass || !is_string($element->getBaseTextRun()->getText())) { + return ''; + } + + $this->getStyles(); + + $content = ''; + $content .= $this->writeOpening(); + $content .= '{'; + $content .= $this->writeFontStyle(); + $content .= $this->writeText($element->getBaseTextRun()->getText()); + $rubyText = $element->getRubyTextRun()->getText(); + if ($rubyText !== '') { + $content .= ' ('; + $content .= $this->writeText($rubyText); + $content .= ')'; + } + $content .= '}'; + $content .= $this->writeClosing(); + + return $content; + } +} diff --git a/src/PhpWord/Writer/RTF/Element/Title.php b/src/PhpWord/Writer/RTF/Element/Title.php index 1022e59f8f..06266897b3 100644 --- a/src/PhpWord/Writer/RTF/Element/Title.php +++ b/src/PhpWord/Writer/RTF/Element/Title.php @@ -59,10 +59,15 @@ public function write() /** @var \PhpOffice\PhpWord\Element\Title $element Type hint */ $element = $this->element; $elementClass = str_replace('\\Writer\\RTF', '', static::class); - if (!$element instanceof $elementClass || !is_string($element->getText())) { + if (!$element instanceof $elementClass) { return ''; } + $textToWrite = $element->getText(); + if ($textToWrite instanceof \PhpOffice\PhpWord\Element\TextRun) { + $textToWrite = $textToWrite->getText(); // gets text from TextRun + } + $this->getStyles(); $content = ''; @@ -83,7 +88,7 @@ public function write() $content .= '{'; $content .= $this->writeFontStyle(); - $content .= $this->writeText($element->getText()); + $content .= $this->writeText($textToWrite); $content .= '}'; $content .= $this->writeClosing(); $content .= $endout; diff --git a/src/PhpWord/Writer/Word2007/Element/Ruby.php b/src/PhpWord/Writer/Word2007/Element/Ruby.php new file mode 100644 index 0000000000..f30a5f7e84 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/Ruby.php @@ -0,0 +1,81 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\Word2007\Element; + +/** + * Ruby element writer. + */ +class Ruby extends AbstractElement +{ + /** + * Write ruby element. + */ + public function write(): void + { + $xmlWriter = $this->getXmlWriter(); + $element = $this->getElement(); + if (!$element instanceof \PhpOffice\PhpWord\Element\Ruby) { + return; + } + /** @var \PhpOffice\PhpWord\Element\Ruby $element */ + $this->startElementP(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:ruby'); + + // write properties + $xmlWriter->startElement('w:rubyPr'); + $properties = $element->getProperties(); + $xmlWriter->startElement('w:rubyAlign'); + $xmlWriter->writeAttribute('w:val', $properties->getAlignment()); + $xmlWriter->endElement(); // w:rubyAlign + $xmlWriter->startElement('w:hps'); + $xmlWriter->writeAttribute('w:val', $properties->getFontFaceSize()); + $xmlWriter->endElement(); // w:hps + $xmlWriter->startElement('w:hpsRaise'); + $xmlWriter->writeAttribute('w:val', $properties->getFontPointsAboveBaseText()); + $xmlWriter->endElement(); // w:hpsRaise + $xmlWriter->startElement('w:hpsBaseText'); + $xmlWriter->writeAttribute('w:val', $properties->getFontSizeForBaseText()); + $xmlWriter->endElement(); // w:hpsBaseText + $xmlWriter->startElement('w:lid'); + $xmlWriter->writeAttribute('w:val', $properties->getLanguageId()); + $xmlWriter->endElement(); // w:lid + + $xmlWriter->endElement(); // w:rubyPr + + // write ruby text + $xmlWriter->startElement('w:rt'); + $rubyTextRun = $element->getRubyTextRun(); + $textRunWriter = new TextRun($xmlWriter, $rubyTextRun, true); + $textRunWriter->write(); + $xmlWriter->endElement(); // w:rt + // write base text + $xmlWriter->startElement('w:rubyBase'); + $baseTextRun = $element->getBaseTextRun(); + $textRunWriter = new TextRun($xmlWriter, $baseTextRun, true); + $textRunWriter->write(); + $xmlWriter->endElement(); // w:rubyBase + + $xmlWriter->endElement(); // w:ruby + $xmlWriter->endElement(); // w:r + + $this->endElementP(); + } +} diff --git a/tests/PhpWordTests/ComplexType/RubyPropertiesTest.php b/tests/PhpWordTests/ComplexType/RubyPropertiesTest.php new file mode 100644 index 0000000000..6d16ebb21d --- /dev/null +++ b/tests/PhpWordTests/ComplexType/RubyPropertiesTest.php @@ -0,0 +1,141 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWordTests\ComplexType; + +use InvalidArgumentException; +use PhpOffice\PhpWord\ComplexType\RubyProperties; + +/** + * Test class for PhpOffice\PhpWord\ComplexType\RubyProperties. + * + * @runTestsInSeparateProcesses + */ +class RubyPropertiesTest extends \PHPUnit\Framework\TestCase +{ + /** + * Test new instance. + */ + public function testConstruct(): void + { + $properties = new RubyProperties(); + self::assertInstanceOf('PhpOffice\\PhpWord\\ComplexType\\RubyProperties', $properties); + + self::assertIsString($properties->getAlignment()); + self::assertTrue($properties->getAlignment() !== '' && $properties->getAlignment() !== null); + self::assertIsFloat($properties->getFontFaceSize()); + self::assertIsFloat($properties->getFontPointsAboveBaseText()); + self::assertIsFloat($properties->getFontSizeForBaseText()); + self::assertIsString($properties->getLanguageId()); + self::assertTrue($properties->getLanguageId() !== '' && $properties->getLanguageId() !== null); + } + + /** + * Get/set alignment. + */ + public function testAlignment(): void + { + $properties = new RubyProperties(); + self::assertIsString($properties->getAlignment()); + self::assertTrue($properties->getAlignment() !== '' && $properties->getAlignment() !== null); + $properties->setAlignment(RubyProperties::ALIGNMENT_RIGHT_VERTICAL); + self::assertEquals(RubyProperties::ALIGNMENT_RIGHT_VERTICAL, $properties->getAlignment()); + } + + /** + * Set valid alignments. Make sure we can set all valid types - should not throw exception. + */ + public function testValidAlignments(): void + { + $properties = new RubyProperties(); + $types = [ + RubyProperties::ALIGNMENT_CENTER, + RubyProperties::ALIGNMENT_DISTRIBUTE_LETTER, + RubyProperties::ALIGNMENT_DISTRIBUTE_SPACE, + RubyProperties::ALIGNMENT_LEFT, + RubyProperties::ALIGNMENT_RIGHT, + RubyProperties::ALIGNMENT_RIGHT_VERTICAL, + ]; + foreach ($types as $type) { + $properties->setAlignment($type); + self::assertEquals($type, $properties->getAlignment()); + } + } + + /** + * Test throws exception on invalid alignment type. + */ + public function testInvalidAlignment(): void + { + $this->expectException(InvalidArgumentException::class); + $properties = new RubyProperties(); + $properties->setAlignment('invalid alignment type'); + } + + /** + * Get/set font face size. + */ + public function testFontFaceSize(): void + { + $properties = new RubyProperties(); + + self::assertTrue($properties->getFontFaceSize() > 0); + $properties->setFontFaceSize(42.42); + self::assertEqualsWithDelta(42.42, $properties->getFontFaceSize(), 0.00001); // use delta as it is a float compare + self::assertIsFloat($properties->getFontFaceSize()); + } + + /** + * Get/set font points above base text. + */ + public function testFontPointsAboveBaseText(): void + { + $properties = new RubyProperties(); + + self::assertTrue($properties->getFontPointsAboveBaseText() > 0); + $properties->setFontPointsAboveBaseText(43.42); + self::assertEqualsWithDelta(43.42, $properties->getFontPointsAboveBaseText(), 0.00001); // use delta as it is a float compare + self::assertIsFloat($properties->getFontPointsAboveBaseText()); + } + + /** + * Get/set font size for base text. + */ + public function testFontSizeForBaseText(): void + { + $properties = new RubyProperties(); + + self::assertTrue($properties->getFontSizeForBaseText() > 0); + $properties->setFontSizeForBaseText(45.42); + self::assertEqualsWithDelta(45.42, $properties->getFontSizeForBaseText(), 0.00001); // use delta as it is a float compare + self::assertIsFloat($properties->getFontSizeForBaseText()); + } + + /** + * Get/set language id. + */ + public function testLanguageId(): void + { + $properties = new RubyProperties(); + + self::assertTrue($properties->getLanguageId() !== '' && $properties->getLanguageId() !== null); + $properties->setLanguageId('en-US'); + self::assertIsString($properties->getLanguageId()); + self::assertEquals('en-US', $properties->getLanguageId()); + } +} diff --git a/tests/PhpWordTests/Element/RubyTest.php b/tests/PhpWordTests/Element/RubyTest.php new file mode 100644 index 0000000000..0e14994fd2 --- /dev/null +++ b/tests/PhpWordTests/Element/RubyTest.php @@ -0,0 +1,104 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWordTests\Element; + +use PhpOffice\PhpWord\ComplexType\RubyProperties; +use PhpOffice\PhpWord\Element\Ruby; +use PhpOffice\PhpWord\Element\TextRun; + +/** + * Test class for PhpOffice\PhpWord\Element\Text. + * + * @runTestsInSeparateProcesses + */ +class RubyTest extends \PHPUnit\Framework\TestCase +{ + /** + * Test new instance. + */ + public function testConstruct(): void + { + $ruby = new Ruby(new TextRun(), new TextRun(), new RubyProperties()); + + self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Ruby', $ruby); + self::assertEquals('', $ruby->getBaseTextRun()->getText()); + self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $ruby->getBaseTextRun()); + self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $ruby->getBaseTextRun()->getParagraphStyle()); + self::assertEquals('', $ruby->getRubyTextRun()->getText()); + self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $ruby->getRubyTextRun()); + self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $ruby->getRubyTextRun()->getParagraphStyle()); + self::assertInstanceOf('PhpOffice\\PhpWord\\ComplexType\\RubyProperties', $ruby->getProperties()); + self::assertEquals(RubyProperties::ALIGNMENT_DISTRIBUTE_SPACE, $ruby->getProperties()->getAlignment()); + } + + /** + * Get/set base text. + */ + public function testBaseText(): void + { + $ruby = new Ruby(new TextRun(), new TextRun(), new RubyProperties()); + + self::assertEquals('', $ruby->getBaseTextRun()->getText()); + $tr = new TextRun(); + $tr->addText('Hello, world'); + $ruby->setBaseTextRun($tr); + self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $ruby->getBaseTextRun()); + self::assertEquals('Hello, world', $ruby->getBaseTextRun()->getText()); + } + + /** + * Get/set ruby text. + */ + public function testRubyText(): void + { + $ruby = new Ruby(new TextRun(), new TextRun(), new RubyProperties()); + + self::assertEquals('', $ruby->getRubyTextRun()->getText()); + $tr = new TextRun(); + $tr->addText('Hello, ruby'); + $ruby->setRubyTextRun($tr); + self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $ruby->getRubyTextRun()); + self::assertEquals('Hello, ruby', $ruby->getRubyTextRun()->getText()); + } + + /** + * Get/set ruby properties. + */ + public function testRubyProperties(): void + { + $ruby = new Ruby(new TextRun(), new TextRun(), new RubyProperties()); + + self::assertEquals(RubyProperties::ALIGNMENT_DISTRIBUTE_SPACE, $ruby->getProperties()->getAlignment()); + + $properties = new RubyProperties(); + $properties->setAlignment(RubyProperties::ALIGNMENT_RIGHT_VERTICAL); + $properties->setFontFaceSize(1); + $properties->setFontPointsAboveBaseText(2); + $properties->setFontSizeForBaseText(3); + $properties->setLanguageId('en-US'); + $ruby->setProperties($properties); + + self::assertInstanceOf('PhpOffice\\PhpWord\\ComplexType\\RubyProperties', $ruby->getProperties()); + self::assertEquals(RubyProperties::ALIGNMENT_RIGHT_VERTICAL, $ruby->getProperties()->getAlignment()); + self::assertEquals(1, $ruby->getProperties()->getFontFaceSize()); + self::assertEquals(2, $ruby->getProperties()->getFontPointsAboveBaseText()); + self::assertEquals(3, $ruby->getProperties()->getFontSizeForBaseText()); + self::assertEquals('en-US', $ruby->getProperties()->getLanguageId()); + } +} diff --git a/tests/PhpWordTests/Element/TextRunTest.php b/tests/PhpWordTests/Element/TextRunTest.php index 8d250676f4..e3a2826f0c 100644 --- a/tests/PhpWordTests/Element/TextRunTest.php +++ b/tests/PhpWordTests/Element/TextRunTest.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWordTests\Element; +use PhpOffice\PhpWord\ComplexType\RubyProperties; use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\SimpleType\Jc; @@ -183,4 +184,24 @@ public function testParagraph(): void $oText->setParagraphStyle(['alignment' => Jc::CENTER, 'spaceAfter' => 100]); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $oText->getParagraphStyle()); } + + /** + * Add ruby element and get raw text. + */ + public function testRubyElementGetText(): void + { + $oTextRun = new TextRun(); + $oTextRun->setPhpWord(new PhpWord()); + + $properties = new RubyProperties(); + $baseTextRun = new TextRun(null); + $baseTextRun->addText('私'); + $rubyTextRun = new TextRun(null); + $rubyTextRun->addText('わたし'); + $element = $oTextRun->addRuby($baseTextRun, $rubyTextRun, $properties); + + self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Ruby', $element); + self::assertCount(1, $oTextRun->getElements()); + self::assertEquals('私 (わたし)', $oTextRun->getText()); + } } diff --git a/tests/PhpWordTests/Reader/Word2007/ElementTest.php b/tests/PhpWordTests/Reader/Word2007/ElementTest.php index b27fc9df1d..892e59adf7 100644 --- a/tests/PhpWordTests/Reader/Word2007/ElementTest.php +++ b/tests/PhpWordTests/Reader/Word2007/ElementTest.php @@ -18,6 +18,8 @@ namespace PhpOffice\PhpWordTests\Reader\Word2007; +use PhpOffice\PhpWord\ComplexType\RubyProperties; +use PhpOffice\PhpWord\Element\Ruby; use PhpOffice\PhpWord\Element\Text; use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\Style\Font; @@ -544,4 +546,134 @@ public function testReadFormFieldCheckbox(): void self::assertEquals('checkbox', $subElements[0]->getType()); self::assertEquals('SomeCheckbox', $subElements[0]->getName()); } + + /** + * Test reading of ruby. + */ + public function testReadRuby(): void + { + $documentXml = '<w:p> + <w:r> + <w:ruby> + <w:rubyPr> + <w:rubyAlign w:val="distributeSpace" /> + <w:hps w:val="12" /> + <w:hpsRaise w:val="22" /> + <w:hpsBaseText w:val="24" /> + <w:lid w:val="ja-JP" /> + </w:rubyPr> + <w:rt> + <w:r w:rsidR="00984B5D" + w:rsidRPr="00984B5D"> + <w:rPr> + <w:rFonts w:ascii="Yu Gothic" + w:eastAsia="Yu Gothic" + w:hAnsi="Yu Gothic" + w:hint="eastAsia" /> + <w:sz w:val="12" /> + </w:rPr> + <w:t>わたし</w:t> + </w:r> + </w:rt> + <w:rubyBase> + <w:r w:rsidR="00984B5D"> + <w:rPr> + <w:rFonts w:hint="eastAsia" /> + </w:rPr> + <w:t>私</w:t> + </w:r> + </w:rubyBase> + </w:ruby> + </w:r> + </w:p>'; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + $elements = $phpWord->getSection(0)->getElements(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); + $subElements = $elements[0]->getElements(); // <w:ruby> + self::assertInstanceOf('PhpOffice\PhpWord\Element\Ruby', $subElements[0]); + /** @var RubyProperties $rubyProperties */ + $rubyProperties = $subElements[0]->getProperties(); + self::assertEquals(RubyProperties::ALIGNMENT_DISTRIBUTE_SPACE, $rubyProperties->getAlignment()); + self::assertEquals(12, $rubyProperties->getFontFaceSize()); + self::assertEquals(22, $rubyProperties->getFontPointsAboveBaseText()); + self::assertEquals(24, $rubyProperties->getFontSizeForBaseText()); + self::assertEquals('ja-JP', $rubyProperties->getLanguageId()); + /** @var \PhpOffice\PhpWord\Element\TextRun $textRun */ + $textRun = $subElements[0]->getBaseTextRun(); + self::assertEquals('私', $textRun->getText()); + $textRun = $subElements[0]->getRubyTextRun(); + self::assertEquals('わたし', $textRun->getText()); + } + + /** + * Test reading of ruby title. + */ + public function testReadRubyTitle(): void + { + $documentXml = '<w:p + w:rsidR="00CB4855" + w:rsidRDefault="00AA542C" + w:rsidP="00AA542C"> + <w:pPr> + <w:pStyle w:val="Heading1" /> + </w:pPr> + <w:r> + <w:ruby> + <w:rubyPr> + <w:rubyAlign w:val="distributeSpace" /> + <w:hps w:val="20" /> + <w:hpsRaise w:val="38" /> + <w:hpsBaseText w:val="40" /> + <w:lid w:val="ja-JP" /> + </w:rubyPr> + <w:rt> + <w:r w:rsidR="00AA542C" + w:rsidRPr="00AA542C"> + <w:rPr> + <w:rFonts w:ascii="Yu Gothic Light" + w:eastAsia="Yu Gothic Light" + w:hAnsi="Yu Gothic Light" + w:hint="eastAsia" /> + <w:sz w:val="20" /> + </w:rPr> + <w:t>かみ</w:t> + </w:r> + </w:rt> + <w:rubyBase> + <w:r w:rsidR="00AA542C"> + <w:rPr> + <w:rFonts w:hint="eastAsia" /> + </w:rPr> + <w:t>神</w:t> + </w:r> + </w:rubyBase> + </w:ruby> + </w:r> + </w:p>'; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + $elements = $phpWord->getSection(0)->getElements(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\Title', $elements[0]); + /** @var \PhpOffice\PhpWord\Element\Title $title */ + $title = $elements[0]; + /** @var \PhpOffice\PhpWord\Element\TextRun $textRun */ + $textRun = $title->getText(); + $subElements = $textRun->getElements(); // <w:ruby> + self::assertInstanceOf('PhpOffice\PhpWord\Element\Ruby', $subElements[0]); + /** @var Ruby $ruby */ + $ruby = $subElements[0]; + /** @var RubyProperties $rubyProperties */ + $rubyProperties = $ruby->getProperties(); + self::assertEquals(RubyProperties::ALIGNMENT_DISTRIBUTE_SPACE, $rubyProperties->getAlignment()); + self::assertEquals(20, $rubyProperties->getFontFaceSize()); + self::assertEquals(38, $rubyProperties->getFontPointsAboveBaseText()); + self::assertEquals(40, $rubyProperties->getFontSizeForBaseText()); + self::assertEquals('ja-JP', $rubyProperties->getLanguageId()); + /** @var \PhpOffice\PhpWord\Element\TextRun $textRun */ + $textRun = $ruby->getBaseTextRun(); + self::assertEquals('神', $textRun->getText()); + $textRun = $ruby->getRubyTextRun(); + self::assertEquals('かみ', $textRun->getText()); + } } diff --git a/tests/PhpWordTests/Shared/HtmlTest.php b/tests/PhpWordTests/Shared/HtmlTest.php index 4edc5432b1..7551f51cb8 100644 --- a/tests/PhpWordTests/Shared/HtmlTest.php +++ b/tests/PhpWordTests/Shared/HtmlTest.php @@ -19,6 +19,7 @@ namespace PhpOffice\PhpWordTests\Shared; use Exception; +use PhpOffice\PhpWord\ComplexType\RubyProperties; use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\Element\Table; use PhpOffice\PhpWord\PhpWord; @@ -1317,4 +1318,51 @@ public static function providerParseWidth(): array ['400', 6000, TblWidth::TWIP], ]; } + + /** + * Test ruby. + */ + public function testParseRubyHtml(): void + { + $html = <<<HTML +<ruby lang="en-US" style="line-height: 8pt;font-size:20pt;ruby-align:center;"> + base text + <rp>(</rp> + <rt style="line-height: 4pt;font-size:10pt">ruby text</rt> + <rp>)</rp> +</ruby> +HTML; + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:ruby')); + self::assertEquals('ruby text', $doc->getElement('/w:document/w:body/w:p/w:r/w:ruby/w:rt/w:r/w:t')->textContent); + self::assertEquals( + 'base text', + $doc->getElement('/w:document/w:body/w:p/w:r/w:ruby/w:rubyBase/w:r/w:t')->textContent + ); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:rubyAlign')); + self::assertEquals( + RubyProperties::ALIGNMENT_CENTER, + $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:rubyAlign', 'w:val') + ); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:hps')); + self::assertEquals( + 10, + $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:hps', 'w:val') + ); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:hpsBaseText')); + self::assertEquals( + 20, + $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:hpsBaseText', 'w:val') + ); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:lid')); + self::assertEquals( + 'en-US', + $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:lid', 'w:val') + ); + } } diff --git a/tests/PhpWordTests/Writer/HTML/Element/RubyTest.php b/tests/PhpWordTests/Writer/HTML/Element/RubyTest.php new file mode 100644 index 0000000000..2ca556bc51 --- /dev/null +++ b/tests/PhpWordTests/Writer/HTML/Element/RubyTest.php @@ -0,0 +1,99 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWordTests\Writer\HTML\Element; + +use DOMXPath; +use PhpOffice\PhpWord\ComplexType\RubyProperties; +use PhpOffice\PhpWord\Element\TextRun; +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWordTests\Writer\HTML\Helper; +use PHPUnit\Framework\TestCase; + +class RubyTest extends TestCase +{ + /** + * Tests writing ruby HTML. + */ + public function testWriteRubyHtml(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $properties = new RubyProperties(); + $properties->setAlignment(RubyProperties::ALIGNMENT_CENTER); + $properties->setFontFaceSize(10); + $properties->setFontPointsAboveBaseText(4); + $properties->setFontSizeForBaseText(20); + $properties->setLanguageId('ja-JP'); + + $baseTextRun = new TextRun(null); + $baseTextRun->addText('私'); + $rubyTextRun = new TextRun(null); + $rubyTextRun->addText('わたし'); + $section->addRuby($baseTextRun, $rubyTextRun, $properties); + + $dom = Helper::getAsHTML($phpWord, '', '', ['ruby', 'rt', 'rp']); + $xpath = new DOMXPath($dom); + self::assertEquals(1, $xpath->query('/html/body/div/ruby')->length); + // ensure text is right + $rubyElement = $dom->getElementsByTagName('ruby')->item(0); + $rtElement = $dom->getElementsByTagName('rt')->item(0); + self::assertNotNull($rubyElement); + self::assertNotNull($rtElement); + self::assertEquals($baseTextRun->getText() . ' (' . $rubyTextRun->getText() . ')', $rubyElement->textContent); + self::assertEquals($rubyTextRun->getText(), $rtElement->textContent); + // check style + self::assertEquals('font-size:20pt;ruby-align:center;', $rubyElement->attributes->getNamedItem('style')->textContent); + self::assertEquals('font-size:10pt;', $rtElement->attributes->getNamedItem('style')->textContent); + } + + /** + * Tests writing ruby HTML. + */ + public function testWriteRubyHtmlParagraphStyle(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $properties = new RubyProperties(); + $properties->setAlignment(RubyProperties::ALIGNMENT_CENTER); + $properties->setFontFaceSize(10); + $properties->setFontPointsAboveBaseText(4); + $properties->setFontSizeForBaseText(20); + $properties->setLanguageId('ja-JP'); + + $baseTextRun = new TextRun(['lineHeight' => '8']); + $baseTextRun->addText('私'); + $rubyTextRun = new TextRun(['lineHeight' => '4']); + $rubyTextRun->addText('わたし'); + $section->addRuby($baseTextRun, $rubyTextRun, $properties); + + $dom = Helper::getAsHTML($phpWord, '', '', ['ruby', 'rt', 'rp']); + $xpath = new DOMXPath($dom); + self::assertEquals(1, $xpath->query('/html/body/div/ruby')->length); + // ensure text is right + $rubyElement = $dom->getElementsByTagName('ruby')->item(0); + $rtElement = $dom->getElementsByTagName('rt')->item(0); + self::assertNotNull($rubyElement); + self::assertNotNull($rtElement); + self::assertEquals($baseTextRun->getText() . ' (' . $rubyTextRun->getText() . ')', $rubyElement->textContent); + self::assertEquals($rubyTextRun->getText(), $rtElement->textContent); + // check style + self::assertEquals('line-height: 8;font-size:20pt;ruby-align:center;', $rubyElement->attributes->getNamedItem('style')->textContent); + self::assertEquals('line-height: 4;font-size:10pt;', $rtElement->attributes->getNamedItem('style')->textContent); + } +} diff --git a/tests/PhpWordTests/Writer/HTML/Helper.php b/tests/PhpWordTests/Writer/HTML/Helper.php index 0fe390fd0d..37f640d28a 100644 --- a/tests/PhpWordTests/Writer/HTML/Helper.php +++ b/tests/PhpWordTests/Writer/HTML/Helper.php @@ -20,6 +20,8 @@ use DOMDocument; use DOMXPath; +use Exception; +use LibXMLError; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Writer\HTML; @@ -85,13 +87,41 @@ public static function getLength(DOMXPath $xpath, string $query): int return $returnVal; } - public static function getAsHTML(PhpWord $phpWord, string $defaultWhiteSpace = '', string $defaultGenericFont = ''): DOMDocument + public static function getAsHTML(PhpWord $phpWord, string $defaultWhiteSpace = '', string $defaultGenericFont = '', array $validTags = []): DOMDocument { $htmlWriter = new HTML($phpWord); $htmlWriter->setDefaultWhiteSpace($defaultWhiteSpace); $htmlWriter->setDefaultGenericFont($defaultGenericFont); $dom = new DOMDocument(); + // DOMDocument does not always accept HTML5 tags like <ruby> + // So, we can manually filter out those errors for testing purposes ONLY. + $original = libxml_use_internal_errors(true); $dom->loadHTML($htmlWriter->getContent()); + $errors = libxml_get_errors(); + $errorsToReport = []; + foreach ($errors as $error) { + /** @var LibXMLError $error */ + if ($error->code === 801) { + $didFindValidTag = false; + foreach ($validTags as $tag) { + if (trim($error->message) === ('Tag ' . $tag . ' invalid')) { + $didFindValidTag = true; + + break; + } + } + if (!$didFindValidTag) { + $errorsToReport[] = $error; + } + } else { + $errorsToReport[] = $error; + } + } + libxml_clear_errors(); + libxml_use_internal_errors($original); + if (count($errorsToReport) > 0) { + throw new Exception('Errors when loading DOMDocument: ' . print_r($errors, true)); + } return $dom; } diff --git a/tests/PhpWordTests/Writer/ODText/ElementTest.php b/tests/PhpWordTests/Writer/ODText/ElementTest.php index 56bbf025ed..4df140aaa4 100644 --- a/tests/PhpWordTests/Writer/ODText/ElementTest.php +++ b/tests/PhpWordTests/Writer/ODText/ElementTest.php @@ -19,6 +19,8 @@ namespace PhpOffice\PhpWordTests\Writer\ODText; use DateTime; +use PhpOffice\PhpWord\ComplexType\RubyProperties; +use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Shared\XMLWriter; @@ -201,7 +203,7 @@ public function testTextRunTitle(): void $section = $phpWord->addSection(); $section->addTitle('Text Title', 1); $section->addText('Text following Text Title'); - $textRun = new \PhpOffice\PhpWord\Element\TextRun(); + $textRun = new TextRun(); $textRun->addText('Text Run'); $textRun->addText(' Title'); $section->addTitle($textRun, 1); @@ -328,4 +330,36 @@ public function testTrackedChanges(): void $element = "$p2t/text:change"; self::AssertEquals($tc3id, $doc->getElementAttribute($element, 'text:change-id')); } + + /** + * Test ruby output. + * Note that this test will need to be updated when ODT Ruby output supports + * ODT's native ruby functionality. + */ + public function testRubyText(): void + { + $esc = \PhpOffice\PhpWord\Settings::isOutputEscapingEnabled(); + \PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(true); + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $properties = new RubyProperties(); + $properties->setAlignment(RubyProperties::ALIGNMENT_RIGHT_VERTICAL); + $properties->setFontFaceSize(10); + $properties->setFontPointsAboveBaseText(4); + $properties->setFontSizeForBaseText(18); + $properties->setLanguageId('ja-JP'); + + $baseTextRun = new TextRun(null); + $baseTextRun->addText('私'); + $rubyTextRun = new TextRun(null); + $rubyTextRun->addText('わたし'); + $section->addRuby($baseTextRun, $rubyTextRun, $properties); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + \PhpOffice\PhpWord\Settings::setOutputEscapingEnabled($esc); + $p2t = '/office:document-content/office:body/office:text/text:section'; + $element = "$p2t/text:p[2]"; + self::assertTrue($doc->elementExists($element)); + self::assertEquals('私 (わたし)', $doc->getElement($element)->nodeValue); + } } diff --git a/tests/PhpWordTests/Writer/RTF/ElementTest.php b/tests/PhpWordTests/Writer/RTF/ElementTest.php index dbd937bc0d..36504a18f8 100644 --- a/tests/PhpWordTests/Writer/RTF/ElementTest.php +++ b/tests/PhpWordTests/Writer/RTF/ElementTest.php @@ -175,4 +175,45 @@ public function testTitle(): void $expect = "\\pard\\nowidctlpar \\sb0\\sa0{\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}"; self::assertEquals($expect, $this->removeCr($elwrite)); } + + public function testRuby(): void + { + $parentWriter = new RTF(); + $properties = new \PhpOffice\PhpWord\ComplexType\RubyProperties(); + $baseTextRun = new \PhpOffice\PhpWord\Element\TextRun(null); + $baseTextRun->addText('base text'); + $rubyTextRun = new \PhpOffice\PhpWord\Element\TextRun(null); + $rubyTextRun->addText('ruby'); + $element = new \PhpOffice\PhpWord\Element\TextRun(); + $element->addRuby($baseTextRun, $rubyTextRun, $properties); + + $textrun = new RTF\Element\TextRun($parentWriter, $element); + $expect = "\\pard\\nowidctlpar {{base text (ruby)}}\\par\n"; + self::assertEquals($expect, $this->removeCr($textrun)); + } + + public function testRubyTitle(): void + { + $parentWriter = new RTF(); + $properties = new \PhpOffice\PhpWord\ComplexType\RubyProperties(); + $baseTextRun = new \PhpOffice\PhpWord\Element\TextRun(null); + $baseTextRun->addText('base text'); + $rubyTextRun = new \PhpOffice\PhpWord\Element\TextRun(null); + $rubyTextRun->addText('ruby'); + $textRun = new \PhpOffice\PhpWord\Element\TextRun(); + $textRun->addRuby($baseTextRun, $rubyTextRun, $properties); + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord->addTitleStyle( + 1, + ['size' => 24, 'bold' => true, 'color' => '000099'], + ['spaceBefore' => 0, 'spaceAfter' => 2] + ); + $section = $phpWord->addSection(); + $element = $section->addTitle($textRun, 1); + $elwrite = new RTF\Element\Title($parentWriter, $element); + + $expect = "\\pard\\nowidctlpar \\sb0\\sa2{\\outlinelevel0{\\cf0\\f0\\fs48\\b base text (ruby)}\\par\n}"; + self::assertEquals($expect, $this->removeCr($elwrite)); + } } diff --git a/tests/PhpWordTests/Writer/Word2007/ElementTest.php b/tests/PhpWordTests/Writer/Word2007/ElementTest.php index 999e188e82..c22994607b 100644 --- a/tests/PhpWordTests/Writer/Word2007/ElementTest.php +++ b/tests/PhpWordTests/Writer/Word2007/ElementTest.php @@ -19,7 +19,9 @@ namespace PhpOffice\PhpWordTests\Writer\Word2007; use DateTime; +use PhpOffice\PhpWord\ComplexType\RubyProperties; use PhpOffice\PhpWord\Element\Comment; +use PhpOffice\PhpWord\Element\Ruby; use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\PhpWord; @@ -534,4 +536,132 @@ public function testListItemRunStyleWriting(): void self::assertEquals(' in bold', $doc->getElement('/w:document/w:body/w:p/w:r[2]/w:t')->nodeValue); self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r[2]/w:rPr/w:b')); } + + /** + * Test Ruby writing. + */ + public function testRubyWriting(): void + { + $phpWord = new PhpWord(); + + $section = $phpWord->addSection(); + $properties = new RubyProperties(); + $properties->setAlignment(RubyProperties::ALIGNMENT_RIGHT_VERTICAL); + $properties->setFontFaceSize(10); + $properties->setFontPointsAboveBaseText(4); + $properties->setFontSizeForBaseText(18); + $properties->setLanguageId('ja-JP'); + + $baseTextRun = new TextRun(null); + $baseTextRun->addText('私'); + $rubyTextRun = new TextRun(null); + $rubyTextRun->addText('わたし'); + $section->addRuby($baseTextRun, $rubyTextRun, $properties); + + $doc = TestHelperDOCX::getDocument($phpWord); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:ruby')); + // check props + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr')); + self::assertEquals( + RubyProperties::ALIGNMENT_RIGHT_VERTICAL, + $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:rubyAlign', 'w:val') + ); + self::assertEquals( + 10, + $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:hps', 'w:val') + ); + self::assertEquals( + 4, + $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:hpsRaise', 'w:val') + ); + self::assertEquals( + 18, + $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:hpsBaseText', 'w:val') + ); + self::assertEquals( + 'ja-JP', + $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:lid', 'w:val') + ); + // check ruby text + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:ruby/w:rt/w:r/w:t')); + self::assertEquals( + 'わたし', + $doc->getElement('/w:document/w:body/w:p/w:r/w:ruby/w:rt/w:r/w:t')->nodeValue + ); + // check base text + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:ruby/w:rubyBase/w:r/w:t')); + self::assertEquals( + '私', + $doc->getElement('/w:document/w:body/w:p/w:r/w:ruby/w:rubyBase/w:r/w:t')->nodeValue + ); + } + + /** + * Test Ruby title writing. + */ + public function testRubyTitleWriting(): void + { + $phpWord = new PhpWord(); + $phpWord->addTitleStyle(1, ['name' => 'Arial', 'size' => 24, 'bold' => true, 'color' => '990000']); + + $section = $phpWord->addSection(); + $properties = new RubyProperties(); + $properties->setAlignment(RubyProperties::ALIGNMENT_RIGHT_VERTICAL); + $properties->setFontFaceSize(10); + $properties->setFontPointsAboveBaseText(4); + $properties->setFontSizeForBaseText(18); + $properties->setLanguageId('ja-JP'); + + $baseTextRun = new TextRun(null); + $baseTextRun->addText('私'); + $rubyTextRun = new TextRun(null); + $rubyTextRun->addText('わたし'); + + $textRun = new TextRun(); + $textRun->addRuby($baseTextRun, $rubyTextRun, $properties); + $section->addTitle($textRun, 1); + + $doc = TestHelperDOCX::getDocument($phpWord); + // make sure style made it in + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:pPr/w:pStyle')); + self::assertEquals( + 'Heading1', + $doc->getElement('/w:document/w:body/w:p/w:pPr/w:pStyle')->getAttribute('w:val') + ); + // check ruby props + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:ruby')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr')); + self::assertEquals( + RubyProperties::ALIGNMENT_RIGHT_VERTICAL, + $doc->getElement('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:rubyAlign')->getAttribute('w:val') + ); + self::assertEquals( + 10, + $doc->getElement('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:hps')->getAttribute('w:val') + ); + self::assertEquals( + 4, + $doc->getElement('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:hpsRaise')->getAttribute('w:val') + ); + self::assertEquals( + 18, + $doc->getElement('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:hpsBaseText')->getAttribute('w:val') + ); + self::assertEquals( + 'ja-JP', + $doc->getElement('/w:document/w:body/w:p/w:r/w:ruby/w:rubyPr/w:lid')->getAttribute('w:val') + ); + // check ruby text + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:ruby/w:rt/w:r/w:t')); + self::assertEquals( + 'わたし', + $doc->getElement('/w:document/w:body/w:p/w:r/w:ruby/w:rt/w:r/w:t')->nodeValue + ); + // check base text + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:ruby/w:rubyBase/w:r/w:t')); + self::assertEquals( + '私', + $doc->getElement('/w:document/w:body/w:p/w:r/w:ruby/w:rubyBase/w:r/w:t')->nodeValue + ); + } } From cd7d1a26d2ac607bff0398361bd7ee0d8ecb4fd9 Mon Sep 17 00:00:00 2001 From: Progi1984 <progi1984@gmail.com> Date: Wed, 29 Jan 2025 12:51:42 +0100 Subject: [PATCH 229/246] Reader HTML: Support for inherit value for property line-height (#2733) --- docs/changes/1.x/1.4.0.md | 5 +++-- src/PhpWord/Shared/Html.php | 2 +- tests/PhpWordTests/Shared/HtmlTest.php | 5 +++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index c8a019115d..8c2651c8b7 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -20,8 +20,9 @@ - Writer ODText: Support for images inside a textRun by [@Progi1984](https://github.com/Progi1984) fixing [#2240](https://github.com/PHPOffice/PHPWord/issues/2240) in [#2668](https://github.com/PHPOffice/PHPWord/pull/2668) - Allow vAlign and vMerge on Style\Cell to be set to null by [@SpraxDev](https://github.com/SpraxDev) fixing [#2673](https://github.com/PHPOffice/PHPWord/issues/2673) in [#2676](https://github.com/PHPOffice/PHPWord/pull/2676) - Reader HTML: Support for differents size units for table by [@Progi1984](https://github.com/Progi1984) fixing [#2384](https://github.com/PHPOffice/PHPWord/issues/2384), [#2701](https://github.com/PHPOffice/PHPWord/issues/2701) in [#2725](https://github.com/PHPOffice/PHPWord/pull/2725) -- Reader Word2007 : Respect paragraph indent units by [@tugmaks](https://github.com/tugmaks) & [@Progi1984](https://github.com/Progi1984) fixing [#507](https://github.com/PHPOffice/PHPWord/issues/507) in [#2726](https://github.com/PHPOffice/PHPWord/pull/2726) -- Reader Word2007 : Support Header elements within Title elements by [@SpraxDev](https://github.com/SpraxDev) fixing [#2616](https://github.com/PHPOffice/PHPWord/issues/2616), [#2426](https://github.com/PHPOffice/PHPWord/issues/2426) in [#2674](https://github.com/PHPOffice/PHPWord/pull/2674) +- Reader Word2007: Respect paragraph indent units by [@tugmaks](https://github.com/tugmaks) & [@Progi1984](https://github.com/Progi1984) fixing [#507](https://github.com/PHPOffice/PHPWord/issues/507) in [#2726](https://github.com/PHPOffice/PHPWord/pull/2726) +- Reader Word2007: Support Header elements within Title elements by [@SpraxDev](https://github.com/SpraxDev) fixing [#2616](https://github.com/PHPOffice/PHPWord/issues/2616), [#2426](https://github.com/PHPOffice/PHPWord/issues/2426) in [#2674](https://github.com/PHPOffice/PHPWord/pull/2674) +- Reader HTML: Support for inherit value for property line-height by [@Progi1984](https://github.com/Progi1984) fixing [#2683](https://github.com/PHPOffice/PHPWord/issues/2683) in [#2733](https://github.com/PHPOffice/PHPWord/pull/2733) ### Miscellaneous diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 4573daf2a9..cdaf8d8c87 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -741,7 +741,7 @@ protected static function parseStyleDeclarations(array $selectors, array $styles break; case 'line-height': $matches = []; - if ($value === 'normal') { + if ($value === 'normal' || $value === 'inherit') { $spacingLineRule = \PhpOffice\PhpWord\SimpleType\LineSpacingRule::AUTO; $spacing = 0; } elseif (preg_match('/([0-9]+\.?[0-9]*[a-z]+)/', $value, $matches)) { diff --git a/tests/PhpWordTests/Shared/HtmlTest.php b/tests/PhpWordTests/Shared/HtmlTest.php index 7551f51cb8..117f5cb01d 100644 --- a/tests/PhpWordTests/Shared/HtmlTest.php +++ b/tests/PhpWordTests/Shared/HtmlTest.php @@ -249,6 +249,7 @@ public function testParseLineHeight(): void Html::addHtml($section, '<p style="line-height: 120%;">test</p>'); Html::addHtml($section, '<p style="line-height: 0.17in;">test</p>'); Html::addHtml($section, '<p style="line-height: normal;">test</p>'); + Html::addHtml($section, '<p style="line-height: inherit;">test</p>'); $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr/w:spacing')); @@ -270,6 +271,10 @@ public function testParseLineHeight(): void self::assertTrue($doc->elementExists('/w:document/w:body/w:p[5]/w:pPr/w:spacing')); self::assertEquals(Paragraph::LINE_HEIGHT, $doc->getElementAttribute('/w:document/w:body/w:p[5]/w:pPr/w:spacing', 'w:line')); self::assertEquals(LineSpacingRule::AUTO, $doc->getElementAttribute('/w:document/w:body/w:p[5]/w:pPr/w:spacing', 'w:lineRule')); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[6]/w:pPr/w:spacing')); + self::assertEquals(Paragraph::LINE_HEIGHT, $doc->getElementAttribute('/w:document/w:body/w:p[6]/w:pPr/w:spacing', 'w:line')); + self::assertEquals(LineSpacingRule::AUTO, $doc->getElementAttribute('/w:document/w:body/w:p[6]/w:pPr/w:spacing', 'w:lineRule')); } public function testParseCellPaddingStyle(): void From 3b12b4e902b746d43699d8ac9e15414a18f03171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=B7=D0=B0=D0=BC=D0=B0=D1=828405?= <azamat8405@yandex.ru> Date: Wed, 29 Jan 2025 14:59:45 +0300 Subject: [PATCH 230/246] Documentation : Improved `docs/usage/writers.md` (#2732) * Update composer.json azamat8405/phpword * fix: package name * feat: addition in documentation related to phpword.ini * Update docs/usage/writers.md Co-authored-by: Progi1984 <progi1984@gmail.com> --------- Co-authored-by: OlisaevAG <A.Olisaev@soccard.ru> Co-authored-by: Progi1984 <progi1984@gmail.com> --- docs/usage/writers.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/usage/writers.md b/docs/usage/writers.md index f561345a95..97708a0294 100644 --- a/docs/usage/writers.md +++ b/docs/usage/writers.md @@ -110,6 +110,13 @@ Settings::setPdfRendererName(Settings::PDF_RENDERER_MPDF); Settings::setPdfRendererPath(__DIR__ . '/../vendor/mpdf/mpdf'); ``` +or you can edit settings in phpword.ini ( or phpword.ini.dist) file. + +``` ini +pdfRendererName = MPDF ;DomPDF, TCPDF, MPDF +pdfRendererPath = /path/to/your/renderer/folder +``` + ## RTF The name of the writer is `RTF`. From 269a81034090cee09b43627ab25986ba194e1792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=B7=D0=B0=D0=BC=D0=B0=D1=828405?= <azamat8405@yandex.ru> Date: Wed, 29 Jan 2025 19:40:24 +0300 Subject: [PATCH 231/246] Documentation : Improved docs/install.md (#2734) * Update composer.json azamat8405/phpword * fix: package name * Documentation : Improved docs/install.md --------- Co-authored-by: OlisaevAG <A.Olisaev@soccard.ru> --- docs/install.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/install.md b/docs/install.md index a4d61b104d..4e485bf739 100644 --- a/docs/install.md +++ b/docs/install.md @@ -45,6 +45,26 @@ require_once 'path/to/PHPWord/src/PhpWord/Autoloader.php'; The preferred method is the Composer one. +### Configuration + +In order to configure you can create phpword.ini file and load configuration by calling Settings::loadConfig + +``` php +<?php + +Settings::loadConfig(); + +``` + +You can also specify the config file location. (Do not use phpword.ini file in vendor folder) + +``` php +<?php + +Settings::loadConfig(__DIR__ . '/../../phpword.ini'); + +``` + ## Samples After installation, you can browse and use the samples that we've provided, either by command line or using browser. If you can access your PhpWord library folder using browser, point your browser to the `samples` folder, e.g. `http://localhost/PhpWord/samples/`. From fd06f96335a7d486d3f415e6d739cea0fef1e89e Mon Sep 17 00:00:00 2001 From: Michael Frey <michael.frey@gmx.ch> Date: Fri, 31 Jan 2025 19:33:58 +0100 Subject: [PATCH 232/246] Writer ODText: Support Default font color (#2735) * Writer ODText: Support Default font color * clean up * self::assertEquals('false', $element->getAttribute('style:use-window-font-color')); * pull request number added --- docs/changes/1.x/1.4.0.md | 9 ++++- src/PhpWord/Writer/ODText/Part/Styles.php | 3 +- .../Writer/ODText/Style/FontTest.php | 34 +++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 8c2651c8b7..f12bb05b0d 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -12,7 +12,8 @@ - Added support for PHP 8.4 by [@Progi1984](https://github.com/Progi1984) in [#2660](https://github.com/PHPOffice/PHPWord/pull/2660) - Autoload : Allow to use PHPWord without Composer fixing [#2543](https://github.com/PHPOffice/PHPWord/issues/2543), [#2552](https://github.com/PHPOffice/PHPWord/issues/2552), [#2716](https://github.com/PHPOffice/PHPWord/issues/2716), [#2717](https://github.com/PHPOffice/PHPWord/issues/2717) in [#2722](https://github.com/PHPOffice/PHPWord/pull/2722) - Add Default font color for Word by [@Collie-IT](https://github.com/Collie-IT) in [#2700](https://github.com/PHPOffice/PHPWord/pull/2700) -- Writer HTML: Support Default font color by [@MichaelPFrey](https://github.com/MichaelPFrey) +- Writer HTML: Support Default font color by [@MichaelPFrey](https://github.com/MichaelPFrey) in [#2731](https://github.com/PHPOffice/PHPWord/pull/2731) +- Writer ODText: Support Default font color by [@MichaelPFrey](https://github.com/MichaelPFrey) in [#2735](https://github.com/PHPOffice/PHPWord/pull/2735) - Add basic ruby text (phonetic guide) support for Word2007 and HTML Reader/Writer, RTF Writer, basic support for ODT writing by [@Deadpikle](https://github.com/Deadpikle) in [#2727](https://github.com/PHPOffice/PHPWord/pull/2727) ### Bug fixes @@ -35,3 +36,9 @@ - Deprecate `PhpOffice\PhpWord\Style\Paragraph::setIndent()` : Use `PhpOffice\PhpWord\Style\Paragraph::setIndentLeft()` ### BC Breaks + +### Notes +- Writer ODText previously used to set 'style:use-window-font-color' to 'true', now it is set to 'false'. (see [#2735](https://github.com/PHPOffice/PHPWord/pull/2735)) + The effect of this attribute is "implementation dependent" (if implemented at all). + Setting it to false allows setting a default font color and improves interoperabilt, + but may break certain specific use cases. diff --git a/src/PhpWord/Writer/ODText/Part/Styles.php b/src/PhpWord/Writer/ODText/Part/Styles.php index 72b93f5815..f8ec843894 100644 --- a/src/PhpWord/Writer/ODText/Part/Styles.php +++ b/src/PhpWord/Writer/ODText/Part/Styles.php @@ -92,11 +92,12 @@ private function writeDefault(XMLWriter $xmlWriter): void // Font $xmlWriter->startElement('style:text-properties'); - $xmlWriter->writeAttribute('style:use-window-font-color', 'true'); + $xmlWriter->writeAttribute('style:use-window-font-color', 'false'); $xmlWriter->writeAttribute('style:font-name', Settings::getDefaultFontName()); $xmlWriter->writeAttribute('fo:font-size', Settings::getDefaultFontSize() . 'pt'); $xmlWriter->writeAttribute('fo:language', $latinLang[0]); $xmlWriter->writeAttribute('fo:country', $latinLang[1]); + $xmlWriter->writeAttribute('fo:color', '#' . Settings::getDefaultFontColor()); $xmlWriter->writeAttribute('style:letter-kerning', 'true'); $xmlWriter->writeAttribute('style:font-name-asian', Settings::getDefaultFontName() . '2'); $xmlWriter->writeAttribute('style:font-size-asian', Settings::getDefaultFontSize() . 'pt'); diff --git a/tests/PhpWordTests/Writer/ODText/Style/FontTest.php b/tests/PhpWordTests/Writer/ODText/Style/FontTest.php index 5edef8fea6..b377ff4fcd 100644 --- a/tests/PhpWordTests/Writer/ODText/Style/FontTest.php +++ b/tests/PhpWordTests/Writer/ODText/Style/FontTest.php @@ -34,6 +34,40 @@ protected function tearDown(): void TestHelperDOCX::clear(); } + public function testDefaultDefaults(): void + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + + $file = 'styles.xml'; + + $path = '/office:document-styles/office:styles/style:default-style/style:text-properties'; + self::assertTrue($doc->elementExists($path, $file)); + $element = $doc->getElement($path, $file); + + self::assertEquals('#000000', $element->getAttribute('fo:color')); + self::assertEquals('false', $element->getAttribute('style:use-window-font-color')); //has to be set to false so that fo:color can take effect + } + + public function testSettingDefaults(): void + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + + $defaultFontColor = '00FF00'; + $phpWord->setDefaultFontColor($defaultFontColor); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + + $file = 'styles.xml'; + + $path = '/office:document-styles/office:styles/style:default-style/style:text-properties'; + self::assertTrue($doc->elementExists($path, $file)); + $element = $doc->getElement($path, $file); + + self::assertEquals('#' . $defaultFontColor, $element->getAttribute('fo:color')); + } + /** * Test colors. */ From 5914e8ec3752f72ec6c9b372533986ee13954021 Mon Sep 17 00:00:00 2001 From: Sambit Chakraborty <58760654+Sambit003@users.noreply.github.com> Date: Mon, 3 Feb 2025 12:14:09 +0530 Subject: [PATCH 233/246] Writer EPub3 : Added support (#2724) * Feat: Added Epub3 writer support * Add: Tests * Fix: Code convention * Update: composer.lock file with latest requirement * Update: composer.lock file with latest requirement * Update: composer.lock file with latest requirement * Remove: composer.lock * Update: Code conventions for PHP 8.x & Update: .gitignore to include composer.lock (in support of PR #2722 : Autoload) * Add: Text & Image Element * Improvement of Epub3 elements code * Add: Unit tests for full EPub3 codebase * Fix: Code convention errors for EPub3 Unit tests * Fix: Added the suggestions * Revert: composer.json changes -> Now again included the gd & zip extension * Update: composer.json * Add: Generating Epub samples with adherence to the Epub 3 checking procedures * Fix: Null type error in php8.x runtime * Update: Changelog --- .gitignore | 1 + composer.json | 4 +- docs/changes/1.x/1.4.0.md | 2 + samples/Sample_Header.php | 2 +- src/PhpWord/IOFactory.php | 2 +- src/PhpWord/Shared/ZipArchive.php | 11 ++ src/PhpWord/Writer/EPub3.php | 91 ++++++++++++ .../Writer/EPub3/Element/AbstractElement.php | 45 ++++++ src/PhpWord/Writer/EPub3/Element/Image.php | 45 ++++++ src/PhpWord/Writer/EPub3/Element/Text.php | 50 +++++++ src/PhpWord/Writer/EPub3/Part.php | 45 ++++++ .../Writer/EPub3/Part/AbstractPart.php | 56 ++++++++ src/PhpWord/Writer/EPub3/Part/Content.php | 130 ++++++++++++++++++ .../Writer/EPub3/Part/ContentXhtml.php | 117 ++++++++++++++++ src/PhpWord/Writer/EPub3/Part/Manifest.php | 40 ++++++ src/PhpWord/Writer/EPub3/Part/Meta.php | 74 ++++++++++ src/PhpWord/Writer/EPub3/Part/Mimetype.php | 33 +++++ src/PhpWord/Writer/EPub3/Part/Nav.php | 53 +++++++ .../Writer/EPub3/Style/AbstractStyle.php | 75 ++++++++++ src/PhpWord/Writer/EPub3/Style/Font.php | 39 ++++++ src/PhpWord/Writer/EPub3/Style/Paragraph.php | 39 ++++++ src/PhpWord/Writer/EPub3/Style/Table.php | 43 ++++++ src/PhpWord/Writer/WriterPartInterface.php | 10 ++ .../Writer/EPub3/Element/ImageTest.php | 69 ++++++++++ .../Writer/EPub3/Element/TextTest.php | 83 +++++++++++ .../PhpWordTests/Writer/EPub3/ElementTest.php | 26 ++++ .../Writer/EPub3/Part/AbstractPartTest.php | 28 ++++ .../Writer/EPub3/Part/ContentTest.php | 38 +++++ .../Writer/EPub3/Part/ManifestTest.php | 35 +++++ .../Writer/EPub3/Part/MetaTest.php | 53 +++++++ .../Writer/EPub3/Part/MimetypeTest.php | 32 +++++ .../Writer/EPub3/Part/NavTest.php | 49 +++++++ tests/PhpWordTests/Writer/EPub3/PartTest.php | 28 ++++ .../Writer/EPub3/Style/AbstractStyleTest.php | 24 ++++ .../Writer/EPub3/Style/FontTest.php | 25 ++++ .../Writer/EPub3/Style/ParagraphTest.php | 25 ++++ .../Writer/EPub3/Style/TableTest.php | 28 ++++ tests/PhpWordTests/Writer/EPub3/StyleTest.php | 23 ++++ tests/PhpWordTests/Writer/EPub3Test.php | 126 +++++++++++++++++ 39 files changed, 1695 insertions(+), 4 deletions(-) create mode 100644 src/PhpWord/Writer/EPub3.php create mode 100644 src/PhpWord/Writer/EPub3/Element/AbstractElement.php create mode 100644 src/PhpWord/Writer/EPub3/Element/Image.php create mode 100644 src/PhpWord/Writer/EPub3/Element/Text.php create mode 100644 src/PhpWord/Writer/EPub3/Part.php create mode 100644 src/PhpWord/Writer/EPub3/Part/AbstractPart.php create mode 100644 src/PhpWord/Writer/EPub3/Part/Content.php create mode 100644 src/PhpWord/Writer/EPub3/Part/ContentXhtml.php create mode 100644 src/PhpWord/Writer/EPub3/Part/Manifest.php create mode 100644 src/PhpWord/Writer/EPub3/Part/Meta.php create mode 100644 src/PhpWord/Writer/EPub3/Part/Mimetype.php create mode 100644 src/PhpWord/Writer/EPub3/Part/Nav.php create mode 100644 src/PhpWord/Writer/EPub3/Style/AbstractStyle.php create mode 100644 src/PhpWord/Writer/EPub3/Style/Font.php create mode 100644 src/PhpWord/Writer/EPub3/Style/Paragraph.php create mode 100644 src/PhpWord/Writer/EPub3/Style/Table.php create mode 100644 src/PhpWord/Writer/WriterPartInterface.php create mode 100644 tests/PhpWordTests/Writer/EPub3/Element/ImageTest.php create mode 100644 tests/PhpWordTests/Writer/EPub3/Element/TextTest.php create mode 100644 tests/PhpWordTests/Writer/EPub3/ElementTest.php create mode 100644 tests/PhpWordTests/Writer/EPub3/Part/AbstractPartTest.php create mode 100644 tests/PhpWordTests/Writer/EPub3/Part/ContentTest.php create mode 100644 tests/PhpWordTests/Writer/EPub3/Part/ManifestTest.php create mode 100644 tests/PhpWordTests/Writer/EPub3/Part/MetaTest.php create mode 100644 tests/PhpWordTests/Writer/EPub3/Part/MimetypeTest.php create mode 100644 tests/PhpWordTests/Writer/EPub3/Part/NavTest.php create mode 100644 tests/PhpWordTests/Writer/EPub3/PartTest.php create mode 100644 tests/PhpWordTests/Writer/EPub3/Style/AbstractStyleTest.php create mode 100644 tests/PhpWordTests/Writer/EPub3/Style/FontTest.php create mode 100644 tests/PhpWordTests/Writer/EPub3/Style/ParagraphTest.php create mode 100644 tests/PhpWordTests/Writer/EPub3/Style/TableTest.php create mode 100644 tests/PhpWordTests/Writer/EPub3/StyleTest.php create mode 100644 tests/PhpWordTests/Writer/EPub3Test.php diff --git a/.gitignore b/.gitignore index 0b9d0608d0..6918df72e6 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ _build /build phpunit.xml composer.phar +composer.lock vendor /report /build diff --git a/composer.json b/composer.json index efebe941e7..5055105d16 100644 --- a/composer.json +++ b/composer.json @@ -108,10 +108,10 @@ "require": { "php": "^7.1|^8.0", "ext-dom": "*", - "ext-gd": "*", + "ext-gd": "*", + "ext-zip": "*", "ext-json": "*", "ext-xml": "*", - "ext-zip": "*", "phpoffice/math": "^0.2" }, "require-dev": { diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index f12bb05b0d..96b86a1bac 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -16,6 +16,8 @@ - Writer ODText: Support Default font color by [@MichaelPFrey](https://github.com/MichaelPFrey) in [#2735](https://github.com/PHPOffice/PHPWord/pull/2735) - Add basic ruby text (phonetic guide) support for Word2007 and HTML Reader/Writer, RTF Writer, basic support for ODT writing by [@Deadpikle](https://github.com/Deadpikle) in [#2727](https://github.com/PHPOffice/PHPWord/pull/2727) +- Added Support for Writer Epub3 by [@Sambit003](https://github.com/Sambit003) in [#2724](https://github.com/PHPOffice/PHPWord/pull/2724) + ### Bug fixes - Writer ODText: Support for images inside a textRun by [@Progi1984](https://github.com/Progi1984) fixing [#2240](https://github.com/PHPOffice/PHPWord/issues/2240) in [#2668](https://github.com/PHPOffice/PHPWord/pull/2668) diff --git a/samples/Sample_Header.php b/samples/Sample_Header.php index eab7033275..57bb10a4c6 100644 --- a/samples/Sample_Header.php +++ b/samples/Sample_Header.php @@ -31,7 +31,7 @@ } // Set writers -$writers = ['Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf', 'HTML' => 'html', 'PDF' => 'pdf']; +$writers = ['Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf', 'HTML' => 'html', 'PDF' => 'pdf', 'EPub3' => 'epub']; // Set PDF renderer if (null === Settings::getPdfRendererPath()) { diff --git a/src/PhpWord/IOFactory.php b/src/PhpWord/IOFactory.php index 55c374a8b9..50c419cae2 100644 --- a/src/PhpWord/IOFactory.php +++ b/src/PhpWord/IOFactory.php @@ -36,7 +36,7 @@ abstract class IOFactory */ public static function createWriter(PhpWord $phpWord, $name = 'Word2007') { - if ($name !== 'WriterInterface' && !in_array($name, ['ODText', 'RTF', 'Word2007', 'HTML', 'PDF'], true)) { + if ($name !== 'WriterInterface' && !in_array($name, ['ODText', 'RTF', 'Word2007', 'HTML', 'PDF', 'EPub3'], true)) { throw new Exception("\"{$name}\" is not a valid writer."); } diff --git a/src/PhpWord/Shared/ZipArchive.php b/src/PhpWord/Shared/ZipArchive.php index 3ee3869191..bce7f18e0f 100644 --- a/src/PhpWord/Shared/ZipArchive.php +++ b/src/PhpWord/Shared/ZipArchive.php @@ -423,4 +423,15 @@ public function pclzipLocateName($filename) return ($listIndex > -1) ? $listIndex : false; } + + /** + * Add an empty directory to the zip archive (emulate \ZipArchive). + * + * @param string $dirname Directory name to add to the zip archive + */ + public function addEmptyDir(string $dirname): bool + { + // Create a directory entry by adding an empty file with trailing slash + return $this->addFromString(rtrim($dirname, '/') . '/', ''); + } } diff --git a/src/PhpWord/Writer/EPub3.php b/src/PhpWord/Writer/EPub3.php new file mode 100644 index 0000000000..b2ed9700d1 --- /dev/null +++ b/src/PhpWord/Writer/EPub3.php @@ -0,0 +1,91 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer; + +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Writer\EPub3\Part\AbstractPart; + +/** + * EPub3 writer. + */ +class EPub3 extends AbstractWriter implements WriterInterface +{ + /** + * Create new EPub3 writer. + */ + public function __construct(?PhpWord $phpWord = null) + { + // Assign PhpWord + $this->setPhpWord($phpWord); + + // Create parts + $this->parts = [ + 'Mimetype' => 'mimetype', + 'Content' => 'content.opf', + 'Toc' => 'toc.ncx', + 'Styles' => 'styles.css', + 'Manifest' => 'META-INF/container.xml', + 'Nav' => 'nav.xhtml', + 'ContentXhtml' => 'content.xhtml', + ]; + foreach (array_keys($this->parts) as $partName) { + $partClass = static::class . '\\Part\\' . $partName; + if (class_exists($partClass)) { + /** @var WriterPartInterface $part */ + $part = new $partClass($partName === 'Content' || $partName === 'ContentXhtml' ? $phpWord : null); + $part->setParentWriter($this); + $this->writerParts[strtolower($partName)] = $part; + } + } + + // Set package paths + $this->mediaPaths = ['image' => 'Images/', 'object' => 'Objects/']; + } + + /** + * Save PhpWord to file. + */ + public function save(string $filename): void + { + $filename = $this->getTempFile($filename); + $zip = $this->getZipArchive($filename); + + // Add mimetype first without compression + $zip->addFromString('mimetype', 'application/epub+zip'); + $zip->addEmptyDir('META-INF'); + + // Add other files + foreach ($this->parts as $partName => $fileName) { + if ($fileName === '') { + continue; + } + $part = $this->getWriterPart($partName); + if (!$part instanceof AbstractPart) { + continue; + } + $zip->addFromString($fileName, $part->write()); + } + + // Close zip archive + $zip->close(); + + // Cleanup temp file + $this->cleanupTempFile(); + } +} diff --git a/src/PhpWord/Writer/EPub3/Element/AbstractElement.php b/src/PhpWord/Writer/EPub3/Element/AbstractElement.php new file mode 100644 index 0000000000..c95efec0f6 --- /dev/null +++ b/src/PhpWord/Writer/EPub3/Element/AbstractElement.php @@ -0,0 +1,45 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\EPub3\Element; + +use PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement as Word2007AbstractElement; + +/** + * Abstract element writer. + * + * @since 0.11.0 + */ +abstract class AbstractElement extends Word2007AbstractElement +{ + /** + * Get class name of writer element based on read element. + * + * @param \PhpOffice\PhpWord\Element\AbstractElement $element + */ + public static function getElementClass($element): string + { + $elementClass = str_replace('PhpOffice\\PhpWord\\Element\\', '', get_class($element)); + $writerClass = 'PhpOffice\\PhpWord\\Writer\\EPub3\\Element\\' . $elementClass; + if (!class_exists($writerClass)) { + throw new \PhpOffice\PhpWord\Exception\Exception("Writer element class {$writerClass} not found."); + } + + return $writerClass; + } +} diff --git a/src/PhpWord/Writer/EPub3/Element/Image.php b/src/PhpWord/Writer/EPub3/Element/Image.php new file mode 100644 index 0000000000..56e9f7c990 --- /dev/null +++ b/src/PhpWord/Writer/EPub3/Element/Image.php @@ -0,0 +1,45 @@ +<?php + +namespace PhpOffice\PhpWord\Writer\EPub3\Element; + +use PhpOffice\PhpWord\Element\Image as ImageElement; + +/** + * Image element writer for EPub3. + */ +class Image extends AbstractElement +{ + /** + * Write element. + */ + public function write(): void + { + $xmlWriter = $this->getXmlWriter(); + $xmlWriter->setIndent(false); + $element = $this->getElement(); + if (!$element instanceof ImageElement) { + return; + } + $mediaIndex = $element->getMediaIndex(); + $target = 'media/image' . $mediaIndex . '.' . $element->getImageExtension(); + if (!$this->withoutP) { + $xmlWriter->startElement('p'); + } + $xmlWriter->startElement('img'); + $xmlWriter->writeAttribute('src', $target); + $style = ''; + if ($element->getStyle()->getWidth() !== null) { + $style .= 'width:' . $element->getStyle()->getWidth() . 'px;'; + } + if ($element->getStyle()->getHeight() !== null) { + $style .= 'height:' . $element->getStyle()->getHeight() . 'px;'; + } + if ($style !== '') { + $xmlWriter->writeAttribute('style', $style); + } + $xmlWriter->endElement(); // img + if (!$this->withoutP) { + $xmlWriter->endElement(); // p + } + } +} diff --git a/src/PhpWord/Writer/EPub3/Element/Text.php b/src/PhpWord/Writer/EPub3/Element/Text.php new file mode 100644 index 0000000000..2e138c0509 --- /dev/null +++ b/src/PhpWord/Writer/EPub3/Element/Text.php @@ -0,0 +1,50 @@ +<?php + +namespace PhpOffice\PhpWord\Writer\EPub3\Element; + +/** + * Text element writer for EPub3. + */ +class Text extends AbstractElement +{ + /** + * Write element. + */ + public function write(): void + { + $xmlWriter = $this->getXmlWriter(); + $xmlWriter->setIndent(true); + $xmlWriter->setIndentString(' '); + $element = $this->getElement(); + if (!$element instanceof \PhpOffice\PhpWord\Element\Text) { + return; + } + + $fontStyle = $element->getFontStyle(); + $paragraphStyle = $element->getParagraphStyle(); + + if (!$this->withoutP) { + $xmlWriter->startElement('p'); + if (is_string($paragraphStyle) && $paragraphStyle !== '') { + $xmlWriter->writeAttribute('class', $paragraphStyle); + } + } + + if (!empty($fontStyle)) { + $xmlWriter->startElement('span'); + if (is_string($fontStyle)) { + $xmlWriter->writeAttribute('class', $fontStyle); + } + } + + $xmlWriter->text($element->getText()); + + if (!empty($fontStyle)) { + $xmlWriter->endElement(); // span + } + + if (!$this->withoutP) { + $xmlWriter->endElement(); // p + } + } +} diff --git a/src/PhpWord/Writer/EPub3/Part.php b/src/PhpWord/Writer/EPub3/Part.php new file mode 100644 index 0000000000..25dfa6654d --- /dev/null +++ b/src/PhpWord/Writer/EPub3/Part.php @@ -0,0 +1,45 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\EPub3; + +use PhpOffice\PhpWord\Exception\Exception; + +/** + * Factory class for EPub3 parts. + */ +class Part +{ + /** + * Get the fully qualified class name for a specific part type. + * + * @param string $type The type of part (Content, Manifest, Meta, Mimetype) + * + * @return string The fully qualified class name + */ + public static function getPartClass(string $type): string + { + $class = 'PhpOffice\\PhpWord\\Writer\\EPub3\\Part\\' . $type; + + if (!class_exists($class)) { + throw new Exception("Invalid part type: {$type}"); + } + + return $class; + } +} diff --git a/src/PhpWord/Writer/EPub3/Part/AbstractPart.php b/src/PhpWord/Writer/EPub3/Part/AbstractPart.php new file mode 100644 index 0000000000..692203ba6c --- /dev/null +++ b/src/PhpWord/Writer/EPub3/Part/AbstractPart.php @@ -0,0 +1,56 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\EPub3\Part; + +use PhpOffice\PhpWord\Writer\AbstractWriter; +use PhpOffice\PhpWord\Writer\WriterPartInterface; + +/** + * Abstract class for EPub3 parts. + */ +abstract class AbstractPart implements WriterPartInterface +{ + /** + * Parent writer. + * + * @var AbstractWriter + */ + protected $parentWriter; + + /** + * Set parent writer. + */ + public function setParentWriter(AbstractWriter $writer): void + { + $this->parentWriter = $writer; + } + + /** + * Get parent writer. + */ + public function getParentWriter(): AbstractWriter + { + return $this->parentWriter; + } + + /** + * Write part content. + */ + abstract public function write(): string; +} diff --git a/src/PhpWord/Writer/EPub3/Part/Content.php b/src/PhpWord/Writer/EPub3/Part/Content.php new file mode 100644 index 0000000000..217c56cc1f --- /dev/null +++ b/src/PhpWord/Writer/EPub3/Part/Content.php @@ -0,0 +1,130 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\EPub3\Part; + +use PhpOffice\PhpWord\Exception\Exception; +use PhpOffice\PhpWord\PhpWord; +use XMLWriter; + +/** + * Class for EPub3 content part. + */ +class Content extends AbstractPart +{ + /** + * PHPWord object. + * + * @var ?PhpWord + */ + private $phpWord; + + /** + * Constructor. + */ + public function __construct(?PhpWord $phpWord = null) + { + $this->phpWord = $phpWord; + } + + /** + * Get XML Writer. + * + * @return XMLWriter + */ + protected function getXmlWriter() + { + $xmlWriter = new XMLWriter(); + $xmlWriter->openMemory(); + $xmlWriter->startDocument('1.0', 'UTF-8'); + + return $xmlWriter; + } + + /** + * Write part content. + */ + public function write(): string + { + if ($this->phpWord === null) { + throw new Exception('No PhpWord assigned.'); + } + + $xmlWriter = $this->getXmlWriter(); + $docInfo = $this->phpWord->getDocInfo(); + + // Write package + $xmlWriter->startElement('package'); + $xmlWriter->writeAttribute('xmlns', 'http://www.idpf.org/2007/opf'); + $xmlWriter->writeAttribute('version', '3.0'); + $xmlWriter->writeAttribute('unique-identifier', 'book-id'); + $xmlWriter->writeAttribute('xml:lang', 'en'); + + // Write metadata + $xmlWriter->startElement('metadata'); + $xmlWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); + $xmlWriter->writeAttribute('xmlns:opf', 'http://www.idpf.org/2007/opf'); + + // Required elements + $xmlWriter->startElement('dc:identifier'); + $xmlWriter->writeAttribute('id', 'book-id'); + $xmlWriter->text('book-id-' . uniqid()); + $xmlWriter->endElement(); + $xmlWriter->writeElement('dc:title', $docInfo->getTitle() ?: 'Untitled'); + $xmlWriter->writeElement('dc:language', 'en'); + + // Required modified timestamp + $xmlWriter->startElement('meta'); + $xmlWriter->writeAttribute('property', 'dcterms:modified'); + $xmlWriter->text(date('Y-m-d\TH:i:s\Z')); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); // metadata + + // Write manifest + $xmlWriter->startElement('manifest'); + + // Add nav document (required) + $xmlWriter->startElement('item'); + $xmlWriter->writeAttribute('id', 'nav'); + $xmlWriter->writeAttribute('href', 'nav.xhtml'); + $xmlWriter->writeAttribute('media-type', 'application/xhtml+xml'); + $xmlWriter->writeAttribute('properties', 'nav'); + $xmlWriter->endElement(); + + // Add content document + $xmlWriter->startElement('item'); + $xmlWriter->writeAttribute('id', 'content'); + $xmlWriter->writeAttribute('href', 'content.xhtml'); + $xmlWriter->writeAttribute('media-type', 'application/xhtml+xml'); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); // manifest + + // Write spine + $xmlWriter->startElement('spine'); + $xmlWriter->startElement('itemref'); + $xmlWriter->writeAttribute('idref', 'content'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); // spine + + $xmlWriter->endElement(); // package + + return $xmlWriter->outputMemory(true); + } +} diff --git a/src/PhpWord/Writer/EPub3/Part/ContentXhtml.php b/src/PhpWord/Writer/EPub3/Part/ContentXhtml.php new file mode 100644 index 0000000000..3ebd82638e --- /dev/null +++ b/src/PhpWord/Writer/EPub3/Part/ContentXhtml.php @@ -0,0 +1,117 @@ +<?php + +namespace PhpOffice\PhpWord\Writer\EPub3\Part; + +use PhpOffice\PhpWord\Element\Text; +use PhpOffice\PhpWord\Element\TextRun; +use PhpOffice\PhpWord\PhpWord; +use XMLWriter; + +/** + * Class for EPub3 content.xhtml part. + */ +class ContentXhtml extends AbstractPart +{ + /** + * PHPWord object. + * + * @var ?PhpWord + */ + private $phpWord; + + /** + * Constructor. + */ + public function __construct(?PhpWord $phpWord = null) + { + $this->phpWord = $phpWord; + } + + /** + * Get XML Writer. + * + * @return XMLWriter + */ + protected function getXmlWriter() + { + $xmlWriter = new XMLWriter(); + $xmlWriter->openMemory(); + + return $xmlWriter; + } + + /** + * Write part content. + */ + public function write(): string + { + if ($this->phpWord === null) { + throw new \PhpOffice\PhpWord\Exception\Exception('No PhpWord assigned.'); + } + + $xmlWriter = $this->getXmlWriter(); + + $xmlWriter->startDocument('1.0', 'UTF-8'); + $xmlWriter->startElement('html'); + $xmlWriter->writeAttribute('xmlns', 'http://www.w3.org/1999/xhtml'); + $xmlWriter->writeAttribute('xmlns:epub', 'http://www.idpf.org/2007/ops'); + $xmlWriter->startElement('head'); + $xmlWriter->writeElement('title', $this->phpWord->getDocInfo()->getTitle() ?: 'Untitled'); + $xmlWriter->endElement(); // head + $xmlWriter->startElement('body'); + + // Write sections content + foreach ($this->phpWord->getSections() as $section) { + $xmlWriter->startElement('div'); + $xmlWriter->writeAttribute('class', 'section'); + + foreach ($section->getElements() as $element) { + if ($element instanceof TextRun) { + $xmlWriter->startElement('p'); + $this->writeTextRun($element, $xmlWriter); + $xmlWriter->endElement(); // p + } elseif (method_exists($element, 'getText')) { + $text = $element->getText(); + $xmlWriter->startElement('p'); + if ($text instanceof TextRun) { + $this->writeTextRun($text, $xmlWriter); + } elseif ($text !== null) { + $xmlWriter->text((string) $text); + } + $xmlWriter->endElement(); // p + } + } + + $xmlWriter->endElement(); // div + } + + $xmlWriter->endElement(); // body + $xmlWriter->endElement(); // html + + return $xmlWriter->outputMemory(true); + } + + protected function writeTextElement(\PhpOffice\PhpWord\Element\AbstractElement $textElement, XMLWriter $xmlWriter): void + { + if ($textElement instanceof Text) { + $text = $textElement->getText(); + if ($text !== null) { + $xmlWriter->text((string) $text); + } + } elseif (is_object($textElement) && method_exists($textElement, 'getText')) { + $text = $textElement->getText(); + if ($text instanceof TextRun) { + $this->writeTextRun($text, $xmlWriter); + } elseif ($text !== null) { + $xmlWriter->text((string) $text); + } + } + } + + protected function writeTextRun(TextRun $textRun, XMLWriter $xmlWriter): void + { + foreach ($textRun->getElements() as $element) { + $this->writeTextElement($element, $xmlWriter); + } + } +} diff --git a/src/PhpWord/Writer/EPub3/Part/Manifest.php b/src/PhpWord/Writer/EPub3/Part/Manifest.php new file mode 100644 index 0000000000..fcb0d1f428 --- /dev/null +++ b/src/PhpWord/Writer/EPub3/Part/Manifest.php @@ -0,0 +1,40 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\EPub3\Part; + +/** + * Class for EPub3 manifest part. + */ +class Manifest extends AbstractPart +{ + /** + * Write part content. + */ + public function write(): string + { + $content = '<?xml version="1.0" encoding="UTF-8"?>'; + $content .= '<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">'; + $content .= '<rootfiles>'; + $content .= '<rootfile full-path="content.opf" media-type="application/oebps-package+xml"/>'; + $content .= '</rootfiles>'; + $content .= '</container>'; + + return $content; + } +} diff --git a/src/PhpWord/Writer/EPub3/Part/Meta.php b/src/PhpWord/Writer/EPub3/Part/Meta.php new file mode 100644 index 0000000000..4b01097653 --- /dev/null +++ b/src/PhpWord/Writer/EPub3/Part/Meta.php @@ -0,0 +1,74 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\EPub3\Part; + +use PhpOffice\PhpWord\Shared\XMLWriter; + +/** + * Class for EPub3 metadata part. + */ +class Meta extends AbstractPart +{ + /** + * Get XML Writer. + */ + protected function getXmlWriter(): XMLWriter + { + $xmlWriter = new XMLWriter(); + $xmlWriter->openMemory(); + $xmlWriter->startDocument('1.0', 'UTF-8'); + + return $xmlWriter; + } + + /** + * Write part content. + */ + public function write(): string + { + $xmlWriter = $this->getXmlWriter(); + + $xmlWriter->startElement('metadata'); + $xmlWriter->writeAttribute('xmlns', 'http://www.idpf.org/2007/opf'); + $xmlWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); + + // Write basic metadata + $title = $this->getParentWriter()->getPhpWord()->getDocInfo()->getTitle() ?: 'Sample EPub3 Document'; + $xmlWriter->writeRaw('<dc:title>' . htmlspecialchars($title, ENT_QUOTES) . '</dc:title>'); + $xmlWriter->writeElement('dc:language', 'en'); + $xmlWriter->writeElement('dc:identifier', 'urn:uuid:12345'); + $xmlWriter->writeAttribute('id', 'bookid'); + + // Write document info if available + $docInfo = $this->getParentWriter()->getPhpWord()->getDocInfo(); + if ($docInfo->getCreator()) { + $xmlWriter->writeElement('dc:creator', $docInfo->getCreator()); + } + + // Write modification date + $xmlWriter->startElement('meta'); + $xmlWriter->writeAttribute('property', 'dcterms:modified'); + $xmlWriter->text('2023-01-01T00:00:00Z'); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); // metadata + + return $xmlWriter->getData(); + } +} diff --git a/src/PhpWord/Writer/EPub3/Part/Mimetype.php b/src/PhpWord/Writer/EPub3/Part/Mimetype.php new file mode 100644 index 0000000000..8e5b7d41ba --- /dev/null +++ b/src/PhpWord/Writer/EPub3/Part/Mimetype.php @@ -0,0 +1,33 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\EPub3\Part; + +/** + * Class for EPub3 mimetype part. + */ +class Mimetype extends AbstractPart +{ + /** + * Write part content. + */ + public function write(): string + { + return 'application/epub+zip'; + } +} diff --git a/src/PhpWord/Writer/EPub3/Part/Nav.php b/src/PhpWord/Writer/EPub3/Part/Nav.php new file mode 100644 index 0000000000..3e6de71c96 --- /dev/null +++ b/src/PhpWord/Writer/EPub3/Part/Nav.php @@ -0,0 +1,53 @@ +<?php + +namespace PhpOffice\PhpWord\Writer\EPub3\Part; + +use XMLWriter; + +class Nav extends AbstractPart +{ + protected function getXmlWriter(): XMLWriter + { + $xmlWriter = new XMLWriter(); + $xmlWriter->openMemory(); + + return $xmlWriter; + } + + public function write(): string + { + $xmlWriter = $this->getXmlWriter(); + + $xmlWriter->startDocument('1.0', 'UTF-8'); + $xmlWriter->startElement('html'); + $xmlWriter->writeAttribute('xmlns', 'http://www.w3.org/1999/xhtml'); + $xmlWriter->writeAttribute('xmlns:epub', 'http://www.idpf.org/2007/ops'); + + $xmlWriter->startElement('head'); + $xmlWriter->writeElement('title', 'Navigation'); + $xmlWriter->endElement(); // head + + $xmlWriter->startElement('body'); + $xmlWriter->startElement('nav'); + $xmlWriter->writeAttribute('epub:type', 'toc'); + $xmlWriter->writeAttribute('id', 'toc'); + + // Add navigation items here if needed + $xmlWriter->writeElement('h1', 'Table of Contents'); + $xmlWriter->startElement('ol'); + // Add at least one list item to satisfy EPUB 3.3 requirements + $xmlWriter->startElement('li'); + $xmlWriter->startElement('a'); + $xmlWriter->writeAttribute('href', 'content.xhtml'); + $xmlWriter->text('Content'); + $xmlWriter->endElement(); // a + $xmlWriter->endElement(); // li + $xmlWriter->endElement(); // ol + + $xmlWriter->endElement(); // nav + $xmlWriter->endElement(); // body + $xmlWriter->endElement(); // html + + return $xmlWriter->outputMemory(); + } +} diff --git a/src/PhpWord/Writer/EPub3/Style/AbstractStyle.php b/src/PhpWord/Writer/EPub3/Style/AbstractStyle.php new file mode 100644 index 0000000000..82cd488b62 --- /dev/null +++ b/src/PhpWord/Writer/EPub3/Style/AbstractStyle.php @@ -0,0 +1,75 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\EPub3\Style; + +use PhpOffice\PhpWord\Shared\XMLWriter; +use PhpOffice\PhpWord\Writer\AbstractWriter; + +/** + * Abstract class for EPub3 styles. + */ +abstract class AbstractStyle +{ + /** + * Parent writer. + * + * @var AbstractWriter + */ + protected $parentWriter; + + /** + * XML Writer. + * + * @var XMLWriter + */ + protected $xmlWriter; + + /** + * Set parent writer. + */ + public function setParentWriter(AbstractWriter $writer): self + { + $this->parentWriter = $writer; + + return $this; + } + + /** + * Set XML Writer. + */ + public function setXmlWriter(XMLWriter $writer): self + { + $this->xmlWriter = $writer; + + return $this; + } + + /** + * Get parent writer. + */ + public function getParentWriter(): AbstractWriter + { + return $this->parentWriter; + } + + /** + * Write style content. + */ + abstract public function write(): string; +} diff --git a/src/PhpWord/Writer/EPub3/Style/Font.php b/src/PhpWord/Writer/EPub3/Style/Font.php new file mode 100644 index 0000000000..4e35eeee41 --- /dev/null +++ b/src/PhpWord/Writer/EPub3/Style/Font.php @@ -0,0 +1,39 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\EPub3\Style; + +/** + * Class for EPub3 font styles. + */ +class Font extends AbstractStyle +{ + /** + * Write style content. + */ + public function write(): string + { + $content = 'body {'; + $content .= 'font-family: "Times New Roman", Times, serif;'; + $content .= 'font-size: 12pt;'; + $content .= 'color: #000000;'; + $content .= '}'; + + return $content; + } +} diff --git a/src/PhpWord/Writer/EPub3/Style/Paragraph.php b/src/PhpWord/Writer/EPub3/Style/Paragraph.php new file mode 100644 index 0000000000..3503c38d15 --- /dev/null +++ b/src/PhpWord/Writer/EPub3/Style/Paragraph.php @@ -0,0 +1,39 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\EPub3\Style; + +/** + * Class for EPub3 paragraph styles. + */ +class Paragraph extends AbstractStyle +{ + /** + * Write style content. + */ + public function write(): string + { + $content = 'p {'; + $content .= 'margin-top: 0;'; + $content .= 'margin-bottom: 1em;'; + $content .= 'text-align: left;'; + $content .= '}'; + + return $content; + } +} diff --git a/src/PhpWord/Writer/EPub3/Style/Table.php b/src/PhpWord/Writer/EPub3/Style/Table.php new file mode 100644 index 0000000000..fe062fae89 --- /dev/null +++ b/src/PhpWord/Writer/EPub3/Style/Table.php @@ -0,0 +1,43 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWord\Writer\EPub3\Style; + +/** + * Class for EPub3 table styles. + */ +class Table extends AbstractStyle +{ + /** + * Write style content. + */ + public function write(): string + { + $content = 'table {'; + $content .= 'border-collapse: collapse;'; + $content .= 'width: 100%;'; + $content .= '}'; + $content .= 'th, td {'; + $content .= 'border: 1px solid black;'; + $content .= 'padding: 8px;'; + $content .= 'text-align: left;'; + $content .= '}'; + + return $content; + } +} diff --git a/src/PhpWord/Writer/WriterPartInterface.php b/src/PhpWord/Writer/WriterPartInterface.php new file mode 100644 index 0000000000..00577bad84 --- /dev/null +++ b/src/PhpWord/Writer/WriterPartInterface.php @@ -0,0 +1,10 @@ +<?php + +namespace PhpOffice\PhpWord\Writer; + +interface WriterPartInterface +{ + public function setParentWriter(AbstractWriter $parentWriter): void; + + public function write(): string; +} diff --git a/tests/PhpWordTests/Writer/EPub3/Element/ImageTest.php b/tests/PhpWordTests/Writer/EPub3/Element/ImageTest.php new file mode 100644 index 0000000000..53685f72dc --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3/Element/ImageTest.php @@ -0,0 +1,69 @@ +<?php + +namespace PhpOffice\PhpWordTests\Writer\EPub3\Element; + +use PhpOffice\PhpWord\Element\Image; +use PhpOffice\PhpWord\Shared\XMLWriter; +use PhpOffice\PhpWord\Style\Image as ImageStyle; +use PhpOffice\PhpWord\Writer\EPub3\Element\Image as ImageWriter; +use PHPUnit\Framework\TestCase; + +class ImageTest extends TestCase +{ + /** + * @var XMLWriter + */ + private $xmlWriter; + + /** + * @var Image + */ + private $element; + + /** + * @var ImageWriter + */ + private $writer; + + protected function setUp(): void + { + $this->xmlWriter = new XMLWriter(); + $style = new ImageStyle(); + $style->setWidth(100); + $style->setHeight(100); + $this->element = new Image('tests/PhpWordTests/_files/images/earth.jpg', $style); + $this->writer = new ImageWriter($this->xmlWriter, $this->element); + } + + public function testWrite(): void + { + $this->writer->write(); + + $expected = '<p><img src="https://github.com/media/image.jpg" style="width:500px;height:500px;"/></p>'; + self::assertEquals($expected, $this->xmlWriter->getData()); + } + + public function testWriteWithoutP(): void + { + $style = new ImageStyle(); + $style->setWidth(100); + $style->setHeight(100); + $this->element = new Image('tests/PhpWordTests/_files/images/earth.jpg', $style); + $this->writer = new ImageWriter($this->xmlWriter, $this->element, true); + + $this->writer->write(); + + $expected = '<img src="https://github.com/media/image.jpg" style="width:500px;height:500px;"/>'; + self::assertEquals($expected, $this->xmlWriter->getData()); + } + + public function testWriteWithInvalidElement(): void + { + $invalidElement = $this->createMock(\PhpOffice\PhpWord\Element\AbstractElement::class); + $writer = new ImageWriter($this->xmlWriter, $invalidElement); + + $writer->write(); + + self::assertEquals('', $this->xmlWriter->getData()); + } +} diff --git a/tests/PhpWordTests/Writer/EPub3/Element/TextTest.php b/tests/PhpWordTests/Writer/EPub3/Element/TextTest.php new file mode 100644 index 0000000000..38490691d5 --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3/Element/TextTest.php @@ -0,0 +1,83 @@ +<?php + +namespace PhpOffice\PhpWordTests\Writer\EPub3\Element; + +use PhpOffice\PhpWord\Element\Text; +use PhpOffice\PhpWord\Shared\XMLWriter; +use PhpOffice\PhpWord\Writer\EPub3\Element\Text as TextWriter; +use PHPUnit\Framework\TestCase; + +class TextTest extends TestCase +{ + /** + * @var XMLWriter + */ + private $xmlWriter; + + /** + * @var Text + */ + private $element; + + /** + * @var TextWriter + */ + private $writer; + + protected function setUp(): void + { + $this->xmlWriter = new XMLWriter(); + $this->element = new Text('Sample Text'); + $this->writer = new TextWriter($this->xmlWriter, $this->element); + } + + public function testWrite(): void + { + $this->writer->write(); + + $expected = "<p>\n <span>Sample Text</span>\n</p>\n"; + self::assertEquals($expected, $this->xmlWriter->getData()); + } + + public function testWriteWithFontStyle(): void + { + $this->element->setFontStyle('customStyle'); + + $this->writer->write(); + + $expected = "<p>\n <span class=\"customStyle\">Sample Text</span>\n</p>\n"; + self::assertEquals($expected, $this->xmlWriter->getData()); + } + + public function testWriteWithParagraphStyle(): void + { + $this->element->setParagraphStyle('paragraphStyle'); + + $this->writer->write(); + + $expected = "<p class=\"paragraphStyle\">\n <span>Sample Text</span>\n</p>\n"; + self::assertEquals($expected, $this->xmlWriter->getData()); + } + + public function testWriteWithoutP(): void + { + $text = new Text('Sample Text'); + $xmlWriter = new XMLWriter(); + $this->writer = new TextWriter($xmlWriter, $text, true); + + $this->writer->write(); + + $expected = "<span>Sample Text</span>\n"; + self::assertEquals($expected, $xmlWriter->getData()); + } + + public function testWriteWithInvalidElement(): void + { + $invalidElement = $this->createMock(\PhpOffice\PhpWord\Element\AbstractElement::class); + $writer = new TextWriter($this->xmlWriter, $invalidElement); + + $writer->write(); + + self::assertEquals('', $this->xmlWriter->getData()); + } +} diff --git a/tests/PhpWordTests/Writer/EPub3/ElementTest.php b/tests/PhpWordTests/Writer/EPub3/ElementTest.php new file mode 100644 index 0000000000..af745d9176 --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3/ElementTest.php @@ -0,0 +1,26 @@ +<?php + +namespace PhpOffice\PhpWordTests\Writer\EPub3; + +use PhpOffice\PhpWord\Element\AbstractElement; +use PhpOffice\PhpWord\Element\Text; +use PhpOffice\PhpWord\Writer\EPub3\Element\AbstractElement as WriterElement; +use PHPUnit\Framework\TestCase; + +class ElementTest extends TestCase +{ + public function testGetElementClass(): void + { + $element = new Text('test'); + $class = WriterElement::getElementClass($element); + self::assertEquals('PhpOffice\\PhpWord\\Writer\\EPub3\\Element\\Text', $class); + } + + public function testGetElementClassWithInvalidElement(): void + { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); + + $element = $this->createMock(AbstractElement::class); + WriterElement::getElementClass($element); + } +} diff --git a/tests/PhpWordTests/Writer/EPub3/Part/AbstractPartTest.php b/tests/PhpWordTests/Writer/EPub3/Part/AbstractPartTest.php new file mode 100644 index 0000000000..5151eea24c --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3/Part/AbstractPartTest.php @@ -0,0 +1,28 @@ +<?php + +namespace PhpOffice\PhpWordTests\Writer\EPub3\Part; + +use PhpOffice\PhpWord\Writer\EPub3; +use PhpOffice\PhpWord\Writer\EPub3\Part\AbstractPart; +use PHPUnit\Framework\TestCase; + +class AbstractPartTest extends TestCase +{ + /** + * @var AbstractPart + */ + private $part; + + protected function setUp(): void + { + $this->part = $this->getMockForAbstractClass(AbstractPart::class); + } + + public function testParentWriter(): void + { + $writer = new EPub3(); + $this->part->setParentWriter($writer); + + self::assertInstanceOf(EPub3::class, $this->part->getParentWriter()); + } +} diff --git a/tests/PhpWordTests/Writer/EPub3/Part/ContentTest.php b/tests/PhpWordTests/Writer/EPub3/Part/ContentTest.php new file mode 100644 index 0000000000..6745ea2eda --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3/Part/ContentTest.php @@ -0,0 +1,38 @@ +<?php + +namespace PhpOffice\PhpWordTests\Writer\EPub3\Part; + +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Writer\EPub3; +use PhpOffice\PhpWord\Writer\EPub3\Part\Content; +use PHPUnit\Framework\TestCase; + +class ContentTest extends TestCase +{ + /** + * @var Content + */ + private $content; + + protected function setUp(): void + { + $phpWord = new PhpWord(); + $this->content = new Content($phpWord); + $section = $phpWord->addSection(); + $section->addText('Test content'); + + $writer = new EPub3($phpWord); + $this->content->setParentWriter($writer); + } + + public function testWrite(): void + { + $result = $this->content->write(); + + self::assertIsString($result); + self::assertStringContainsString('<?xml version="1.0" encoding="UTF-8"?>', $result); + self::assertStringContainsString('<package', $result); + self::assertStringContainsString('<manifest>', $result); + self::assertStringContainsString('<spine>', $result); + } +} diff --git a/tests/PhpWordTests/Writer/EPub3/Part/ManifestTest.php b/tests/PhpWordTests/Writer/EPub3/Part/ManifestTest.php new file mode 100644 index 0000000000..d1755da9af --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3/Part/ManifestTest.php @@ -0,0 +1,35 @@ +<?php + +namespace PhpOffice\PhpWordTests\Writer\EPub3\Part; + +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Writer\EPub3; +use PhpOffice\PhpWord\Writer\EPub3\Part\Manifest; +use PHPUnit\Framework\TestCase; + +class ManifestTest extends TestCase +{ + /** + * @var Manifest + */ + private $manifest; + + protected function setUp(): void + { + $this->manifest = new Manifest(); + $phpWord = new PhpWord(); + $writer = new EPub3($phpWord); + $this->manifest->setParentWriter($writer); + } + + public function testWrite(): void + { + $result = $this->manifest->write(); + + self::assertStringContainsString('<?xml version="1.0" encoding="UTF-8"?>', $result); + self::assertIsString($result); + self::assertStringContainsString('<container version="1.0"', $result); + self::assertStringContainsString('<rootfiles>', $result); + self::assertStringContainsString('<rootfile full-path="content.opf"', $result); + } +} diff --git a/tests/PhpWordTests/Writer/EPub3/Part/MetaTest.php b/tests/PhpWordTests/Writer/EPub3/Part/MetaTest.php new file mode 100644 index 0000000000..3e1275a7c0 --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3/Part/MetaTest.php @@ -0,0 +1,53 @@ +<?php + +namespace PhpOffice\PhpWordTests\Writer\EPub3\Part; + +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Writer\EPub3; +use PhpOffice\PhpWord\Writer\EPub3\Part\Meta; +use PHPUnit\Framework\TestCase; + +class MetaTest extends TestCase +{ + /** + * @var Meta + */ + private $meta; + + protected function setUp(): void + { + $this->meta = new Meta(); + $phpWord = new PhpWord(); + $writer = new EPub3($phpWord); + $this->meta->setParentWriter($writer); + } + + public function testWrite(): void + { + $result = $this->meta->write(); + + self::assertIsString($result); + self::assertStringContainsString('<?xml version="1.0" encoding="UTF-8"?>', $result); + self::assertStringContainsString('<metadata', $result); + self::assertStringContainsString('xmlns:dc="http://purl.org/dc/elements/1.1/"', $result); + } + + public function testWriteWithDocInfo(): void + { + $phpWord = new PhpWord(); + $properties = $phpWord->getDocInfo(); + $properties->setCreator('PHPWord'); + $properties->setTitle('Test Title'); + $properties->setKeywords('test, keywords'); + + $writer = new EPub3($phpWord); + $this->meta->setParentWriter($writer); + + $expected = '<?xml version="1.0" encoding="UTF-8"?>\n<metadata xmlns="http://www.idpf.org/2007/opf" xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:title>Test Title</dc:title><dc:language>en</dc:language><dc:identifier>urn:uuid:12345</dc:identifier><dc:creator>PHPWord</dc:creator><meta property="dcterms:modified">2023-01-01T00:00:00Z</meta></metadata>'; + + $result = $this->meta->write(); + + self::assertStringContainsString('<dc:creator>PHPWord</dc:creator>', $result); + self::assertStringContainsString('<dc:title>Test Title</dc:title>', $result); + } +} diff --git a/tests/PhpWordTests/Writer/EPub3/Part/MimetypeTest.php b/tests/PhpWordTests/Writer/EPub3/Part/MimetypeTest.php new file mode 100644 index 0000000000..c1cd57f705 --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3/Part/MimetypeTest.php @@ -0,0 +1,32 @@ +<?php + +namespace PhpOffice\PhpWordTests\Writer\EPub3\Part; + +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Writer\EPub3; +use PhpOffice\PhpWord\Writer\EPub3\Part\Mimetype; +use PHPUnit\Framework\TestCase; + +class MimetypeTest extends TestCase +{ + /** + * @var Mimetype + */ + private $mimetype; + + protected function setUp(): void + { + $this->mimetype = new Mimetype(); + $phpWord = new PhpWord(); + $writer = new EPub3($phpWord); + $this->mimetype->setParentWriter($writer); + } + + public function testWrite(): void + { + $result = $this->mimetype->write(); + + self::assertIsString($result); + self::assertEquals('application/epub+zip', $result); + } +} diff --git a/tests/PhpWordTests/Writer/EPub3/Part/NavTest.php b/tests/PhpWordTests/Writer/EPub3/Part/NavTest.php new file mode 100644 index 0000000000..a050f95511 --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3/Part/NavTest.php @@ -0,0 +1,49 @@ +<?php + +namespace PhpOffice\PhpWordTests\Writer\EPub3\Part; + +use DOMDocument; +use PhpOffice\PhpWord\Writer\EPub3\Part\Nav; +use PHPUnit\Framework\TestCase; + +/** + * Test class for PhpOffice\PhpWord\Writer\EPub3\Part\Nav. + */ +class NavTest extends TestCase +{ + public function testWrite(): void + { + $nav = new Nav(); + $xml = $nav->write(); + + // Test that valid XML is generated + $dom = new DOMDocument(); + $dom->loadXML($xml); + + // Test required XML elements and attributes exist + self::assertEquals('html', $dom->documentElement->nodeName); + self::assertEquals('http://www.w3.org/1999/xhtml', $dom->documentElement->getAttribute('xmlns')); + self::assertEquals('http://www.idpf.org/2007/ops', $dom->documentElement->getAttribute('xmlns:epub')); + + // Test nav element + $navElements = $dom->getElementsByTagName('nav'); + self::assertEquals(1, $navElements->length); + $navElement = $navElements->item(0); + self::assertEquals('toc', $navElement->getAttribute('epub:type')); + self::assertEquals('toc', $navElement->getAttribute('id')); + + // Test title exists + $titleElements = $dom->getElementsByTagName('title'); + self::assertEquals(1, $titleElements->length); + self::assertEquals('Navigation', $titleElements->item(0)->nodeValue); + + // Test TOC header exists + $h1Elements = $dom->getElementsByTagName('h1'); + self::assertEquals(1, $h1Elements->length); + self::assertEquals('Table of Contents', $h1Elements->item(0)->nodeValue); + + // Test TOC list structure exists + $olElements = $dom->getElementsByTagName('ol'); + self::assertEquals(1, $olElements->length); + } +} diff --git a/tests/PhpWordTests/Writer/EPub3/PartTest.php b/tests/PhpWordTests/Writer/EPub3/PartTest.php new file mode 100644 index 0000000000..ed91c60bcb --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3/PartTest.php @@ -0,0 +1,28 @@ +<?php + +namespace PhpOffice\PhpWordTests\Writer\EPub3; + +use PhpOffice\PhpWord\Writer\EPub3\Part; +use PHPUnit\Framework\TestCase; + +class PartTest extends TestCase +{ + public function testGetPartClass(): void + { + $types = ['Content', 'Manifest', 'Meta', 'Mimetype']; + + foreach ($types as $type) { + $class = Part::getPartClass($type); + $expectedClass = 'PhpOffice\\PhpWord\\Writer\\EPub3\\Part\\' . $type; + + self::assertEquals($expectedClass, $class); + } + } + + public function testGetPartClassWithInvalidType(): void + { + $this->expectException(\PhpOffice\PhpWord\Exception\Exception::class); + + Part::getPartClass('InvalidType'); + } +} diff --git a/tests/PhpWordTests/Writer/EPub3/Style/AbstractStyleTest.php b/tests/PhpWordTests/Writer/EPub3/Style/AbstractStyleTest.php new file mode 100644 index 0000000000..fb9135f0cd --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3/Style/AbstractStyleTest.php @@ -0,0 +1,24 @@ +<?php + +namespace PhpOffice\PhpWordTests\Writer\EPub3\Style; + +use PhpOffice\PhpWord\Writer\EPub3; +use PhpOffice\PhpWord\Writer\EPub3\Style\AbstractStyle; +use PHPUnit\Framework\TestCase; + +class AbstractStyleTest extends TestCase +{ + /** + * Test setParentWriter and getParentWriter methods. + */ + public function testParentWriter(): void + { + $parentWriter = new EPub3(); + $style = $this->getMockForAbstractClass(AbstractStyle::class); + + $result = $style->setParentWriter($parentWriter); + + self::assertSame($style, $result); + self::assertSame($parentWriter, $style->getParentWriter()); + } +} diff --git a/tests/PhpWordTests/Writer/EPub3/Style/FontTest.php b/tests/PhpWordTests/Writer/EPub3/Style/FontTest.php new file mode 100644 index 0000000000..26572af3a4 --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3/Style/FontTest.php @@ -0,0 +1,25 @@ +<?php + +namespace PhpOffice\PhpWordTests\Writer\EPub3\Style; + +use PhpOffice\PhpWord\Writer\EPub3\Style\Font; +use PHPUnit\Framework\TestCase; + +class FontTest extends TestCase +{ + /** + * Test write method. + */ + public function testWrite(): void + { + $style = new Font(); + + $content = $style->write(); + + self::assertStringContainsString('font-family: "Times New Roman", Times, serif;', $content); + self::assertStringContainsString('font-size: 12pt;', $content); + self::assertStringContainsString('color: #000000;', $content); + self::assertStringStartsWith('body {', $content); + self::assertStringEndsWith('}', $content); + } +} diff --git a/tests/PhpWordTests/Writer/EPub3/Style/ParagraphTest.php b/tests/PhpWordTests/Writer/EPub3/Style/ParagraphTest.php new file mode 100644 index 0000000000..bcaab0bab1 --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3/Style/ParagraphTest.php @@ -0,0 +1,25 @@ +<?php + +namespace PhpOffice\PhpWordTests\Writer\EPub3\Style; + +use PhpOffice\PhpWord\Writer\EPub3\Style\Paragraph; +use PHPUnit\Framework\TestCase; + +class ParagraphTest extends TestCase +{ + /** + * Test write method. + */ + public function testWrite(): void + { + $style = new Paragraph(); + + $content = $style->write(); + + self::assertStringContainsString('margin-top: 0;', $content); + self::assertStringContainsString('margin-bottom: 1em;', $content); + self::assertStringContainsString('text-align: left;', $content); + self::assertStringStartsWith('p {', $content); + self::assertStringEndsWith('}', $content); + } +} diff --git a/tests/PhpWordTests/Writer/EPub3/Style/TableTest.php b/tests/PhpWordTests/Writer/EPub3/Style/TableTest.php new file mode 100644 index 0000000000..1d6ff0d6bb --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3/Style/TableTest.php @@ -0,0 +1,28 @@ +<?php + +namespace PhpOffice\PhpWordTests\Writer\EPub3\Style; + +use PhpOffice\PhpWord\Writer\EPub3\Style\Table; +use PHPUnit\Framework\TestCase; + +class TableTest extends TestCase +{ + /** + * Test write method. + */ + public function testWrite(): void + { + $style = new Table(); + + $content = $style->write(); + + self::assertStringContainsString('border-collapse: collapse;', $content); + self::assertStringContainsString('width: 100%;', $content); + self::assertStringContainsString('border: 1px solid black;', $content); + self::assertStringContainsString('padding: 8px;', $content); + self::assertStringContainsString('text-align: left;', $content); + self::assertStringContainsString('table {', $content); + self::assertStringContainsString('th, td {', $content); + self::assertStringEndsWith('}', $content); + } +} diff --git a/tests/PhpWordTests/Writer/EPub3/StyleTest.php b/tests/PhpWordTests/Writer/EPub3/StyleTest.php new file mode 100644 index 0000000000..15db0d581d --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3/StyleTest.php @@ -0,0 +1,23 @@ +<?php + +namespace PhpOffice\PhpWordTests\Writer\EPub3; + +use PhpOffice\PhpWord\Shared\XMLWriter; +use PHPUnit\Framework\TestCase; + +class StyleTest extends TestCase +{ + public function testEmptyStyles(): void + { + $styles = ['Font', 'Paragraph', 'Table']; + foreach ($styles as $style) { + $objectClass = 'PhpOffice\\PhpWord\\Writer\\EPub3\\Style\\' . $style; + $xmlWriter = new XMLWriter(); + $object = new $objectClass(); + $object->setXmlWriter($xmlWriter); + $object->write(); + + self::assertEquals('', $xmlWriter->getData()); + } + } +} diff --git a/tests/PhpWordTests/Writer/EPub3Test.php b/tests/PhpWordTests/Writer/EPub3Test.php new file mode 100644 index 0000000000..acdbb5e32f --- /dev/null +++ b/tests/PhpWordTests/Writer/EPub3Test.php @@ -0,0 +1,126 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWordTests\Writer; + +use PhpOffice\PhpWord\Exception\Exception; +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\SimpleType\Jc; +use PhpOffice\PhpWord\Writer\EPub3; + +/** + * Test class for PhpOffice\PhpWord\Writer\Epub3. + * + * @runTestsInSeparateProcesses + */ +class EPub3Test extends \PHPUnit\Framework\TestCase +{ + /** + * Test document construction. + */ + public function testConstruct(): void + { + $object = new EPub3(new PhpWord()); + self::assertInstanceOf(PhpWord::class, $object->getPhpWord()); + self::assertEquals('./', $object->getDiskCachingDirectory()); + foreach (['Content', 'Manifest', 'Mimetype'] as $part) { + self::assertInstanceOf( + "PhpOffice\\PhpWord\\Writer\\Epub3\\Part\\{$part}", + $object->getWriterPart($part) + ); + self::assertInstanceOf( + 'PhpOffice\\PhpWord\\Writer\\Epub3', + $object->getWriterPart($part)->getParentWriter() + ); + } + } + + /** + * Test construction with null. + */ + public function testConstructWithNull(): void + { + $this->expectException(Exception::class); + $this->expectExceptionMessage('No PhpWord assigned.'); + + $writer = new EPub3(); + $writer->getWriterPart('content')->write(); + } + + /** + * Test saving document. + */ + public function testSave(): void + { + $imageSrc = __DIR__ . '/../_files/images/PhpWord.png'; + $file = __DIR__ . '/../_files/temp.epub'; + + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $section->addText('Test 1'); + $section->addTextBreak(); + $section->addText('Test 2', null, ['alignment' => Jc::CENTER]); + $section->addLink('https://github.com/PHPOffice/PHPWord'); + $section->addTitle('Test', 1); + $section->addPageBreak(); + $section->addImage($imageSrc); + $writer = new EPub3($phpWord); + $writer->save($file); + self::assertFileExists($file); + unlink($file); + } + + /** + * Test PHP output. + */ + public function testSavePhpOutput(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $section->addText('Test'); + $writer = new EPub3($phpWord); + ob_start(); + $writer->save('php://output'); + $contents = ob_get_contents(); + self::assertTrue(ob_end_clean()); + self::assertNotEmpty($contents); + } + + /** + * Test disk caching. + */ + public function testSetGetUseDiskCaching(): void + { + $object = new EPub3(); + $object->setUseDiskCaching(true, PHPWORD_TESTS_BASE_DIR); + self::assertTrue($object->isUseDiskCaching()); + self::assertEquals(PHPWORD_TESTS_BASE_DIR, $object->getDiskCachingDirectory()); + } + + /** + * Test disk caching exception. + */ + public function testSetUseDiskCachingException(): void + { + $this->expectException(Exception::class); + $dir = implode(DIRECTORY_SEPARATOR, [PHPWORD_TESTS_BASE_DIR, 'foo']); + + $object = new EPub3(); + $object->setUseDiskCaching(true, $dir); + } +} From 2f270f294fc476c2f723533e9fe71cb6863c4b1b Mon Sep 17 00:00:00 2001 From: Progi1984 <progi1984@gmail.com> Date: Mon, 3 Feb 2025 08:15:35 +0100 Subject: [PATCH 234/246] Reader HTML: Support font styles for h1/h6 (#2737) --- docs/changes/1.x/1.4.0.md | 1 + src/PhpWord/Shared/Html.php | 33 +++++++++---------- src/PhpWord/Style/Font.php | 6 ++-- tests/PhpWordTests/Shared/HtmlTest.php | 45 ++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 22 deletions(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 96b86a1bac..0f225edd64 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -15,6 +15,7 @@ - Writer HTML: Support Default font color by [@MichaelPFrey](https://github.com/MichaelPFrey) in [#2731](https://github.com/PHPOffice/PHPWord/pull/2731) - Writer ODText: Support Default font color by [@MichaelPFrey](https://github.com/MichaelPFrey) in [#2735](https://github.com/PHPOffice/PHPWord/pull/2735) - Add basic ruby text (phonetic guide) support for Word2007 and HTML Reader/Writer, RTF Writer, basic support for ODT writing by [@Deadpikle](https://github.com/Deadpikle) in [#2727](https://github.com/PHPOffice/PHPWord/pull/2727) +- Reader HTML: Support font styles for h1/h6 by [@Progi1984](https://github.com/Progi1984) fixing [#2619](https://github.com/PHPOffice/PHPWord/issues/2619) in [#2737](https://github.com/PHPOffice/PHPWord/pull/2737) - Added Support for Writer Epub3 by [@Sambit003](https://github.com/Sambit003) in [#2724](https://github.com/PHPOffice/PHPWord/pull/2724) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index cdaf8d8c87..170dc5dff3 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -211,16 +211,16 @@ protected static function parseNode($node, $element, $styles = [], $data = []): // Node mapping table $nodes = [ - // $method $node $element $styles $data $argument1 $argument2 - 'p' => ['Paragraph', $node, $element, $styles, null, null, null], - 'h1' => ['Heading', null, $element, $styles, null, 'Heading1', null], - 'h2' => ['Heading', null, $element, $styles, null, 'Heading2', null], - 'h3' => ['Heading', null, $element, $styles, null, 'Heading3', null], - 'h4' => ['Heading', null, $element, $styles, null, 'Heading4', null], - 'h5' => ['Heading', null, $element, $styles, null, 'Heading5', null], - 'h6' => ['Heading', null, $element, $styles, null, 'Heading6', null], - '#text' => ['Text', $node, $element, $styles, null, null, null], - 'strong' => ['Property', null, null, $styles, null, 'bold', true], + // $method $node $element $styles $data $argument1 $argument2 + 'p' => ['Paragraph', $node, $element, $styles, null, null, null], + 'h1' => ['Heading', $node, $element, $styles, null, 'Heading1', null], + 'h2' => ['Heading', $node, $element, $styles, null, 'Heading2', null], + 'h3' => ['Heading', $node, $element, $styles, null, 'Heading3', null], + 'h4' => ['Heading', $node, $element, $styles, null, 'Heading4', null], + 'h5' => ['Heading', $node, $element, $styles, null, 'Heading5', null], + 'h6' => ['Heading', $node, $element, $styles, null, 'Heading6', null], + '#text' => ['Text', $node, $element, $styles, null, null, null], + 'strong' => ['Property', null, null, $styles, null, 'bold', true], 'b' => ['Property', null, null, $styles, null, 'bold', true], 'em' => ['Property', null, null, $styles, null, 'italic', true], 'i' => ['Property', null, null, $styles, null, 'italic', true], @@ -345,21 +345,18 @@ protected static function parseInput($node, $element, &$styles): void /** * Parse heading node. * - * @param AbstractContainer $element - * @param array &$styles * @param string $argument1 Name of heading style * - * @return TextRun - * * @todo Think of a clever way of defining header styles, now it is only based on the assumption, that * Heading1 - Heading6 are already defined somewhere */ - protected static function parseHeading($element, &$styles, $argument1) + protected static function parseHeading(DOMNode $node, AbstractContainer $element, array &$styles, string $argument1): TextRun { - $styles['paragraph'] = $argument1; - $newElement = $element->addTextRun($styles['paragraph']); + $style = new Paragraph(); + $style->setStyleName($argument1); + $style->setStyleByArray(self::parseInlineStyle($node, $styles['paragraph'])); - return $newElement; + return $element->addTextRun($style); } /** diff --git a/src/PhpWord/Style/Font.php b/src/PhpWord/Style/Font.php index fe7f621454..f03e8899d1 100644 --- a/src/PhpWord/Style/Font.php +++ b/src/PhpWord/Style/Font.php @@ -109,7 +109,7 @@ class Font extends AbstractStyle /** * Font color. * - * @var string + * @var null|string */ private $color; @@ -426,10 +426,8 @@ public function setSize($value = null) /** * Get font color. - * - * @return string */ - public function getColor() + public function getColor(): ?string { return $this->color; } diff --git a/tests/PhpWordTests/Shared/HtmlTest.php b/tests/PhpWordTests/Shared/HtmlTest.php index 117f5cb01d..42d8aa598b 100644 --- a/tests/PhpWordTests/Shared/HtmlTest.php +++ b/tests/PhpWordTests/Shared/HtmlTest.php @@ -22,12 +22,15 @@ use PhpOffice\PhpWord\ComplexType\RubyProperties; use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\Element\Table; +use PhpOffice\PhpWord\Element\Text; +use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Shared\Converter; use PhpOffice\PhpWord\Shared\Html; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\SimpleType\LineSpacingRule; use PhpOffice\PhpWord\SimpleType\TblWidth; +use PhpOffice\PhpWord\Style\Font; use PhpOffice\PhpWord\Style\Paragraph; use PhpOffice\PhpWordTests\AbstractWebServerEmbedded; use PhpOffice\PhpWordTests\TestHelperDOCX; @@ -105,6 +108,48 @@ public function testParseFullHtml(): void self::assertCount(2, $section->getElements()); } + public function testParseHeader(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + Html::addHtml($section, '<h1>Text</h1>'); + + self::assertCount(1, $section->getElements()); + $element = $section->getElement(0); + self::assertInstanceOf(TextRun::class, $element); + self::assertInstanceOf(Paragraph::class, $element->getParagraphStyle()); + self::assertEquals('Heading1', $element->getParagraphStyle()->getStyleName()); + self::assertEquals('', $element->getParagraphStyle()->getAlignment()); + self::assertEquals('Text', $element->getText()); + self::assertCount(1, $element->getElements()); + $subElement = $element->getElement(0); + self::assertInstanceOf(Text::class, $subElement); + self::assertInstanceOf(Font::class, $subElement->getFontStyle()); + self::assertNull($subElement->getFontStyle()->getColor()); + self::assertEquals('Text', $subElement->getText()); + } + + public function testParseHeaderStyle(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + Html::addHtml($section, '<h1 style="color: #ff0000; text-align:center">Text</h1>'); + + self::assertCount(1, $section->getElements()); + $element = $section->getElement(0); + self::assertInstanceOf(TextRun::class, $element); + self::assertInstanceOf(Paragraph::class, $element->getParagraphStyle()); + self::assertEquals('Heading1', $element->getParagraphStyle()->getStyleName()); + self::assertEquals('center', $element->getParagraphStyle()->getAlignment()); + self::assertEquals('Text', $element->getText()); + self::assertCount(1, $element->getElements()); + $subElement = $element->getElement(0); + self::assertInstanceOf(Text::class, $subElement); + self::assertInstanceOf(Font::class, $subElement->getFontStyle()); + self::assertEquals('ff0000', $subElement->getFontStyle()->getColor()); + self::assertEquals('Text', $subElement->getText()); + } + /** * Test HTML entities. */ From 1be7a807f2a89c48ddac833e2de01dc29d6c0afb Mon Sep 17 00:00:00 2001 From: Progi1984 <progi1984@gmail.com> Date: Mon, 3 Feb 2025 09:13:23 +0100 Subject: [PATCH 235/246] Writer HTML: Fixed null string for Text Elements (#2738) Co-authored-by: armagedon007 <000yurik000@gmail.com> --- docs/changes/1.x/1.4.0.md | 4 +- src/PhpWord/Element/Link.php | 4 +- src/PhpWord/Element/Text.php | 4 +- src/PhpWord/Writer/HTML/Element/Text.php | 2 +- .../Writer/HTML/Element/TextTest.php | 43 +++++++++++++++++++ 5 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 tests/PhpWordTests/Writer/HTML/Element/TextTest.php diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 0f225edd64..2afadebd5f 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -16,8 +16,7 @@ - Writer ODText: Support Default font color by [@MichaelPFrey](https://github.com/MichaelPFrey) in [#2735](https://github.com/PHPOffice/PHPWord/pull/2735) - Add basic ruby text (phonetic guide) support for Word2007 and HTML Reader/Writer, RTF Writer, basic support for ODT writing by [@Deadpikle](https://github.com/Deadpikle) in [#2727](https://github.com/PHPOffice/PHPWord/pull/2727) - Reader HTML: Support font styles for h1/h6 by [@Progi1984](https://github.com/Progi1984) fixing [#2619](https://github.com/PHPOffice/PHPWord/issues/2619) in [#2737](https://github.com/PHPOffice/PHPWord/pull/2737) - -- Added Support for Writer Epub3 by [@Sambit003](https://github.com/Sambit003) in [#2724](https://github.com/PHPOffice/PHPWord/pull/2724) +- Writer EPub3: Basic support by [@Sambit003](https://github.com/Sambit003) fixing [#55](https://github.com/PHPOffice/PHPWord/issues/55) in [#2724](https://github.com/PHPOffice/PHPWord/pull/2724) ### Bug fixes @@ -27,6 +26,7 @@ - Reader Word2007: Respect paragraph indent units by [@tugmaks](https://github.com/tugmaks) & [@Progi1984](https://github.com/Progi1984) fixing [#507](https://github.com/PHPOffice/PHPWord/issues/507) in [#2726](https://github.com/PHPOffice/PHPWord/pull/2726) - Reader Word2007: Support Header elements within Title elements by [@SpraxDev](https://github.com/SpraxDev) fixing [#2616](https://github.com/PHPOffice/PHPWord/issues/2616), [#2426](https://github.com/PHPOffice/PHPWord/issues/2426) in [#2674](https://github.com/PHPOffice/PHPWord/pull/2674) - Reader HTML: Support for inherit value for property line-height by [@Progi1984](https://github.com/Progi1984) fixing [#2683](https://github.com/PHPOffice/PHPWord/issues/2683) in [#2733](https://github.com/PHPOffice/PHPWord/pull/2733) +- Writer HTML: Fixed null string for Text Elements by [@armagedon007](https://github.com/armagedon007) and [@Progi1984](https://github.com/Progi1984) in [#2738](https://github.com/PHPOffice/PHPWord/pull/2738) ### Miscellaneous diff --git a/src/PhpWord/Element/Link.php b/src/PhpWord/Element/Link.php index 755fd7ba0f..a0deb0a5ec 100644 --- a/src/PhpWord/Element/Link.php +++ b/src/PhpWord/Element/Link.php @@ -99,10 +99,8 @@ public function getSource() /** * Get link text. - * - * @return string */ - public function getText() + public function getText(): string { return $this->text; } diff --git a/src/PhpWord/Element/Text.php b/src/PhpWord/Element/Text.php index ea5f5f87a4..f20b273e02 100644 --- a/src/PhpWord/Element/Text.php +++ b/src/PhpWord/Element/Text.php @@ -147,10 +147,8 @@ public function setText($text) /** * Get Text content. - * - * @return ?string */ - public function getText() + public function getText(): ?string { return $this->text; } diff --git a/src/PhpWord/Writer/HTML/Element/Text.php b/src/PhpWord/Writer/HTML/Element/Text.php index 312d3a19c2..7be95a5c76 100644 --- a/src/PhpWord/Writer/HTML/Element/Text.php +++ b/src/PhpWord/Writer/HTML/Element/Text.php @@ -73,7 +73,7 @@ public function write() /** @var \PhpOffice\PhpWord\Element\Text $element Type hint */ $element = $this->element; - $text = $this->parentWriter->escapeHTML($element->getText()); + $text = $this->parentWriter->escapeHTML($element->getText() ?? ''); if (!$this->withoutP && !trim($text)) { $text = ' '; } diff --git a/tests/PhpWordTests/Writer/HTML/Element/TextTest.php b/tests/PhpWordTests/Writer/HTML/Element/TextTest.php new file mode 100644 index 0000000000..2dfdd53be3 --- /dev/null +++ b/tests/PhpWordTests/Writer/HTML/Element/TextTest.php @@ -0,0 +1,43 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWordTests\Writer\HTML\Element; + +use PhpOffice\PhpWord\Element\Text as BaseText; +use PhpOffice\PhpWord\Writer\HTML; +use PhpOffice\PhpWord\Writer\HTML\Element\Text; +use PHPUnit\Framework\TestCase; + +class TextTest extends TestCase +{ + public function testHTMLNullString(): void + { + $writer = new HTML(); + $object = new Text($writer, new BaseText()); + + self::assertEquals('<p> </p>' . PHP_EOL, $object->write()); + } + + public function testHTMLEmptyString(): void + { + $writer = new HTML(); + $object = new Text($writer, new BaseText('')); + + self::assertEquals('<p> </p>' . PHP_EOL, $object->write()); + } +} From 66f0a2cfbf3eb59452517de94744543e3a1c2a45 Mon Sep 17 00:00:00 2001 From: Progi1984 <progi1984@gmail.com> Date: Wed, 12 Feb 2025 13:00:02 +0100 Subject: [PATCH 236/246] Template Processor: Fix 0 considered as empty string (#2748) * Fix `0` considered as empty string * Update changelog * Updated changelog & Added unit test --------- Co-authored-by: Florian CAVASIN <cavasinf.info@gmail.com> --- docs/changes/1.x/1.4.0.md | 1 + src/PhpWord/TemplateProcessor.php | 2 +- tests/PhpWordTests/TemplateProcessorTest.php | 97 ++++++++++++++++++++ 3 files changed, 99 insertions(+), 1 deletion(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 2afadebd5f..b5102f25fa 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -27,6 +27,7 @@ - Reader Word2007: Support Header elements within Title elements by [@SpraxDev](https://github.com/SpraxDev) fixing [#2616](https://github.com/PHPOffice/PHPWord/issues/2616), [#2426](https://github.com/PHPOffice/PHPWord/issues/2426) in [#2674](https://github.com/PHPOffice/PHPWord/pull/2674) - Reader HTML: Support for inherit value for property line-height by [@Progi1984](https://github.com/Progi1984) fixing [#2683](https://github.com/PHPOffice/PHPWord/issues/2683) in [#2733](https://github.com/PHPOffice/PHPWord/pull/2733) - Writer HTML: Fixed null string for Text Elements by [@armagedon007](https://github.com/armagedon007) and [@Progi1984](https://github.com/Progi1984) in [#2738](https://github.com/PHPOffice/PHPWord/pull/2738) +- Template Processor: Fix 0 considered as empty string by [@cavasinf](https://github.com/cavasinf), [@SnipsMine](https://github.com/SnipsMine) and [@Progi1984](https://github.com/Progi1984) fixing [#2572](https://github.com/PHPOffice/PHPWord/issues/2572), [#2703](https://github.com/PHPOffice/PHPWord/issues/2703) in [#2748](https://github.com/PHPOffice/PHPWord/pull/2748) ### Miscellaneous diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 643bae4cb6..360cce74b6 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -269,7 +269,7 @@ protected static function ensureMacroCompleted($macro) */ protected static function ensureUtf8Encoded($subject) { - return $subject ? Text::toUTF8($subject) : ''; + return (null !== $subject) ? Text::toUTF8($subject) : ''; } /** diff --git a/tests/PhpWordTests/TemplateProcessorTest.php b/tests/PhpWordTests/TemplateProcessorTest.php index 9ba6933e74..d031eb75c1 100644 --- a/tests/PhpWordTests/TemplateProcessorTest.php +++ b/tests/PhpWordTests/TemplateProcessorTest.php @@ -1641,4 +1641,101 @@ public function testShouldMakeFieldsUpdateOnOpenWithCustomMacro(): void $templateProcessor->setUpdateFields(false); self::assertStringContainsString('<w:updateFields w:val="false"/>', $templateProcessor->getSettingsPart()); } + + public function testEnsureUtf8Encoded(): void + { + $mainPart = '<w:tbl> + <w:tr> + <w:tc> + <w:tcPr> + <w:vMerge w:val="restart"/> + </w:tcPr> + <w:p> + <w:r> + <w:t t=1>${stringZero}</w:t> + </w:r> + </w:p> + </w:tc> + <w:tc> + <w:p> + <w:r> + <w:t t=2>${intZero}</w:t> + </w:r> + </w:p> + </w:tc> + <w:tc> + <w:p> + <w:r> + <w:t t=3>${stringTest}</w:t> + </w:r> + </w:p> + </w:tc> + <w:tc> + <w:p> + <w:r> + <w:t t=4>${null}</w:t> + </w:r> + </w:p> + </w:tc> + <w:tc> + <w:p> + <w:r> + <w:t t=5>${floatZero}</w:t> + </w:r> + </w:p> + </w:tc> + <w:tc> + <w:p> + <w:r> + <w:t t=6>${intTen}</w:t> + </w:r> + </w:p> + </w:tc> + <w:tc> + <w:p> + <w:r> + <w:t t=7>${boolFalse}</w:t> + </w:r> + </w:p> + </w:tc> + <w:tc> + <w:p> + <w:r> + <w:t t=8>${boolTrue}</w:t> + </w:r> + </w:p> + </w:tc> + </w:tr> + </w:tbl>'; + $templateProcessor = new TestableTemplateProcesor($mainPart); + + self::assertEquals( + ['stringZero', 'intZero', 'stringTest', 'null', 'floatZero', 'intTen', 'boolFalse', 'boolTrue'], + $templateProcessor->getVariables() + ); + + $templateProcessor->setValue('stringZero', '0'); + self::assertStringContainsString('<w:t t=1>0</w:t>', $templateProcessor->getMainPart()); + + $templateProcessor->setValue('intZero', 0); + self::assertStringContainsString('<w:t t=2>0</w:t>', $templateProcessor->getMainPart()); + + $templateProcessor->setValue('stringTest', 'test'); + self::assertStringContainsString('<w:t t=3>test</w:t>', $templateProcessor->getMainPart()); + + $templateProcessor->setValue('null', null); + self::assertStringContainsString('<w:t t=4></w:t>', $templateProcessor->getMainPart()); + + $templateProcessor->setValue('floatZero', 0.00); + self::assertStringContainsString('<w:t t=5>0</w:t>', $templateProcessor->getMainPart()); + + $templateProcessor->setValue('intTen', 10); + self::assertStringContainsString('<w:t t=6>10</w:t>', $templateProcessor->getMainPart()); + + $templateProcessor->setValue('boolFalse', false); + self::assertStringContainsString('<w:t t=7></w:t>', $templateProcessor->getMainPart()); + + $templateProcessor->setValue('boolTrue', true); + self::assertStringContainsString('<w:t t=8>1</w:t>', $templateProcessor->getMainPart()); + } } From 2a524e2445e27b293c9b3e0f3945f312cedac3a1 Mon Sep 17 00:00:00 2001 From: Kacper <30697294+Chudy20007@users.noreply.github.com> Date: Wed, 12 Feb 2025 21:36:01 +0100 Subject: [PATCH 237/246] Background and border color transparency support for textboxes when color is undefined (#2555) --- docs/changes/1.x/1.4.0.md | 3 +- .../Writer/Word2007/Element/TextBox.php | 7 ++ .../Writer/Word2007/Element/TextBoxTest.php | 84 +++++++++++++++++++ 3 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 tests/PhpWordTests/Writer/Word2007/Element/TextBoxTest.php diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index b5102f25fa..634d1d6f31 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -17,7 +17,8 @@ - Add basic ruby text (phonetic guide) support for Word2007 and HTML Reader/Writer, RTF Writer, basic support for ODT writing by [@Deadpikle](https://github.com/Deadpikle) in [#2727](https://github.com/PHPOffice/PHPWord/pull/2727) - Reader HTML: Support font styles for h1/h6 by [@Progi1984](https://github.com/Progi1984) fixing [#2619](https://github.com/PHPOffice/PHPWord/issues/2619) in [#2737](https://github.com/PHPOffice/PHPWord/pull/2737) - Writer EPub3: Basic support by [@Sambit003](https://github.com/Sambit003) fixing [#55](https://github.com/PHPOffice/PHPWord/issues/55) in [#2724](https://github.com/PHPOffice/PHPWord/pull/2724) - +- Writer2007: Added support for background and border color transparency in Text Box element [@chudy20007](https://github.com/Chudy20007) in [#2555](https://github.com/PHPOffice/PHPWord/pull/2555) + ### Bug fixes - Writer ODText: Support for images inside a textRun by [@Progi1984](https://github.com/Progi1984) fixing [#2240](https://github.com/PHPOffice/PHPWord/issues/2240) in [#2668](https://github.com/PHPOffice/PHPWord/pull/2668) diff --git a/src/PhpWord/Writer/Word2007/Element/TextBox.php b/src/PhpWord/Writer/Word2007/Element/TextBox.php index e005480802..79011d8d6f 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Element/TextBox.php @@ -51,6 +51,13 @@ public function write(): void if ($style->getBgColor()) { $xmlWriter->writeAttribute('fillcolor', $style->getBgColor()); + } else { + $xmlWriter->writeAttribute('filled', 'f'); + } + + if (!$style->getBorderColor()) { + $xmlWriter->writeAttribute('stroked', 'f'); + $xmlWriter->writeAttribute('strokecolor', 'white'); } $styleWriter->write(); diff --git a/tests/PhpWordTests/Writer/Word2007/Element/TextBoxTest.php b/tests/PhpWordTests/Writer/Word2007/Element/TextBoxTest.php new file mode 100644 index 0000000000..6d4df65298 --- /dev/null +++ b/tests/PhpWordTests/Writer/Word2007/Element/TextBoxTest.php @@ -0,0 +1,84 @@ +<?php + +declare(strict_types=1); + +namespace PhpOffice\PhpWordTests\Writer\Word2007\Element; + +use PhpOffice\PhpWord\Element\TextBox as TextBoxElement; +use PhpOffice\PhpWord\Shared\XMLWriter; +use PhpOffice\PhpWord\Style\TextBox as TextBoxStyle; +use PhpOffice\PhpWord\Writer\Word2007\Element\TextBox; +use PHPUnit\Framework\TestCase; + +class TextBoxTest extends TestCase +{ + /** + * @dataProvider textBoxColorProvider + */ + public function testTextBoxGeneratesCorrectXml( + ?string $bgColor, + ?string $borderColor, + string $expectedFillColorAttribute, + string $expectedBorderColorAttribute + ): void { + // Arrange + $xmlWriter = new XMLWriter(); + $style = new TextBoxStyle(); + + if ($bgColor !== null) { + $style->setBgColor($bgColor); + } + + if ($borderColor !== null) { + $style->setBorderColor($borderColor); + } + + $textBoxElement = new TextBoxElement($style); + $textBox = new TextBox($xmlWriter, $textBoxElement); + + // Act + $textBox->write(); + $output = $xmlWriter->getData(); + + // Assert + self::assertStringContainsString($expectedFillColorAttribute, $output, 'Background color should be applied.'); + self::assertStringContainsString($expectedBorderColorAttribute, $output, 'Border color should be applied correctly.'); + } + + /** + * Data provider for testing different combinations of background and border colors. + */ + public static function textBoxColorProvider(): array + { + return [ + // Case 1: Background color set, border color set + 'With both colors' => [ + '#FF0000', + '#000000', + 'fillcolor="#FF0000"', + 'stroke color="#000000"', + ], + // Case 2: Background color set, no border color + 'With background only' => [ + '#00FF00', + null, + 'fillcolor="#00FF00"', + 'stroked="f" strokecolor="white"', + ], + // Case 3: No background color, border color set + 'With border only' => [ + null, + '#123456', + 'filled="f"', + 'stroke color="#123456"', + ], + // Case 4: Neither background nor border color set + 'Without any colors' => [ + null, + null, + 'filled="f"', + 'stroked="f" strokecolor="white"', + ], + ]; + } +} From 5c84adf95e9d6868fa89aeaad9b998de20af5310 Mon Sep 17 00:00:00 2001 From: moghwan <chaoui.mar2@gmail.com> Date: Thu, 13 Feb 2025 20:22:50 +0100 Subject: [PATCH 238/246] Feature: add limit option to setvalues (#2640) * adding limit option to setValues for multiple values * add parameter type * Update 2.0.0.md * add more replacement for testSetValues * testSetValues with different limit values * testSetValues with a zero replacement * Update 1.3.0.md * improve tests with variables count check to ensure number of occurrences replaced * Update 1.4.0.md * Update 1.3.0.md --- docs/changes/1.x/1.4.0.md | 1 + src/PhpWord/TemplateProcessor.php | 4 +- tests/PhpWordTests/TemplateProcessorTest.php | 45 +++++++++++++++++++- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 634d1d6f31..7213519719 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -34,6 +34,7 @@ - Bump dompdf/dompdf from 2.0.4 to 3.0.0 by [@dependabot](https://github.com/dependabot) fixing [#2621](https://github.com/PHPOffice/PHPWord/issues/2621) in [#2666](https://github.com/PHPOffice/PHPWord/pull/2666) - Add test case to make sure vMerge defaults to 'continue' by [@SpraxDev](https://github.com/SpraxDev) in [#2677](https://github.com/PHPOffice/PHPWord/pull/2677) +- Adding the possibility to use iterate search and replace with setValues by [@moghwan](https://github.com/moghwan) in [#2632](https://github.com/PHPOffice/PHPWord/pull/2640) ### Deprecations - Deprecate `PhpOffice\PhpWord\Style\Paragraph::getIndent()` : Use `PhpOffice\PhpWord\Style\Paragraph::getIndentLeft()` diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 360cce74b6..7dd99af291 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -362,10 +362,10 @@ public function setValue($search, $replace, $limit = self::MAXIMUM_REPLACEMENTS_ /** * Set values from a one-dimensional array of "variable => value"-pairs. */ - public function setValues(array $values): void + public function setValues(array $values, int $limit = self::MAXIMUM_REPLACEMENTS_DEFAULT): void { foreach ($values as $macro => $replace) { - $this->setValue($macro, $replace); + $this->setValue($macro, $replace, $limit); } } diff --git a/tests/PhpWordTests/TemplateProcessorTest.php b/tests/PhpWordTests/TemplateProcessorTest.php index d031eb75c1..093879a042 100644 --- a/tests/PhpWordTests/TemplateProcessorTest.php +++ b/tests/PhpWordTests/TemplateProcessorTest.php @@ -615,12 +615,53 @@ public function testSetValues(): void <w:r> <w:t xml:space="preserve">Hello ${firstname} ${lastname}</w:t> </w:r> - </w:p>'; + </w:p> + <w:p> + <w:r> + <w:t xml:space="preserve">Hello ${firstname} ${lastname}</w:t> + </w:r> + </w:p> + <w:p> + <w:r> + <w:t xml:space="preserve">Hello ${firstname} ${lastname}</w:t> + </w:r> + </w:p> + '; $templateProcessor = new TestableTemplateProcesor($mainPart); $templateProcessor->setValues(['firstname' => 'John', 'lastname' => 'Doe']); - self::assertStringContainsString('Hello John Doe', $templateProcessor->getMainPart()); + self::assertStringNotContainsString('Hello ${firstname} ${lastname}', $templateProcessor->getMainPart()); + + // test with a specific limit that is lower than the number of replacements + $templateProcessor = new TestableTemplateProcesor($mainPart); + $templateProcessor->setValues(['firstname' => 'Jane', 'lastname' => 'Smith'], 2); + $variablesCounts = $templateProcessor->getVariableCount(); + + self::assertStringContainsString('Hello Jane Smith', $templateProcessor->getMainPart()); + self::assertStringContainsString('Hello ${firstname} ${lastname}', $templateProcessor->getMainPart()); + self::assertEquals(1, $variablesCounts['firstname']); + self::assertEquals(1, $variablesCounts['lastname']); + + // test with a limit for only one replacement + $templateProcessor = new TestableTemplateProcesor($mainPart); + $templateProcessor->setValues(['firstname' => 'Alice', 'lastname' => 'Wonderland'], 1); + $variablesCounts = $templateProcessor->getVariableCount(); + + self::assertStringContainsString('Hello Alice Wonderland', $templateProcessor->getMainPart()); + self::assertStringContainsString('Hello ${firstname} ${lastname}', $templateProcessor->getMainPart()); + self::assertEquals(2, $variablesCounts['firstname']); + self::assertEquals(2, $variablesCounts['lastname']); + + // Test with a limit of 0 for a result with no replacements + $templateProcessor = new TestableTemplateProcesor($mainPart); + $templateProcessor->setValues(['firstname' => 'Test', 'lastname' => 'User'], 0); + $variablesCounts = $templateProcessor->getVariableCount(); + + self::assertStringContainsString('Hello ${firstname} ${lastname}', $templateProcessor->getMainPart()); + self::assertStringNotContainsString('Hello Test User', $templateProcessor->getMainPart()); + self::assertEquals(3, $variablesCounts['firstname']); + self::assertEquals(3, $variablesCounts['lastname']); } /** From cdf3d31f8b0b15560bc1a1db24cb7ccfc7edabe4 Mon Sep 17 00:00:00 2001 From: Michael Frey <michael.frey@gmx.ch> Date: Sat, 15 Feb 2025 07:41:33 +0100 Subject: [PATCH 239/246] test the reader with the writer (#2745) --- docs/changes/1.x/1.4.0.md | 1 + .../PhpWordTests/WriteReadback/ODTextTest.php | 59 ++++++ .../WriteReadback/Word2007Test.php | 170 ++++++++++++++++++ 3 files changed, 230 insertions(+) create mode 100644 tests/PhpWordTests/WriteReadback/ODTextTest.php create mode 100644 tests/PhpWordTests/WriteReadback/Word2007Test.php diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 7213519719..6fdef4e74f 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -35,6 +35,7 @@ - Bump dompdf/dompdf from 2.0.4 to 3.0.0 by [@dependabot](https://github.com/dependabot) fixing [#2621](https://github.com/PHPOffice/PHPWord/issues/2621) in [#2666](https://github.com/PHPOffice/PHPWord/pull/2666) - Add test case to make sure vMerge defaults to 'continue' by [@SpraxDev](https://github.com/SpraxDev) in [#2677](https://github.com/PHPOffice/PHPWord/pull/2677) - Adding the possibility to use iterate search and replace with setValues by [@moghwan](https://github.com/moghwan) in [#2632](https://github.com/PHPOffice/PHPWord/pull/2640) +- Add test cases that test the ODTText and Word2007 reader using the corresponding writer, increasing test coverage by [@MichaelPFrey](https://github.com/MichaelPFrey) in [#2745](https://github.com/PHPOffice/PHPWord/pull/2745) ### Deprecations - Deprecate `PhpOffice\PhpWord\Style\Paragraph::getIndent()` : Use `PhpOffice\PhpWord\Style\Paragraph::getIndentLeft()` diff --git a/tests/PhpWordTests/WriteReadback/ODTextTest.php b/tests/PhpWordTests/WriteReadback/ODTextTest.php new file mode 100644 index 0000000000..cee0f38301 --- /dev/null +++ b/tests/PhpWordTests/WriteReadback/ODTextTest.php @@ -0,0 +1,59 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWordTests\WriteReadback; + +use PhpOffice\PhpWord\Element\TextRun; +use PhpOffice\PhpWord\IOFactory; +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Writer\ODText; + +/** + * Test class for PhpOffice\PhpWord\Reader\ODText and PhpOffice\PhpWord\Writer\ODText. + * + * @coversDefaultClass \PhpOffice\PhpWord\Reader\ODText + * + * @runTestsInSeparateProcesses + */ +class ODTextTest extends \PHPUnit\Framework\TestCase +{ + /** + * Test a document with one section and text. + */ + public function testOneSectionWithText(): void + { + $phpWordWriter = new PhpWord(); + $testText = 'Hello World!'; + $sectionWriter = $phpWordWriter->addSection(); + $sectionWriter->addText($testText); + + $writer = new ODText($phpWordWriter); + $file = __DIR__ . '/../_files/temp.odt'; + $writer->save($file); + + self::assertFileExists($file); + + $phpWordReader = IOFactory::load($file, 'ODText'); + + self::assertCount(1, $phpWordReader->getSections()); + self::assertCount(1, $phpWordReader->getSections()[0]->getElements()); + self::assertInstanceOf(TextRun::class, $phpWordReader->getSections()[0]->getElements()[0]); + self::assertEquals($testText, $phpWordReader->getSections()[0]->getElements()[0]->getText()); + unlink($file); + } +} diff --git a/tests/PhpWordTests/WriteReadback/Word2007Test.php b/tests/PhpWordTests/WriteReadback/Word2007Test.php new file mode 100644 index 0000000000..572977ccf8 --- /dev/null +++ b/tests/PhpWordTests/WriteReadback/Word2007Test.php @@ -0,0 +1,170 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWordTests\WriteReadback; + +use PhpOffice\PhpWord\Element\TextRun; +use PhpOffice\PhpWord\IOFactory; +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Style\Font; +use PhpOffice\PhpWord\Writer\Word2007; + +/** + * Test class for PhpOffice\PhpWord\Reader\Word2007 and PhpOffice\PhpWord\Writer\Word2007. + * + * @coversDefaultClass \PhpOffice\PhpWord\Reader\Word2007 + * + * @runTestsInSeparateProcesses + */ +class Word2007Test extends \PHPUnit\Framework\TestCase +{ + /** + * Test default font name. + */ + public function testDefaultFontName(): void + { + $phpWordWriter = new PhpWord(); + $testDefaultFontName = 'Times New Roman'; + $phpWordWriter->setDefaultFontName($testDefaultFontName); + + $writer = new Word2007($phpWordWriter); + $file = __DIR__ . '/../_files/temp.docx'; + $writer->save($file); + + self::assertFileExists($file); + + $phpWordReader = IOFactory::load($file, 'Word2007'); + + self::assertEquals($testDefaultFontName, $phpWordReader->getDefaultFontName()); + + unlink($file); + } + + /** + * Test default Asian font name. + */ + public function testDefaultAsianFontName(): void + { + $phpWordWriter = new PhpWord(); + $testDefaultFontName = '標楷體'; + $phpWordWriter->setDefaultAsianFontName($testDefaultFontName); + + $writer = new Word2007($phpWordWriter); + $file = __DIR__ . '/../_files/temp.docx'; + $writer->save($file); + + self::assertFileExists($file); + + $phpWordReader = IOFactory::load($file, 'Word2007'); + + self::assertEquals($testDefaultFontName, $phpWordReader->getDefaultAsianFontName()); + + unlink($file); + } + + /** + * Test default font size. + */ + public function testDefaulFontSize(): void + { + $phpWordWriter = new PhpWord(); + $testDefaultFontSize = 144; + $phpWordWriter->setDefaultFontSize($testDefaultFontSize); + + $writer = new Word2007($phpWordWriter); + $file = __DIR__ . '/../_files/temp.docx'; + $writer->save($file); + + self::assertFileExists($file); + + $phpWordReader = IOFactory::load($file, 'Word2007'); + + self::assertEquals($testDefaultFontSize, $phpWordReader->getDefaultFontSize()); + + unlink($file); + } + + /** + * Test default font color. + */ + public function testDefaultFontColor(): void + { + $phpWordWriter = new PhpWord(); + $testDefaultFontColor = '00FF00'; + $phpWordWriter->setDefaultFontColor($testDefaultFontColor); + + $writer = new Word2007($phpWordWriter); + $file = __DIR__ . '/../_files/temp.docx'; + $writer->save($file); + + self::assertFileExists($file); + + $phpWordReader = IOFactory::load($file, 'Word2007'); + + self::assertEquals($testDefaultFontColor, $phpWordReader->getDefaultFontColor()); + + unlink($file); + } + + /** + * Test Zoom. + */ + public function testZoom(): void + { + $phpWordWriter = new PhpWord(); + $zoomLevel = 75; + $phpWordWriter->getSettings()->setZoom($zoomLevel); + + $writer = new Word2007($phpWordWriter); + $file = __DIR__ . '/../_files/temp.docx'; + $writer->save($file); + + self::assertFileExists($file); + + $phpWordReader = IOFactory::load($file, 'Word2007'); + + self::assertEquals($zoomLevel, $phpWordReader->getSettings()->getZoom()); + + unlink($file); + } + + /** + * Test a document with one section and text. + */ + public function testOneSectionWithText(): void + { + $phpWordWriter = new PhpWord(); + $testText = 'Hello World!'; + $sectionWriter = $phpWordWriter->addSection(); + $sectionWriter->addText($testText); + + $writer = new Word2007($phpWordWriter); + $file = __DIR__ . '/../_files/temp.docx'; + $writer->save($file); + + self::assertFileExists($file); + + $phpWordReader = IOFactory::load($file, 'Word2007'); + + self::assertCount(1, $phpWordReader->getSections()); + self::assertCount(1, $phpWordReader->getSections()[0]->getElements()); + self::assertInstanceOf(TextRun::class, $phpWordReader->getSections()[0]->getElements()[0]); + self::assertEquals($testText, $phpWordReader->getSections()[0]->getElements()[0]->getText()); + unlink($file); + } +} From c92ee4d6b19224c994b52f214c6a01b0c3ef4263 Mon Sep 17 00:00:00 2001 From: Progi1984 <progi1984@gmail.com> Date: Thu, 20 Feb 2025 13:05:20 +0100 Subject: [PATCH 240/246] Writer/Reader Word2007: Added support for the firstLineChars for Indentation (#2753) * Add support for the firstLineChars style in Word2007. * Writer Word2007: Added support for the firstLineChars for Indentation * Fixed Changelog * Fixed PHPStan & PHPCSFixer * Fixed PHPStan --------- Co-authored-by: ling <ling@yundian> --- docs/changes/1.x/1.4.0.md | 3 +- docs/usage/styles/paragraph.md | 2 +- src/PhpWord/Reader/Word2007/AbstractPart.php | 1 + src/PhpWord/Style/Indentation.php | 25 +++++++ src/PhpWord/Style/Paragraph.php | 8 +++ .../Writer/Word2007/Style/Indentation.php | 3 + .../Element/AbstractElementTest.php | 16 ++++- .../Reader/Word2007/StyleTest.php | 57 +++++++++++++-- .../PhpWordTests/Style/AbstractStyleTest.php | 33 +++++++-- tests/PhpWordTests/Style/IndentationTest.php | 1 + .../Writer/EPub3/Part/AbstractPartTest.php | 11 ++- .../Writer/EPub3/Style/AbstractStyleTest.php | 12 +++- .../Writer/ODText/Part/AbstractPartTest.php | 24 ++++++- .../Writer/Word2007/Part/AbstractPartTest.php | 30 ++++++-- .../Writer/Word2007/Style/IndentationTest.php | 71 +++++++++++++++++++ 15 files changed, 273 insertions(+), 24 deletions(-) create mode 100644 tests/PhpWordTests/Writer/Word2007/Style/IndentationTest.php diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 6fdef4e74f..711acf37e6 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -17,7 +17,8 @@ - Add basic ruby text (phonetic guide) support for Word2007 and HTML Reader/Writer, RTF Writer, basic support for ODT writing by [@Deadpikle](https://github.com/Deadpikle) in [#2727](https://github.com/PHPOffice/PHPWord/pull/2727) - Reader HTML: Support font styles for h1/h6 by [@Progi1984](https://github.com/Progi1984) fixing [#2619](https://github.com/PHPOffice/PHPWord/issues/2619) in [#2737](https://github.com/PHPOffice/PHPWord/pull/2737) - Writer EPub3: Basic support by [@Sambit003](https://github.com/Sambit003) fixing [#55](https://github.com/PHPOffice/PHPWord/issues/55) in [#2724](https://github.com/PHPOffice/PHPWord/pull/2724) -- Writer2007: Added support for background and border color transparency in Text Box element [@chudy20007](https://github.com/Chudy20007) in [#2555](https://github.com/PHPOffice/PHPWord/pull/2555) +- Writer Word2007: Added support for background and border color transparency in Text Box element by [@chudy20007](https://github.com/Chudy20007) in [#2555](https://github.com/PHPOffice/PHPWord/pull/2555) +- Writer/Reader Word2007: Added support for the firstLineChars for Indentation by [@liuzhilinux](https://github.com/liuzhilinux) & [@Progi1984](https://github.com/Progi1984) in [#2753](https://github.com/PHPOffice/PHPWord/pull/2753) ### Bug fixes diff --git a/docs/usage/styles/paragraph.md b/docs/usage/styles/paragraph.md index e9ca155005..f51d5ba030 100644 --- a/docs/usage/styles/paragraph.md +++ b/docs/usage/styles/paragraph.md @@ -7,7 +7,7 @@ Available Paragraph style options: - ``basedOn``. Parent style. - ``hanging``. Hanging indentation in *half inches*. - ``indent``. Indent (left indentation) in *half inches*. -- ``indentation``. An array of indentation key => value pairs in *twip*. Supports *left*, *right*, *firstLine* and *hanging* indentation. +- ``indentation``. An array of indentation key => value pairs in *twip*. Supports *left*, *right*, *firstLine*, *firstLineChars* and *hanging* indentation. See ``\PhpOffice\PhpWord\Style\Indentation`` for possible identation types. - ``keepLines``. Keep all lines on one page, *true* or *false*. - ``keepNext``. Keep paragraph with next paragraph, *true* or *false*. diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 96d4a46f8a..9d49573d69 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -708,6 +708,7 @@ protected function readParagraphStyle(XMLReader $xmlReader, DOMElement $domNode) 'indentRight' => [self::READ_VALUE, 'w:ind', 'w:right'], 'indentHanging' => [self::READ_VALUE, 'w:ind', 'w:hanging'], 'indentFirstLine' => [self::READ_VALUE, 'w:ind', 'w:firstLine'], + 'indentFirstLineChars' => [self::READ_VALUE, 'w:ind', 'w:firstLineChars'], 'spaceAfter' => [self::READ_VALUE, 'w:spacing', 'w:after'], 'spaceBefore' => [self::READ_VALUE, 'w:spacing', 'w:before'], 'widowControl' => [self::READ_FALSE, 'w:widowControl'], diff --git a/src/PhpWord/Style/Indentation.php b/src/PhpWord/Style/Indentation.php index c2032dd22f..f2b646f7b6 100644 --- a/src/PhpWord/Style/Indentation.php +++ b/src/PhpWord/Style/Indentation.php @@ -47,6 +47,13 @@ class Indentation extends AbstractStyle */ private $firstLine = 0; + /** + * Additional first line chars indentation (twip). + * + * @var int + */ + private $firstLineChars = 0; + /** * Indentation removed from first line (twip). * @@ -118,6 +125,24 @@ public function setFirstLine(?float $value): self return $this; } + /** + * Get first line chars. + */ + public function getFirstLineChars(): int + { + return $this->firstLineChars; + } + + /** + * Set first line chars. + */ + public function setFirstLineChars(int $value): self + { + $this->firstLineChars = $this->setIntVal($value, $this->firstLineChars); + + return $this; + } + /** * Get hanging. */ diff --git a/src/PhpWord/Style/Paragraph.php b/src/PhpWord/Style/Paragraph.php index 5dda985fe5..5ab7ade673 100644 --- a/src/PhpWord/Style/Paragraph.php +++ b/src/PhpWord/Style/Paragraph.php @@ -432,6 +432,14 @@ public function setIndentFirstLine(?float $value = null): self return $this->setIndentation(['firstLine' => $value]); } + /** + * Set firstlineChars indentation. + */ + public function setIndentFirstLineChars(int $value = 0): self + { + return $this->setIndentation(['firstLineChars' => $value]); + } + /** * Set left indentation. */ diff --git a/src/PhpWord/Writer/Word2007/Style/Indentation.php b/src/PhpWord/Writer/Word2007/Style/Indentation.php index 85880d4c22..3588683cd9 100644 --- a/src/PhpWord/Writer/Word2007/Style/Indentation.php +++ b/src/PhpWord/Writer/Word2007/Style/Indentation.php @@ -44,6 +44,9 @@ public function write(): void $firstLine = $style->getFirstLine(); $xmlWriter->writeAttributeIf(null !== $firstLine, 'w:firstLine', $this->convertTwip($firstLine)); + $firstLineChars = $style->getFirstLineChars(); + $xmlWriter->writeAttributeIf(0 !== $firstLineChars, 'w:firstLineChars', $this->convertTwip($firstLineChars)); + $hanging = $style->getHanging(); $xmlWriter->writeAttributeIf(null !== $hanging, 'w:hanging', $this->convertTwip($hanging)); diff --git a/tests/PhpWordTests/Element/AbstractElementTest.php b/tests/PhpWordTests/Element/AbstractElementTest.php index 8219871f73..307225b8f4 100644 --- a/tests/PhpWordTests/Element/AbstractElementTest.php +++ b/tests/PhpWordTests/Element/AbstractElementTest.php @@ -30,7 +30,13 @@ class AbstractElementTest extends \PHPUnit\Framework\TestCase */ public function testElementIndex(): void { - $stub = $this->getMockForAbstractClass(AbstractElement::class); + if (method_exists($this, 'getMockForAbstractClass')) { + $stub = $this->getMockForAbstractClass(AbstractElement::class); + } else { + /** @var AbstractElement $stub */ + $stub = new class() extends AbstractElement { + }; + } $ival = mt_rand(0, 100); $stub->setElementIndex($ival); self::assertEquals($ival, $stub->getElementIndex()); @@ -41,7 +47,13 @@ public function testElementIndex(): void */ public function testElementId(): void { - $stub = $this->getMockForAbstractClass(AbstractElement::class); + if (method_exists($this, 'getMockForAbstractClass')) { + $stub = $this->getMockForAbstractClass(AbstractElement::class); + } else { + /** @var AbstractElement $stub */ + $stub = new class() extends AbstractElement { + }; + } $stub->setElementId(); self::assertEquals(6, strlen($stub->getElementId())); } diff --git a/tests/PhpWordTests/Reader/Word2007/StyleTest.php b/tests/PhpWordTests/Reader/Word2007/StyleTest.php index 347c0350f9..7f4afde476 100644 --- a/tests/PhpWordTests/Reader/Word2007/StyleTest.php +++ b/tests/PhpWordTests/Reader/Word2007/StyleTest.php @@ -334,8 +334,14 @@ public function testPageVerticalAlign(): void /** * @dataProvider providerIndentation */ - public function testIndentation(string $indent, float $left, float $right, ?float $hanging, float $firstLine): void - { + public function testIndentation( + string $indent, + float $left, + float $right, + ?float $hanging, + float $firstLine, + int $firstLineChars + ): void { $documentXml = "<w:p> <w:pPr> $indent @@ -359,16 +365,53 @@ public function testIndentation(string $indent, float $left, float $right, ?floa self::assertSame($right, $indentation->getRight()); self::assertSame($hanging, $indentation->getHanging()); self::assertSame($firstLine, $indentation->getFirstLine()); + self::assertSame($firstLineChars, $indentation->getFirstLineChars()); } /** - * @return Generator<array{0:string, 1:float, 2:float, 3:null|float, 4: float}> + * @return Generator<array{0:string, 1:float, 2:float, 3:null|float, 4: float, 5: int}> */ public static function providerIndentation() { - yield ['<w:ind w:left="709" w:right="488" w:hanging="10" w:firstLine="490"/>', 709.00, 488.00, 10.0, 490.00]; - yield ['<w:ind w:hanging="10" w:firstLine="490"/>', 0, 0, 10.0, 490.00]; - yield ['<w:ind w:left="709"/>', 709.00, 0, 0, 0]; - yield ['<w:ind w:right="488"/>', 0, 488.00, 0, 0]; + yield [ + '<w:ind w:left="709" w:right="488" w:hanging="10" w:firstLine="490" w:firstLineChars="140"/>', + 709.00, + 488.00, + 10.0, + 490.00, + 140, + ]; + yield [ + '<w:ind w:left="709" w:right="488" w:hanging="10" w:firstLine="490"/>', + 709.00, + 488.00, + 10.0, + 490.00, + 0, + ]; + yield [ + '<w:ind w:hanging="10" w:firstLine="490"/>', + 0, + 0, + 10.0, + 490.00, + 0, + ]; + yield [ + '<w:ind w:left="709"/>', + 709.00, + 0, + 0, + 0, + 0, + ]; + yield [ + '<w:ind w:right="488"/>', + 0, + 488.00, + 0, + 0, + 0, + ]; } } diff --git a/tests/PhpWordTests/Style/AbstractStyleTest.php b/tests/PhpWordTests/Style/AbstractStyleTest.php index 2f1585fd5a..2b8d3d8d17 100644 --- a/tests/PhpWordTests/Style/AbstractStyleTest.php +++ b/tests/PhpWordTests/Style/AbstractStyleTest.php @@ -20,6 +20,7 @@ use InvalidArgumentException; use PhpOffice\PhpWord\SimpleType\Jc; +use PhpOffice\PhpWord\Style\AbstractStyle; use PhpOffice\PhpWord\Style\Paragraph; use ReflectionClass; @@ -35,7 +36,13 @@ class AbstractStyleTest extends \PHPUnit\Framework\TestCase */ public function testSetStyleByArray(): void { - $stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Style\AbstractStyle'); + if (method_exists($this, 'getMockForAbstractClass')) { + $stub = $this->getMockForAbstractClass(AbstractStyle::class); + } else { + /** @var AbstractStyle $stub */ + $stub = new class() extends AbstractStyle { + }; + } $stub->setStyleByArray(['index' => 1]); self::assertEquals(1, $stub->getIndex()); @@ -62,7 +69,13 @@ public function testSetStyleByArrayWithAlignment(): void */ public function testSetValNormal(): void { - $stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Style\AbstractStyle'); + if (method_exists($this, 'getMockForAbstractClass')) { + $stub = $this->getMockForAbstractClass(AbstractStyle::class); + } else { + /** @var AbstractStyle $stub */ + $stub = new class() extends AbstractStyle { + }; + } self::assertTrue(self::callProtectedMethod($stub, 'setBoolVal', [true, false])); self::assertEquals(12, self::callProtectedMethod($stub, 'setIntVal', [12, 200])); @@ -76,7 +89,13 @@ public function testSetValNormal(): void */ public function testSetValDefault(): void { - $stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Style\AbstractStyle'); + if (method_exists($this, 'getMockForAbstractClass')) { + $stub = $this->getMockForAbstractClass(AbstractStyle::class); + } else { + /** @var AbstractStyle $stub */ + $stub = new class() extends AbstractStyle { + }; + } self::assertNotTrue(self::callProtectedMethod($stub, 'setBoolVal', ['a', false])); self::assertEquals(200, self::callProtectedMethod($stub, 'setIntVal', ['foo', 200])); @@ -90,7 +109,13 @@ public function testSetValDefault(): void public function testSetValEnumException(): void { $this->expectException(InvalidArgumentException::class); - $stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Style\AbstractStyle'); + if (method_exists($this, 'getMockForAbstractClass')) { + $stub = $this->getMockForAbstractClass(AbstractStyle::class); + } else { + /** @var AbstractStyle $stub */ + $stub = new class() extends AbstractStyle { + }; + } self::assertEquals('b', self::callProtectedMethod($stub, 'setEnumVal', ['z', ['a', 'b'], 'b'])); } diff --git a/tests/PhpWordTests/Style/IndentationTest.php b/tests/PhpWordTests/Style/IndentationTest.php index db13407ff3..76e3c74cb7 100644 --- a/tests/PhpWordTests/Style/IndentationTest.php +++ b/tests/PhpWordTests/Style/IndentationTest.php @@ -37,6 +37,7 @@ public function testGetSetProperties(): void 'left' => [0, 10], 'right' => [0, 10], 'firstLine' => [null, 20], + 'firstLineChars' => [0, 20], 'hanging' => [null, 20], ]; foreach ($properties as $property => $value) { diff --git a/tests/PhpWordTests/Writer/EPub3/Part/AbstractPartTest.php b/tests/PhpWordTests/Writer/EPub3/Part/AbstractPartTest.php index 5151eea24c..c12980c7e2 100644 --- a/tests/PhpWordTests/Writer/EPub3/Part/AbstractPartTest.php +++ b/tests/PhpWordTests/Writer/EPub3/Part/AbstractPartTest.php @@ -15,7 +15,16 @@ class AbstractPartTest extends TestCase protected function setUp(): void { - $this->part = $this->getMockForAbstractClass(AbstractPart::class); + if (method_exists($this, 'getMockForAbstractClass')) { + $this->part = $this->getMockForAbstractClass(AbstractPart::class); + } else { + $this->part = new class() extends AbstractPart { + public function write(): string + { + return ''; + } + }; + } } public function testParentWriter(): void diff --git a/tests/PhpWordTests/Writer/EPub3/Style/AbstractStyleTest.php b/tests/PhpWordTests/Writer/EPub3/Style/AbstractStyleTest.php index fb9135f0cd..12be0f2e4f 100644 --- a/tests/PhpWordTests/Writer/EPub3/Style/AbstractStyleTest.php +++ b/tests/PhpWordTests/Writer/EPub3/Style/AbstractStyleTest.php @@ -14,7 +14,17 @@ class AbstractStyleTest extends TestCase public function testParentWriter(): void { $parentWriter = new EPub3(); - $style = $this->getMockForAbstractClass(AbstractStyle::class); + if (method_exists($this, 'getMockForAbstractClass')) { + $style = $this->getMockForAbstractClass(AbstractStyle::class); + } else { + /** @var AbstractStyle $style */ + $style = new class() extends AbstractStyle { + public function write(): string + { + return ''; + } + }; + } $result = $style->setParentWriter($parentWriter); diff --git a/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php b/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php index 6742b20ad5..27008dae82 100644 --- a/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php +++ b/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php @@ -34,7 +34,17 @@ class AbstractPartTest extends \PHPUnit\Framework\TestCase */ public function testSetGetParentWriter(): void { - $object = $this->getMockForAbstractClass(ODText\Part\AbstractPart::class); + if (method_exists($this, 'getMockForAbstractClass')) { + $object = $this->getMockForAbstractClass(ODText\Part\AbstractPart::class); + } else { + /** @var ODText\Part\AbstractPart $object */ + $object = new class() extends ODText\Part\AbstractPart { + public function write(): string + { + return ''; + } + }; + } $object->setParentWriter(new ODText()); self::assertEquals(new ODText(), $object->getParentWriter()); } @@ -46,7 +56,17 @@ public function testSetGetParentWriterNull(): void { $this->expectException(Exception::class); $this->expectExceptionMessage('No parent WriterInterface assigned.'); - $object = $this->getMockForAbstractClass(ODText\Part\AbstractPart::class); + if (method_exists($this, 'getMockForAbstractClass')) { + $object = $this->getMockForAbstractClass(ODText\Part\AbstractPart::class); + } else { + /** @var ODText\Part\AbstractPart $object */ + $object = new class() extends ODText\Part\AbstractPart { + public function write(): string + { + return ''; + } + }; + } $object->getParentWriter(); } } diff --git a/tests/PhpWordTests/Writer/Word2007/Part/AbstractPartTest.php b/tests/PhpWordTests/Writer/Word2007/Part/AbstractPartTest.php index 04cdb5ff52..ca38d5d3fc 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/AbstractPartTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/AbstractPartTest.php @@ -32,9 +32,19 @@ class AbstractPartTest extends \PHPUnit\Framework\TestCase */ public function testSetGetParentWriter(): void { - $object = $this->getMockForAbstractClass(Word2007\Part\AbstractPart::class); - $object->setParentWriter(new Word2007()); - self::assertEquals(new Word2007(), $object->getParentWriter()); + if (method_exists($this, 'getMockForAbstractClass')) { + $stub = $this->getMockForAbstractClass(Word2007\Part\AbstractPart::class); + } else { + /** @var Word2007\Part\AbstractPart $stub */ + $stub = new class() extends Word2007\Part\AbstractPart { + public function write(): string + { + return ''; + } + }; + } + $stub->setParentWriter(new Word2007()); + self::assertEquals(new Word2007(), $stub->getParentWriter()); } /** @@ -44,7 +54,17 @@ public function testSetGetParentWriterNull(): void { $this->expectException(Exception::class); $this->expectExceptionMessage('No parent WriterInterface assigned.'); - $object = $this->getMockForAbstractClass(Word2007\Part\AbstractPart::class); - $object->getParentWriter(); + if (method_exists($this, 'getMockForAbstractClass')) { + $stub = $this->getMockForAbstractClass(Word2007\Part\AbstractPart::class); + } else { + /** @var Word2007\Part\AbstractPart $stub */ + $stub = new class() extends Word2007\Part\AbstractPart { + public function write(): string + { + return ''; + } + }; + } + $stub->getParentWriter(); } } diff --git a/tests/PhpWordTests/Writer/Word2007/Style/IndentationTest.php b/tests/PhpWordTests/Writer/Word2007/Style/IndentationTest.php new file mode 100644 index 0000000000..44d071415a --- /dev/null +++ b/tests/PhpWordTests/Writer/Word2007/Style/IndentationTest.php @@ -0,0 +1,71 @@ +<?php + +/** + * This file is part of PHPWord - A pure PHP library for reading and writing + * word processing documents. + * + * PHPWord is free software distributed under the terms of the GNU Lesser + * General Public License version 3 as published by the Free Software Foundation. + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. For the full list of + * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. + * + * @see https://github.com/PHPOffice/PHPWord + * + * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 + */ + +namespace PhpOffice\PhpWordTests\Writer\Word2007\Style; + +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Settings; +use PhpOffice\PhpWord\Style\Paragraph; +use PhpOffice\PhpWordTests\TestHelperDOCX; + +class IndentationTest extends \PHPUnit\Framework\TestCase +{ + /** + * Executed before each method of the class. + */ + protected function tearDown(): void + { + Settings::setDefaultRtl(null); + TestHelperDOCX::clear(); + } + + public function testDefault(): void + { + $word = new PhpWord(); + Settings::setDefaultRtl(true); + $section = $word->addSection(); + $text = $section->addText('AA'); + $paragraphStyle = $text->getParagraphStyle(); + self::assertInstanceOf(Paragraph::class, $paragraphStyle); + $paragraphStyle->setIndentation([]); + $doc = TestHelperDOCX::getDocument($word, 'Word2007'); + + $path = '/w:document/w:body/w:p[1]/w:pPr/w:ind'; + self::assertTrue($doc->elementExists($path)); + self::assertFalse($doc->hasElementAttribute($path, 'w:firstLineChars')); + } + + public function testFirstLineChars(): void + { + $word = new PhpWord(); + Settings::setDefaultRtl(true); + $section = $word->addSection(); + $text = $section->addText('AA'); + $paragraphStyle = $text->getParagraphStyle(); + self::assertInstanceOf(Paragraph::class, $paragraphStyle); + $paragraphStyle->setIndentation([ + 'firstLineChars' => 1440, + ]); + $doc = TestHelperDOCX::getDocument($word, 'Word2007'); + + $path = '/w:document/w:body/w:p[1]/w:pPr/w:ind'; + self::assertTrue($doc->elementExists($path)); + self::assertTrue($doc->hasElementAttribute($path, 'w:firstLineChars')); + self::assertSame('1440', $doc->getElementAttribute($path, 'w:firstLineChars')); + } +} From 6ca8c9ff67e0ea7729973b7b3a33626febad6628 Mon Sep 17 00:00:00 2001 From: Jessica <122348613+jgiacomello@users.noreply.github.com> Date: Thu, 20 Feb 2025 21:19:21 +0100 Subject: [PATCH 241/246] automatic update of the TOC to fix page number missing issues (#2556) * fix: TOC pages numbers * fix: TOC pages numbers * Update tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php Co-authored-by: Progi1984 <progi1984@gmail.com> * changelog update * fix testWriteTitleWithoutpageNumber * fix testWriteTitleWithoutpageNumber * Fixed Changelog --------- Co-authored-by: Progi1984 <progi1984@gmail.com> --- docs/changes/1.x/1.4.0.md | 1 + src/PhpWord/Writer/Word2007/Element/TOC.php | 2 +- .../Writer/Word2007/Element/TOCTest.php | 27 +++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 711acf37e6..ed095035e3 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -30,6 +30,7 @@ - Reader HTML: Support for inherit value for property line-height by [@Progi1984](https://github.com/Progi1984) fixing [#2683](https://github.com/PHPOffice/PHPWord/issues/2683) in [#2733](https://github.com/PHPOffice/PHPWord/pull/2733) - Writer HTML: Fixed null string for Text Elements by [@armagedon007](https://github.com/armagedon007) and [@Progi1984](https://github.com/Progi1984) in [#2738](https://github.com/PHPOffice/PHPWord/pull/2738) - Template Processor: Fix 0 considered as empty string by [@cavasinf](https://github.com/cavasinf), [@SnipsMine](https://github.com/SnipsMine) and [@Progi1984](https://github.com/Progi1984) fixing [#2572](https://github.com/PHPOffice/PHPWord/issues/2572), [#2703](https://github.com/PHPOffice/PHPWord/issues/2703) in [#2748](https://github.com/PHPOffice/PHPWord/pull/2748) +- Word2007 Writer : Corrected generating TOC to fix page number missing issues [@jgiacomello](https://github.com/jgiacomello) in [#2556](https://github.com/PHPOffice/PHPWord/pull/2556) ### Miscellaneous diff --git a/src/PhpWord/Writer/Word2007/Element/TOC.php b/src/PhpWord/Writer/Word2007/Element/TOC.php index 8164aa6528..44c6ba11fa 100644 --- a/src/PhpWord/Writer/Word2007/Element/TOC.php +++ b/src/PhpWord/Writer/Word2007/Element/TOC.php @@ -114,7 +114,7 @@ private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, Title $ti $xmlWriter->startElement('w:r'); $xmlWriter->startElement('w:instrText'); $xmlWriter->writeAttribute('xml:space', 'preserve'); - $xmlWriter->text("PAGEREF _Toc{$rId} \\h"); + $xmlWriter->text("PAGEREF $rId \\h"); $xmlWriter->endElement(); $xmlWriter->endElement(); diff --git a/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php b/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php index 45973a4fed..95e79114aa 100644 --- a/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php @@ -15,6 +15,7 @@ * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ + declare(strict_types=1); namespace PhpOffice\PhpWordTests\Writer\Word2007\Element; @@ -54,4 +55,30 @@ public function testWriteTitlePageNumber(): void self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:hyperlink/w:r[6]/w:t')); self::assertEquals($expectedPageNum, $doc->getElement('/w:document/w:body/w:p[1]/w:hyperlink/w:r[6]/w:t')->textContent); } + + public function testWriteTitleWithoutpageNumber(): void + { + $phpWord = new PhpWord(); + + $section = $phpWord->addSection(); + $section->addTOC(); + + //more than one title and random text for create more than one page + for ($i = 1; $i <= 10; ++$i) { + $section->addTitle('Title ' . $i, 1); + $content = file_get_contents('https://loripsum.net/api/10/long'); + \PhpOffice\PhpWord\Shared\Html::addHtml($section, $content ? $content : '', false, false); + $section->addPageBreak(); + } + + $doc = TestHelperDOCX::getDocument($phpWord); + + for ($i = 1; $i <= 10; ++$i) { + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[' . $i . ']/w:hyperlink/w:r[1]/w:t')); + self::assertEquals('Title ' . $i, $doc->getElement('/w:document/w:body/w:p[' . $i . ']/w:hyperlink/w:r[1]/w:t')->textContent); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[' . $i . ']/w:hyperlink/w:r[4]/w:instrText')); + self::assertEquals('preserve', $doc->getElementAttribute('/w:document/w:body/w:p[' . $i . ']/w:hyperlink/w:r[4]/w:instrText', 'xml:space')); + self::assertEquals('PAGEREF ' . ($i - 1) . ' \\h', $doc->getElement('/w:document/w:body/w:p[' . $i . ']/w:hyperlink/w:r[4]/w:instrText')->nodeValue); + } + } } From 1f28d36d4060edc09bdec5404aa908b05baff533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Schroeder?= <michalschroeder@gmail.com> Date: Fri, 30 May 2025 20:19:48 +0200 Subject: [PATCH 242/246] Code fixes to make a CI green (#2784) * Enhance error handling in encoding functions and update TOC test with static HTML content * Update TOC test to use static HTML content instead of external API * update changelog --- docs/changes/1.x/1.4.0.md | 2 ++ src/PhpWord/Shared/Microsoft/PasswordEncoder.php | 7 ++++++- src/PhpWord/Shared/Text.php | 5 +++++ tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php | 9 +++++++-- tests/bootstrap.php | 4 +++- 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index ed095035e3..9eb6d42d71 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -31,6 +31,7 @@ - Writer HTML: Fixed null string for Text Elements by [@armagedon007](https://github.com/armagedon007) and [@Progi1984](https://github.com/Progi1984) in [#2738](https://github.com/PHPOffice/PHPWord/pull/2738) - Template Processor: Fix 0 considered as empty string by [@cavasinf](https://github.com/cavasinf), [@SnipsMine](https://github.com/SnipsMine) and [@Progi1984](https://github.com/Progi1984) fixing [#2572](https://github.com/PHPOffice/PHPWord/issues/2572), [#2703](https://github.com/PHPOffice/PHPWord/issues/2703) in [#2748](https://github.com/PHPOffice/PHPWord/pull/2748) - Word2007 Writer : Corrected generating TOC to fix page number missing issues [@jgiacomello](https://github.com/jgiacomello) in [#2556](https://github.com/PHPOffice/PHPWord/pull/2556) +- Enhanced error handling in encoding functions [@michalschroeder](https://github.com/michalschroeder) in [#2784](https://github.com/PHPOffice/PHPWord/pull/2784) ### Miscellaneous @@ -38,6 +39,7 @@ - Add test case to make sure vMerge defaults to 'continue' by [@SpraxDev](https://github.com/SpraxDev) in [#2677](https://github.com/PHPOffice/PHPWord/pull/2677) - Adding the possibility to use iterate search and replace with setValues by [@moghwan](https://github.com/moghwan) in [#2632](https://github.com/PHPOffice/PHPWord/pull/2640) - Add test cases that test the ODTText and Word2007 reader using the corresponding writer, increasing test coverage by [@MichaelPFrey](https://github.com/MichaelPFrey) in [#2745](https://github.com/PHPOffice/PHPWord/pull/2745) +- Updated TOCTest to use static HTML content instead of external resource [@michalschroeder](https://github.com/michalschroeder) in [#2784](https://github.com/PHPOffice/PHPWord/pull/2784) ### Deprecations - Deprecate `PhpOffice\PhpWord\Style\Paragraph::getIndent()` : Use `PhpOffice\PhpWord\Style\Paragraph::getIndentLeft()` diff --git a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php b/src/PhpWord/Shared/Microsoft/PasswordEncoder.php index 45f9a53632..4762cc7104 100644 --- a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php +++ b/src/PhpWord/Shared/Microsoft/PasswordEncoder.php @@ -18,6 +18,8 @@ namespace PhpOffice\PhpWord\Shared\Microsoft; +use PhpOffice\PhpWord\Exception\Exception; + /** * Password encoder for microsoft office applications. */ @@ -119,8 +121,11 @@ public static function hashPassword($password, $algorithmName = self::ALGORITHM_ // Get the single-byte values by iterating through the Unicode characters of the truncated password. // For each character, if the low byte is not equal to 0, take it. Otherwise, take the high byte. $passUtf8 = mb_convert_encoding($password, 'UCS-2LE', 'UTF-8'); - $byteChars = []; + if (!is_string($passUtf8)) { + throw new Exception('Failed to convert password to UCS-2LE'); + } + $byteChars = []; for ($i = 0; $i < mb_strlen($password); ++$i) { $byteChars[$i] = ord(substr($passUtf8, $i * 2, 1)); diff --git a/src/PhpWord/Shared/Text.php b/src/PhpWord/Shared/Text.php index 90550c0650..251764b3dd 100644 --- a/src/PhpWord/Shared/Text.php +++ b/src/PhpWord/Shared/Text.php @@ -18,6 +18,8 @@ namespace PhpOffice\PhpWord\Shared; +use PhpOffice\PhpWord\Exception\Exception; + /** * Text. */ @@ -148,6 +150,9 @@ public static function toUTF8($value = '') if (null !== $value && !self::isUTF8($value)) { // PHP8.2 : utf8_encode is deprecated, but mb_convert_encoding always usable $value = (function_exists('mb_convert_encoding')) ? mb_convert_encoding($value, 'UTF-8', 'ISO-8859-1') : utf8_encode($value); + if ($value === false) { + throw new Exception('Unable to convert text to UTF-8'); + } } return $value; diff --git a/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php b/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php index 95e79114aa..66778a41ec 100644 --- a/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php @@ -63,11 +63,16 @@ public function testWriteTitleWithoutpageNumber(): void $section = $phpWord->addSection(); $section->addTOC(); + $staticHtml = '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. + Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. + Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi.</p> + <p>Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. + Duis semper. Duis arcu massa, scelerisque vitae, consequat in, pretium a, enim.</p>'; + //more than one title and random text for create more than one page for ($i = 1; $i <= 10; ++$i) { $section->addTitle('Title ' . $i, 1); - $content = file_get_contents('https://loripsum.net/api/10/long'); - \PhpOffice\PhpWord\Shared\Html::addHtml($section, $content ? $content : '', false, false); + \PhpOffice\PhpWord\Shared\Html::addHtml($section, $staticHtml, false, false); $section->addPageBreak(); } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 7c4e0a3e1b..f9e0ca2388 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -54,7 +54,9 @@ function phpunit10ErrorHandler(int $errno, string $errstr, string $filename, int function utf8decode(string $value, string $toEncoding = 'ISO-8859-1'): string { - return function_exists('mb_convert_encoding') ? mb_convert_encoding($value, $toEncoding, 'UTF-8') : utf8_decode($value); + $result = function_exists('mb_convert_encoding') ? mb_convert_encoding($value, $toEncoding, 'UTF-8') : utf8_decode($value); + + return $result === false ? '' : $result; } if (!method_exists(PHPUnit\Framework\TestCase::class, 'setOutputCallback')) { From 44e6c268e3c03b0ce5e5ca2665c400a211d34d8b Mon Sep 17 00:00:00 2001 From: Eileen McNaughton <eileen@mcnaughty.com> Date: Tue, 3 Jun 2025 17:06:38 +1200 Subject: [PATCH 243/246] Update phpmath from 0.2.0 to 0.3.0 (#2785) * Update phpmath Release 0.3.0 has a security fix in it... https://github.com/PHPOffice/Math/compare/0.2.0...master * Update Changelog 1.4.0.md --- composer.json | 2 +- docs/changes/1.x/1.4.0.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5055105d16..90b1c2e571 100644 --- a/composer.json +++ b/composer.json @@ -112,7 +112,7 @@ "ext-zip": "*", "ext-json": "*", "ext-xml": "*", - "phpoffice/math": "^0.2" + "phpoffice/math": "^0.3" }, "require-dev": { "ext-libxml": "*", diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 9eb6d42d71..84b5e8eeeb 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -40,6 +40,7 @@ - Adding the possibility to use iterate search and replace with setValues by [@moghwan](https://github.com/moghwan) in [#2632](https://github.com/PHPOffice/PHPWord/pull/2640) - Add test cases that test the ODTText and Word2007 reader using the corresponding writer, increasing test coverage by [@MichaelPFrey](https://github.com/MichaelPFrey) in [#2745](https://github.com/PHPOffice/PHPWord/pull/2745) - Updated TOCTest to use static HTML content instead of external resource [@michalschroeder](https://github.com/michalschroeder) in [#2784](https://github.com/PHPOffice/PHPWord/pull/2784) +- Bump PHPOffice/math from 0.2.0 to 0.3.0 by [@eileenmcnaughton](https://github.com/eileenmcnaughton) in [#2785](https://github.com/PHPOffice/PHPWord/pull/2785) ### Deprecations - Deprecate `PhpOffice\PhpWord\Style\Paragraph::getIndent()` : Use `PhpOffice\PhpWord\Style\Paragraph::getIndentLeft()` From 6d75328229bc93790b37e93741adf70646cea958 Mon Sep 17 00:00:00 2001 From: Progi1984 <progi1984@gmail.com> Date: Thu, 5 Jun 2025 12:32:36 +0200 Subject: [PATCH 244/246] Release 1.4.0 (#2786) --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- docs/changes/1.x/1.4.0.md | 2 +- docs/changes/1.x/1.5.0.md | 15 +++++++++++++++ mkdocs.yml | 3 ++- 4 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 docs/changes/1.x/1.5.0.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7b74162561..b91f1bd4ac 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -9,4 +9,4 @@ Fixes # (issue) - [ ] My CI is :green_circle: - [ ] I have covered by unit tests my new code (check build/coverage for coverage report) - [ ] I have updated the [documentation](https://github.com/PHPOffice/PHPWord/tree/master/docs) to describe the changes -- [ ] I have updated the [changelog](https://github.com/PHPOffice/PHPWord/blob/master/docs/changes/1.x/1.4.0.md) +- [ ] I have updated the [changelog](https://github.com/PHPOffice/PHPWord/blob/master/docs/changes/1.x/1.5.0.md) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 84b5e8eeeb..5daf85dbfd 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -1,4 +1,4 @@ -# [1.4.0](https://github.com/PHPOffice/PHPWord/tree/1.4.0) (WIP) +# [1.4.0](https://github.com/PHPOffice/PHPWord/tree/1.4.0) [Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.3.0...1.4.0) diff --git a/docs/changes/1.x/1.5.0.md b/docs/changes/1.x/1.5.0.md new file mode 100644 index 0000000000..ba8c15e939 --- /dev/null +++ b/docs/changes/1.x/1.5.0.md @@ -0,0 +1,15 @@ +# [1.5.0](https://github.com/PHPOffice/PHPWord/tree/1.5.0) (WIP) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.4.0...1.5.0) + +## Enhancements + +### Bug fixes + +### Miscellaneous + +### Deprecations + +### BC Breaks + +### Notes \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 0462c9c8a4..97c842112c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -88,7 +88,8 @@ nav: - Credits: 'credits.md' - Releases: - '1.x': - - '1.4.0 (WIP)': 'changes/1.x/1.4.0.md' + - '1.5.0 (WIP)': 'changes/1.x/1.5.0.md' + - '1.4.0': 'changes/1.x/1.4.0.md' - '1.3.0': 'changes/1.x/1.3.0.md' - '1.2.0': 'changes/1.x/1.2.0.md' - '1.1.0': 'changes/1.x/1.1.0.md' From a3de6efd7af4c27e98d8808a966206d172a60890 Mon Sep 17 00:00:00 2001 From: Andrew Murray <3112309+radarhere@users.noreply.github.com> Date: Thu, 5 Jun 2025 21:28:33 +1000 Subject: [PATCH 245/246] Set writeAttribute return type (#2776) Co-authored-by: Andrew Murray <radarhere@users.noreply.github.com> --- docs/changes/1.x/1.5.0.md | 2 ++ src/PhpWord/Shared/XMLWriter.php | 6 +----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/changes/1.x/1.5.0.md b/docs/changes/1.x/1.5.0.md index ba8c15e939..bbe131d32f 100644 --- a/docs/changes/1.x/1.5.0.md +++ b/docs/changes/1.x/1.5.0.md @@ -6,6 +6,8 @@ ### Bug fixes +- Set writeAttribute return type by [@radarhere](https://github.com/radarhere) fixing [#2204](https://github.com/PHPOffice/PHPWord/issues/2204) in [#2776](https://github.com/PHPOffice/PHPWord/pull/2776) + ### Miscellaneous ### Deprecations diff --git a/src/PhpWord/Shared/XMLWriter.php b/src/PhpWord/Shared/XMLWriter.php index 8dc28e1184..441eac05f0 100644 --- a/src/PhpWord/Shared/XMLWriter.php +++ b/src/PhpWord/Shared/XMLWriter.php @@ -19,7 +19,6 @@ namespace PhpOffice\PhpWord\Shared; use Exception; -use ReturnTypeWillChange; /** * XMLWriter. @@ -173,11 +172,8 @@ public function writeAttributeIf($condition, $attribute, $value): void /** * @param string $name * @param mixed $value - * - * @return bool */ - #[ReturnTypeWillChange] - public function writeAttribute($name, $value) + public function writeAttribute($name, $value): bool { if (is_float($value)) { $value = json_encode($value); From 0ab0b4940bc52c7183e82ab2fd55324607037a73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Jun 2025 12:02:28 +0200 Subject: [PATCH 246/246] Update phpstan/phpstan requirement from ^0.12.88 || ^1.0.0 to ^0.12.88 || ^1.0.0 || ^2.0.0 (#2736) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Progi1984 <progi1984@gmail.com> --- composer.json | 2 +- docs/changes/1.x/1.5.0.md | 2 + phpstan-baseline.neon | 36 +++++++++ phpstan.neon.dist | 1 + src/PhpWord/Element/Field.php | 38 ++++----- src/PhpWord/Element/OLEObject.php | 11 ++- src/PhpWord/Element/Section.php | 6 +- src/PhpWord/Element/TOC.php | 5 +- src/PhpWord/Reader/ODText/Content.php | 3 +- src/PhpWord/Reader/RTF/Document.php | 2 +- src/PhpWord/Reader/Word2007.php | 9 ++- src/PhpWord/Reader/Word2007/Document.php | 2 +- src/PhpWord/Shared/Html.php | 14 ++-- src/PhpWord/Shared/ZipArchive.php | 33 ++++---- src/PhpWord/Style/Chart.php | 5 +- src/PhpWord/Style/Language.php | 20 ++--- src/PhpWord/Style/Numbering.php | 14 ++-- src/PhpWord/Style/NumberingLevel.php | 2 +- src/PhpWord/Style/Row.php | 30 ++----- src/PhpWord/Style/Table.php | 29 ++++--- src/PhpWord/TemplateProcessor.php | 21 ++--- .../Writer/EPub3/Part/ContentXhtml.php | 5 +- src/PhpWord/Writer/HTML.php | 6 +- src/PhpWord/Writer/HTML/Element/Ruby.php | 4 - src/PhpWord/Writer/HTML/Style/Table.php | 6 +- src/PhpWord/Writer/ODText/Element/Field.php | 10 +-- src/PhpWord/Writer/ODText/Part/Content.php | 3 +- src/PhpWord/Writer/ODText/Style/Font.php | 2 +- src/PhpWord/Writer/ODText/Style/Paragraph.php | 4 +- src/PhpWord/Writer/RTF/Part/Document.php | 24 +++--- src/PhpWord/Writer/RTF/Style/Border.php | 2 +- src/PhpWord/Writer/Word2007.php | 2 +- .../Writer/Word2007/Element/FormField.php | 2 +- src/PhpWord/Writer/Word2007/Element/SDT.php | 2 +- src/PhpWord/Writer/Word2007/Element/Shape.php | 2 +- .../Writer/Word2007/Part/Numbering.php | 6 +- src/PhpWord/Writer/Word2007/Part/Styles.php | 2 +- src/PhpWord/Writer/Word2007/Style/Table.php | 4 +- .../ComplexType/RubyPropertiesTest.php | 9 +-- .../Element/AbstractElementTest.php | 2 + tests/PhpWordTests/Element/BookmarkTest.php | 1 - tests/PhpWordTests/Element/CellTest.php | 1 - tests/PhpWordTests/Element/CheckBoxTest.php | 1 - tests/PhpWordTests/Element/CommentTest.php | 1 - tests/PhpWordTests/Element/FieldTest.php | 16 ---- tests/PhpWordTests/Element/FooterTest.php | 1 - tests/PhpWordTests/Element/FootnoteTest.php | 1 - tests/PhpWordTests/Element/FormulaTest.php | 13 +--- tests/PhpWordTests/Element/HeaderTest.php | 1 - tests/PhpWordTests/Element/ImageTest.php | 10 +-- tests/PhpWordTests/Element/LineTest.php | 1 - tests/PhpWordTests/Element/LinkTest.php | 2 - .../PhpWordTests/Element/ListItemRunTest.php | 4 - tests/PhpWordTests/Element/ObjectTest.php | 5 +- tests/PhpWordTests/Element/PageBreakTest.php | 41 ---------- .../PhpWordTests/Element/PreserveTextTest.php | 1 - tests/PhpWordTests/Element/RowTest.php | 1 - tests/PhpWordTests/Element/RubyTest.php | 7 -- tests/PhpWordTests/Element/SDTTest.php | 1 - tests/PhpWordTests/Element/TableTest.php | 1 - tests/PhpWordTests/Element/TextBoxTest.php | 1 - tests/PhpWordTests/Element/TextRunTest.php | 4 - tests/PhpWordTests/Element/TextTest.php | 1 - tests/PhpWordTests/Element/TitleTest.php | 2 - .../PhpWordTests/Element/TrackChangeTest.php | 2 - .../Exception/CopyFileExceptionTest.php | 2 - .../CreateTemporaryFileExceptionTest.php | 2 - tests/PhpWordTests/Metadata/SettingsTest.php | 6 +- tests/PhpWordTests/SettingsTest.php | 2 +- tests/PhpWordTests/Shared/XMLReaderTest.php | 6 +- .../PhpWordTests/Style/AbstractStyleTest.php | 4 + tests/PhpWordTests/Style/CellTest.php | 37 ++++++--- tests/PhpWordTests/Style/ChartTest.php | 4 - tests/PhpWordTests/Style/ImageTest.php | 27 ++++--- tests/PhpWordTests/Style/LanguageTest.php | 29 +++++-- .../PhpWordTests/Style/LineNumberingTest.php | 27 +++++-- tests/PhpWordTests/Style/LineTest.php | 25 ++++-- .../PhpWordTests/Style/NumberingLevelTest.php | 27 +++++-- tests/PhpWordTests/Style/NumberingTest.php | 30 ++++--- tests/PhpWordTests/Style/ParagraphTest.php | 78 ++++++++++--------- tests/PhpWordTests/Style/RowTest.php | 20 ----- tests/PhpWordTests/Style/SpacingTest.php | 23 +++++- tests/PhpWordTests/Style/TOCTest.php | 29 +++++-- tests/PhpWordTests/Style/TabTest.php | 29 +++++-- .../PhpWordTests/Style/TablePositionTest.php | 27 +++++-- tests/PhpWordTests/TemplateProcessorTest.php | 1 - .../Writer/EPub3/Part/AbstractPartTest.php | 1 + .../Writer/EPub3/Style/AbstractStyleTest.php | 1 + tests/PhpWordTests/Writer/HTMLTest.php | 20 +++-- .../Writer/ODText/ElementTest.php | 8 +- .../Writer/ODText/Part/AbstractPartTest.php | 2 + .../Writer/Word2007/Part/AbstractPartTest.php | 2 + .../Writer/Word2007/Part/DocumentTest.php | 3 +- .../Writer/Word2007/StyleTest.php | 45 +++++++---- tests/bootstrap.php | 1 + 95 files changed, 540 insertions(+), 480 deletions(-) delete mode 100644 tests/PhpWordTests/Element/PageBreakTest.php diff --git a/composer.json b/composer.json index 90b1c2e571..08ef4ec927 100644 --- a/composer.json +++ b/composer.json @@ -120,7 +120,7 @@ "friendsofphp/php-cs-fixer": "^3.3", "mpdf/mpdf": "^7.0 || ^8.0", "phpmd/phpmd": "^2.13", - "phpstan/phpstan": "^0.12.88 || ^1.0.0", + "phpstan/phpstan": "^0.12.88 || ^1.0.0 || ^2.0.0", "phpstan/phpstan-phpunit": "^1.0 || ^2.0", "phpunit/phpunit": ">=7.0", "symfony/process": "^4.4 || ^5.0", diff --git a/docs/changes/1.x/1.5.0.md b/docs/changes/1.x/1.5.0.md index bbe131d32f..b96865bada 100644 --- a/docs/changes/1.x/1.5.0.md +++ b/docs/changes/1.x/1.5.0.md @@ -10,6 +10,8 @@ ### Miscellaneous +- Update phpstan/phpstan requirement from ^0.12.88 || ^1.0.0 to ^0.12.88 || ^1.0.0 || ^2.0.0 by [@dependabot](https://github.com/dependabot) & [@Progi1984](https://github.com/Progi1984) in [#2736](https://github.com/PHPOffice/PHPWord/pull/2736) + ### Deprecations ### BC Breaks diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 86a542769a..ea75a4bd91 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1839,3 +1839,39 @@ parameters: message: "#^Property PhpOffice\\\\PhpWordTests\\\\XmlDocument\\:\\:\\$xpath \\(DOMXPath\\) does not accept null\\.$#" count: 1 path: tests/PhpWordTests/XmlDocument.php + + # https://github.com/phpstan/phpstan/issues/8770 + - + message: "#^PHPDoc tag @var with type PhpOffice\\\\PhpWord\\\\Writer\\\\HTML\\\\Part\\\\AbstractPart is not subtype of native type[\\sA-Za-z\\@\\\\\\/0-9\\.:|]+$#" + count: 1 + path: src/PhpWord/Writer/HTML.php + + # https://github.com/phpstan/phpstan/issues/8770 + - + message: "#^PHPDoc tag @var with type PhpOffice\\\\PhpWord\\\\Element\\\\AbstractElement is not subtype of native type[\\sA-Za-z\\@\\\\\\/0-9\\.:]+$#" + count: 2 + path: tests/PhpWordTests/Element/AbstractElementTest.php + + # https://github.com/phpstan/phpstan/issues/8770 + - + message: "#^PHPDoc tag @var with type PhpOffice\\\\PhpWord\\\\Style\\\\AbstractStyle is not subtype of native type[\\sA-Za-z\\@\\\\\\/0-9\\.:]+$#" + count: 4 + path: tests/PhpWordTests/Style/AbstractStyleTest.php + + # https://github.com/phpstan/phpstan/issues/8770 + - + message: "#^PHPDoc tag @var with type PhpOffice\\\\PhpWord\\\\Writer\\\\EPub3\\\\Style\\\\AbstractStyle is not subtype of native type[\\sA-Za-z\\@\\\\\\/0-9\\.:]+$#" + count: 2 + path: tests/PhpWordTests/Writer/EPub3/Style/AbstractStyleTest.php + + # https://github.com/phpstan/phpstan/issues/8770 + - + message: "#^PHPDoc tag @var with type PhpOffice\\\\PhpWord\\\\Writer\\\\ODText\\\\Part\\\\AbstractPart is not subtype of native type[\\sA-Za-z\\@\\\\\\/0-9\\.:]+$#" + count: 2 + path: tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php + + # https://github.com/phpstan/phpstan/issues/8770 + - + message: "#^PHPDoc tag @var with type PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Part\\\\AbstractPart is not subtype of native type[\\sA-Za-z\\@\\\\\\/0-9\\.:]+$#" + count: 2 + path: tests/PhpWordTests/Writer/Word2007/Part/AbstractPartTest.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 0cdf25ef21..cf26b6956b 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -16,6 +16,7 @@ parameters: - tests/bootstrap.php ## <=PHP7.4 reportUnmatchedIgnoredErrors: false + treatPhpDocTypesAsCertain: false ignoreErrors: - identifier: missingType.iterableValue diff --git a/src/PhpWord/Element/Field.php b/src/PhpWord/Element/Field.php index cb6ac070f0..592d6e421c 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -108,7 +108,7 @@ class Field extends AbstractElement /** * Field text. * - * @var string|TextRun + * @var null|string|TextRun */ protected $text; @@ -217,22 +217,18 @@ public function getType() /** * Set Field properties. * - * @param array $properties - * * @return self */ - public function setProperties($properties = []) + public function setProperties(array $properties = []) { - if (is_array($properties)) { - foreach (array_keys($properties) as $propkey) { - if (!(isset($this->fieldsArray[$this->type]['properties'][$propkey]))) { - throw new InvalidArgumentException("Invalid property '$propkey'"); - } + foreach (array_keys($properties) as $propkey) { + if (!(isset($this->fieldsArray[$this->type]['properties'][$propkey]))) { + throw new InvalidArgumentException("Invalid property '$propkey'"); } - $this->properties = array_merge($this->properties, $properties); } + $this->properties = array_merge($this->properties, $properties); - return $this->properties; + return $this; } /** @@ -248,22 +244,18 @@ public function getProperties() /** * Set Field options. * - * @param array $options - * * @return self */ - public function setOptions($options = []) + public function setOptions(array $options = []) { - if (is_array($options)) { - foreach (array_keys($options) as $optionkey) { - if (!(isset($this->fieldsArray[$this->type]['options'][$optionkey])) && substr($optionkey, 0, 1) !== '\\') { - throw new InvalidArgumentException("Invalid option '$optionkey', possible values are " . implode(', ', $this->fieldsArray[$this->type]['options'])); - } + foreach (array_keys($options) as $optionkey) { + if (!(isset($this->fieldsArray[$this->type]['options'][$optionkey])) && substr($optionkey, 0, 1) !== '\\') { + throw new InvalidArgumentException("Invalid option '$optionkey', possible values are " . implode(', ', $this->fieldsArray[$this->type]['options'])); } - $this->options = array_merge($this->options, $options); } + $this->options = array_merge($this->options, $options); - return $this->options; + return $this; } /** @@ -279,13 +271,13 @@ public function getOptions() /** * Set Field text. * - * @param null|string|TextRun $text + * @param null|mixed|string|TextRun $text * * @return null|string|TextRun */ public function setText($text = null) { - if (isset($text)) { + if (null !== $text) { if (is_string($text) || $text instanceof TextRun) { $this->text = $text; } else { diff --git a/src/PhpWord/Element/OLEObject.php b/src/PhpWord/Element/OLEObject.php index 74c31a79ed..8e447873a7 100644 --- a/src/PhpWord/Element/OLEObject.php +++ b/src/PhpWord/Element/OLEObject.php @@ -70,17 +70,16 @@ class OLEObject extends AbstractElement public function __construct($source, $style = null) { $supportedTypes = ['xls', 'doc', 'ppt', 'xlsx', 'docx', 'pptx']; - $pathInfo = pathinfo($source); + $pathInfoExtension = pathinfo($source, PATHINFO_EXTENSION); - if (file_exists($source) && in_array($pathInfo['extension'], $supportedTypes)) { - $ext = $pathInfo['extension']; - if (strlen($ext) == 4 && strtolower(substr($ext, -1)) == 'x') { - $ext = substr($ext, 0, -1); + if (file_exists($source) && in_array($pathInfoExtension, $supportedTypes)) { + if (strlen($pathInfoExtension) == 4 && strtolower(substr($pathInfoExtension, -1)) == 'x') { + $pathInfoExtension = substr($pathInfoExtension, 0, -1); } $this->source = $source; $this->style = $this->setNewStyle(new ImageStyle(), $style, true); - $this->icon = realpath(__DIR__ . "/../resources/{$ext}.png"); + $this->icon = realpath(__DIR__ . "/../resources/{$pathInfoExtension}.png"); return; } diff --git a/src/PhpWord/Element/Section.php b/src/PhpWord/Element/Section.php index cf765792dc..0ae00aa9f6 100644 --- a/src/PhpWord/Element/Section.php +++ b/src/PhpWord/Element/Section.php @@ -75,12 +75,10 @@ public function __construct($sectionCount, $style = null) /** * Set section style. - * - * @param array $style */ - public function setStyle($style = null): void + public function setStyle(?array $style = null): void { - if (null !== $style && is_array($style)) { + if (null !== $style) { $this->style->setStyleByArray($style); } } diff --git a/src/PhpWord/Element/TOC.php b/src/PhpWord/Element/TOC.php index 8f8e71f65a..9e784c75df 100644 --- a/src/PhpWord/Element/TOC.php +++ b/src/PhpWord/Element/TOC.php @@ -59,15 +59,14 @@ class TOC extends AbstractElement * Create a new Table-of-Contents Element. * * @param mixed $fontStyle - * @param array $tocStyle * @param int $minDepth * @param int $maxDepth */ - public function __construct($fontStyle = null, $tocStyle = null, $minDepth = 1, $maxDepth = 9) + public function __construct($fontStyle = null, ?array $tocStyle = null, $minDepth = 1, $maxDepth = 9) { $this->tocStyle = new TOCStyle(); - if (null !== $tocStyle && is_array($tocStyle)) { + if (null !== $tocStyle) { $this->tocStyle->setStyleByArray($tocStyle); } diff --git a/src/PhpWord/Reader/ODText/Content.php b/src/PhpWord/Reader/ODText/Content.php index f555d00654..fff93618d9 100644 --- a/src/PhpWord/Reader/ODText/Content.php +++ b/src/PhpWord/Reader/ODText/Content.php @@ -45,8 +45,6 @@ public function read(PhpWord $phpWord): void $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); - $trackedChanges = []; - $nodes = $xmlReader->getElements('office:body/office:text/*'); $this->section = null; $this->processNodes($nodes, $xmlReader, $phpWord); @@ -186,6 +184,7 @@ public function processNodes(DOMNodeList $nodes, XMLReader $xmlReader, PhpWord $ case 'text:section': // Section // $sectionStyleName = $xmlReader->getAttribute('text:style-name', $listItem); $this->section = $phpWord->addSection(); + /** @var DOMNodeList<DOMElement> $children */ $children = $node->childNodes; $this->processNodes($children, $xmlReader, $phpWord); diff --git a/src/PhpWord/Reader/RTF/Document.php b/src/PhpWord/Reader/RTF/Document.php index 358464a61d..59f0a7dd59 100644 --- a/src/PhpWord/Reader/RTF/Document.php +++ b/src/PhpWord/Reader/RTF/Document.php @@ -31,7 +31,7 @@ * * @since 0.11.0 * - * @SuppressWarnings(PHPMD.UnusedPrivateMethod) + * @SuppressWarnings("PHPMD.UnusedPrivateMethod") */ class Document { diff --git a/src/PhpWord/Reader/Word2007.php b/src/PhpWord/Reader/Word2007.php index a67cd612ed..1b9055754c 100644 --- a/src/PhpWord/Reader/Word2007.php +++ b/src/PhpWord/Reader/Word2007.php @@ -138,8 +138,15 @@ private function readRelationships($docFile) if ($zip->open($docFile) === true) { for ($i = 0; $i < $zip->numFiles; ++$i) { $xmlFile = $zip->getNameIndex($i); + if (!is_string($xmlFile)) { + continue; + } if ((substr($xmlFile, 0, strlen($wordRelsPath))) == $wordRelsPath && (substr($xmlFile, -1)) != '/') { - $docPart = str_replace('.xml.rels', '', str_replace($wordRelsPath, '', $xmlFile)); + $docPart = str_replace( + '.xml.rels', + '', + str_replace($wordRelsPath, '', $xmlFile) + ); $relationships[$docPart] = $this->getRels($docFile, $xmlFile, 'word/'); } } diff --git a/src/PhpWord/Reader/Word2007/Document.php b/src/PhpWord/Reader/Word2007/Document.php index 11e6089dba..89e479ef36 100644 --- a/src/PhpWord/Reader/Word2007/Document.php +++ b/src/PhpWord/Reader/Word2007/Document.php @@ -28,7 +28,7 @@ * * @since 0.10.0 * - * @SuppressWarnings(PHPMD.UnusedPrivateMethod) For readWPNode + * @SuppressWarnings("PHPMD.UnusedPrivateMethod") For readWPNode */ class Document extends AbstractPart { diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 170dc5dff3..6ee6399fd6 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -18,7 +18,6 @@ namespace PhpOffice\PhpWord\Shared; -use DOMAttr; use DOMDocument; use DOMNode; use DOMXPath; @@ -36,7 +35,7 @@ /** * Common Html functions. * - * @SuppressWarnings(PHPMD.UnusedPrivateMethod) For readWPNode + * @SuppressWarnings("PHPMD.UnusedPrivateMethod") For readWPNode */ class Html { @@ -666,14 +665,11 @@ protected static function parseListItem($node, $element, &$styles, $data): void /** * Parse style. * - * @param DOMAttr $attribute - * @param array $styles - * - * @return array + * @param DOMNode $attribute */ - protected static function parseStyle($attribute, $styles) + protected static function parseStyle($attribute, array $styles): array { - $properties = explode(';', trim($attribute->value, " \t\n\r\0\x0B;")); + $properties = explode(';', trim($attribute->nodeValue, " \t\n\r\0\x0B;")); $selectors = []; foreach ($properties as $property) { @@ -684,7 +680,7 @@ protected static function parseStyle($attribute, $styles) return self::parseStyleDeclarations($selectors, $styles); } - protected static function parseStyleDeclarations(array $selectors, array $styles) + protected static function parseStyleDeclarations(array $selectors, array $styles): array { $bidi = ($selectors['direction'] ?? '') === 'rtl'; foreach ($selectors as $property => $value) { diff --git a/src/PhpWord/Shared/ZipArchive.php b/src/PhpWord/Shared/ZipArchive.php index bce7f18e0f..462206c7f5 100644 --- a/src/PhpWord/Shared/ZipArchive.php +++ b/src/PhpWord/Shared/ZipArchive.php @@ -209,7 +209,7 @@ public function extractTo($destination, $entries = null) * * @param string $filename Filename for the file in zip archive * - * @return string $contents File string contents + * @return bool|string $contents File string contents */ public function getFromName($filename) { @@ -245,22 +245,24 @@ public function pclzipAddFile($filename, $localname = null) $filename = $realpathFilename; } - $filenameParts = pathinfo($filename); - $localnameParts = pathinfo($localname); + $filenamePartsBaseName = pathinfo($filename, PATHINFO_BASENAME); + $filenamePartsDirName = pathinfo($filename, PATHINFO_DIRNAME); + $localnamePartsBaseName = pathinfo($localname, PATHINFO_BASENAME); + $localnamePartsDirName = pathinfo($localname, PATHINFO_DIRNAME); // To Rename the file while adding it to the zip we // need to create a temp file with the correct name $tempFile = false; - if ($filenameParts['basename'] != $localnameParts['basename']) { + if ($filenamePartsBaseName != $localnamePartsBaseName) { $tempFile = true; // temp file created - $temppath = $this->tempDir . DIRECTORY_SEPARATOR . $localnameParts['basename']; + $temppath = $this->tempDir . DIRECTORY_SEPARATOR . $localnamePartsBaseName; copy($filename, $temppath); $filename = $temppath; - $filenameParts = pathinfo($temppath); + $filenamePartsDirName = pathinfo($temppath, PATHINFO_DIRNAME); } - $pathRemoved = $filenameParts['dirname']; - $pathAdded = $localnameParts['dirname']; + $pathRemoved = $filenamePartsDirName; + $pathAdded = $localnamePartsDirName; if (!$this->usePclzip) { $pathAdded = $pathAdded . '/' . ltrim(str_replace('\\', '/', substr($filename, strlen($pathRemoved))), '/'); @@ -272,7 +274,7 @@ public function pclzipAddFile($filename, $localname = null) if ($tempFile) { // Remove temp file, if created - unlink($this->tempDir . DIRECTORY_SEPARATOR . $localnameParts['basename']); + unlink($this->tempDir . DIRECTORY_SEPARATOR . $localnamePartsBaseName); } return $res != 0; @@ -290,24 +292,25 @@ public function pclzipAddFromString($localname, $contents) { /** @var PclZip $zip Type hint */ $zip = $this->zip; - $filenameParts = pathinfo($localname); + $filenamePartsBaseName = pathinfo($localname, PATHINFO_BASENAME); + $filenamePartsDirName = pathinfo($localname, PATHINFO_DIRNAME); // Write $contents to a temp file - $handle = fopen($this->tempDir . DIRECTORY_SEPARATOR . $filenameParts['basename'], 'wb'); + $handle = fopen($this->tempDir . DIRECTORY_SEPARATOR . $filenamePartsBaseName, 'wb'); if ($handle) { fwrite($handle, $contents); fclose($handle); } // Add temp file to zip - $filename = $this->tempDir . DIRECTORY_SEPARATOR . $filenameParts['basename']; + $filename = $this->tempDir . DIRECTORY_SEPARATOR . $filenamePartsBaseName; $pathRemoved = $this->tempDir; - $pathAdded = $filenameParts['dirname']; + $pathAdded = $filenamePartsDirName; $res = $zip->add($filename, PCLZIP_OPT_REMOVE_PATH, $pathRemoved, PCLZIP_OPT_ADD_PATH, $pathAdded); // Remove temp file - @unlink($this->tempDir . DIRECTORY_SEPARATOR . $filenameParts['basename']); + @unlink($this->tempDir . DIRECTORY_SEPARATOR . $filenamePartsBaseName); return $res != 0; } @@ -370,7 +373,7 @@ public function pclzipGetFromName($filename) $listIndex = $this->pclzipLocateName($filename); $extracted = $zip->extractByIndex($listIndex, PCLZIP_OPT_EXTRACT_AS_STRING); } - if ((is_array($extracted)) && ($extracted != 0)) { + if (is_array($extracted) && count($extracted) != 0) { $contents = $extracted[0]['content']; } diff --git a/src/PhpWord/Style/Chart.php b/src/PhpWord/Style/Chart.php index 6cffc4d5b0..3773565ce9 100644 --- a/src/PhpWord/Style/Chart.php +++ b/src/PhpWord/Style/Chart.php @@ -456,11 +456,8 @@ public function getValueLabelPosition() * "nextTo" - sets labels next to the value * "low" - sets labels are below the graph * "high" - sets labels above the graph. - * - * @param string - * @param mixed $labelPosition */ - public function setValueLabelPosition($labelPosition) + public function setValueLabelPosition(string $labelPosition) { $enum = ['nextTo', 'low', 'high']; $this->valueLabelPosition = $this->setEnumVal($labelPosition, $enum, $this->valueLabelPosition); diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index 54e4376562..641ed7b41e 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -101,32 +101,28 @@ final class Language extends AbstractStyle /** * Latin Language. * - * @var string + * @var null|string */ private $latin; /** * East Asian Language. * - * @var string + * @var null|string */ private $eastAsia; /** * Complex Script Language. * - * @var string + * @var null|string */ private $bidirectional; /** * Constructor. - * - * @param null|string $latin - * @param null|string $eastAsia - * @param null|string $bidirectional */ - public function __construct($latin = null, $eastAsia = null, $bidirectional = null) + public function __construct(?string $latin = null, ?string $eastAsia = null, ?string $bidirectional = null) { if (!empty($latin)) { $this->setLatin($latin); @@ -144,10 +140,8 @@ public function __construct($latin = null, $eastAsia = null, $bidirectional = nu * * @param string $latin * The value for the latin language - * - * @return self */ - public function setLatin($latin) + public function setLatin(?string $latin): self { $this->latin = $this->validateLocale($latin); @@ -156,10 +150,8 @@ public function setLatin($latin) /** * Get the Latin Language. - * - * @return null|string */ - public function getLatin() + public function getLatin(): ?string { return $this->latin; } diff --git a/src/PhpWord/Style/Numbering.php b/src/PhpWord/Style/Numbering.php index 1ecbe68c83..2b34f2a9bb 100644 --- a/src/PhpWord/Style/Numbering.php +++ b/src/PhpWord/Style/Numbering.php @@ -105,15 +105,13 @@ public function getLevels(): array */ public function setLevels(array $values): self { - if (is_array($values)) { - foreach ($values as $key => $value) { - $numberingLevel = new NumberingLevel(); - if (is_array($value)) { - $numberingLevel->setStyleByArray($value); - $numberingLevel->setLevel($key); - } - $this->levels[$key] = $numberingLevel; + foreach ($values as $key => $value) { + $numberingLevel = new NumberingLevel(); + if (is_array($value)) { + $numberingLevel->setStyleByArray($value); + $numberingLevel->setLevel($key); } + $this->levels[$key] = $numberingLevel; } return $this; diff --git a/src/PhpWord/Style/NumberingLevel.php b/src/PhpWord/Style/NumberingLevel.php index 31ec3738c8..f2505a330d 100644 --- a/src/PhpWord/Style/NumberingLevel.php +++ b/src/PhpWord/Style/NumberingLevel.php @@ -93,7 +93,7 @@ class NumberingLevel extends AbstractStyle /** * Justification, w:lvlJc. * - * @var string, one of PhpOffice\PhpWord\SimpleType\Jc + * @var string one of PhpOffice\PhpWord\SimpleType\Jc */ private $alignment = ''; diff --git a/src/PhpWord/Style/Row.php b/src/PhpWord/Style/Row.php index 31ae3dedc1..749839c4e2 100644 --- a/src/PhpWord/Style/Row.php +++ b/src/PhpWord/Style/Row.php @@ -55,22 +55,16 @@ public function __construct() /** * Is tblHeader. - * - * @return bool */ - public function isTblHeader() + public function isTblHeader(): bool { return $this->tblHeader; } /** * Is tblHeader. - * - * @param bool $value - * - * @return self */ - public function setTblHeader($value = true) + public function setTblHeader(bool $value = true): self { $this->tblHeader = $this->setBoolVal($value, $this->tblHeader); @@ -79,22 +73,16 @@ public function setTblHeader($value = true) /** * Is cantSplit. - * - * @return bool */ - public function isCantSplit() + public function isCantSplit(): bool { return $this->cantSplit; } /** * Is cantSplit. - * - * @param bool $value - * - * @return self */ - public function setCantSplit($value = true) + public function setCantSplit(bool $value = true): self { $this->cantSplit = $this->setBoolVal($value, $this->cantSplit); @@ -103,22 +91,16 @@ public function setCantSplit($value = true) /** * Is exactHeight. - * - * @return bool */ - public function isExactHeight() + public function isExactHeight(): bool { return $this->exactHeight; } /** * Set exactHeight. - * - * @param bool $value - * - * @return self */ - public function setExactHeight($value = true) + public function setExactHeight(bool $value = true): self { $this->exactHeight = $this->setBoolVal($value, $this->exactHeight); diff --git a/src/PhpWord/Style/Table.php b/src/PhpWord/Style/Table.php index 21e8a74823..2510a3fa72 100644 --- a/src/PhpWord/Style/Table.php +++ b/src/PhpWord/Style/Table.php @@ -23,7 +23,6 @@ use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\SimpleType\JcTable; use PhpOffice\PhpWord\SimpleType\TblWidth; -use PhpOffice\PhpWord\Style; class Table extends Border { @@ -136,7 +135,7 @@ class Table extends Border /** * @var null|float|int cell spacing value */ - protected $cellSpacing; + private $cellSpacing; /** * @var string Table Layout @@ -171,21 +170,29 @@ class Table extends Border /** * Create new table style. - * - * @param mixed $tableStyle - * @param mixed $firstRowStyle */ - public function __construct($tableStyle = null, $firstRowStyle = null) + public function __construct(?array $tableStyle = null, ?array $firstRowStyle = null) { // Clone first row from table style, but with certain properties disabled - if ($firstRowStyle !== null && is_array($firstRowStyle)) { + if ($firstRowStyle !== null) { $this->firstRowStyle = clone $this; $this->firstRowStyle->isFirstRow = true; - unset($this->firstRowStyle->firstRowStyle, $this->firstRowStyle->borderInsideHSize, $this->firstRowStyle->borderInsideHColor, $this->firstRowStyle->borderInsideVSize, $this->firstRowStyle->borderInsideVColor, $this->firstRowStyle->cellMarginTop, $this->firstRowStyle->cellMarginLeft, $this->firstRowStyle->cellMarginRight, $this->firstRowStyle->cellMarginBottom, $this->firstRowStyle->cellSpacing); + unset( + $this->firstRowStyle->firstRowStyle, + $this->firstRowStyle->borderInsideHSize, + $this->firstRowStyle->borderInsideHColor, + $this->firstRowStyle->borderInsideVSize, + $this->firstRowStyle->borderInsideVColor, + $this->firstRowStyle->cellMarginTop, + $this->firstRowStyle->cellMarginLeft, + $this->firstRowStyle->cellMarginRight, + $this->firstRowStyle->cellMarginBottom, + $this->firstRowStyle->cellSpacing + ); $this->firstRowStyle->setStyleByArray($firstRowStyle); } - if ($tableStyle !== null && is_array($tableStyle)) { + if ($tableStyle !== null) { $this->setStyleByArray($tableStyle); } } @@ -193,9 +200,11 @@ public function __construct($tableStyle = null, $firstRowStyle = null) /** * @param null|float|int $cellSpacing */ - public function setCellSpacing($cellSpacing = null): void + public function setCellSpacing($cellSpacing = null): self { $this->cellSpacing = $cellSpacing; + + return $this; } /** diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 7dd99af291..073393ffc4 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -133,7 +133,10 @@ public function __construct($documentTemplate) $this->tempDocumentMainPart = $this->readPartWithRels($this->getMainPartName()); $this->tempDocumentSettingsPart = $this->readPartWithRels($this->getSettingsPartName()); - $this->tempDocumentContentTypes = $this->zipClass->getFromName($this->getDocumentContentTypesName()); + $tempDocumentContentTypes = $this->zipClass->getFromName($this->getDocumentContentTypesName()); + if (is_string($tempDocumentContentTypes)) { + $this->tempDocumentContentTypes = $tempDocumentContentTypes; + } } public function __destruct() @@ -316,8 +319,8 @@ public function setComplexBlock($search, Element\AbstractElement $complexType): } /** - * @param mixed $search - * @param mixed $replace + * @param array<string>|string $search + * @param null|array<string>|bool|float|int|string $replace * @param int $limit */ public function setValue($search, $replace, $limit = self::MAXIMUM_REPLACEMENTS_DEFAULT): void @@ -337,7 +340,7 @@ public function setValue($search, $replace, $limit = self::MAXIMUM_REPLACEMENTS_ } unset($item); } else { - $replace = static::ensureUtf8Encoded($replace); + $replace = static::ensureUtf8Encoded(null === $replace ? null : (string) $replace); } if (Settings::isOutputEscapingEnabled()) { @@ -678,7 +681,7 @@ public function setImageValue($search, $replace, $limit = self::MAXIMUM_REPLACEM foreach ($searchReplace as $searchString => $replaceImage) { $varsToReplace = array_filter($partVariables, function ($partVar) use ($searchString) { - return ($partVar == $searchString) || preg_match('/^' . preg_quote($searchString) . ':/', $partVar); + return ($partVar == $searchString) || preg_match('/^' . preg_quote($searchString, '/') . ':/', $partVar); }); foreach ($varsToReplace as $varNameWithArgs) { @@ -697,7 +700,7 @@ public function setImageValue($search, $replace, $limit = self::MAXIMUM_REPLACEM // replace variable $varNameWithArgsFixed = static::ensureMacroCompleted($varNameWithArgs); $matches = []; - if (preg_match('/(<[^<]+>)([^<]*)(' . preg_quote($varNameWithArgsFixed) . ')([^>]*)(<[^>]+>)/Uu', $partContent, $matches)) { + if (preg_match('/(<[^<]+>)([^<]*)(' . preg_quote($varNameWithArgsFixed, '/') . ')([^>]*)(<[^>]+>)/Uu', $partContent, $matches)) { $wholeTag = $matches[0]; array_shift($matches); [$openTag, $prefix, , $postfix, $closeTag] = $matches; @@ -1078,12 +1081,12 @@ function ($match) { /** * Find and replace macros in the given XML section. * - * @param mixed $search - * @param mixed $replace + * @param array<string>|string $search + * @param array<string>|string $replace * @param array<int, string>|string $documentPartXML * @param int $limit * - * @return string + * @return ($documentPartXML is string ? string : array<string>) */ protected function setValueForPart($search, $replace, $documentPartXML, $limit) { diff --git a/src/PhpWord/Writer/EPub3/Part/ContentXhtml.php b/src/PhpWord/Writer/EPub3/Part/ContentXhtml.php index 3ebd82638e..74143a30ef 100644 --- a/src/PhpWord/Writer/EPub3/Part/ContentXhtml.php +++ b/src/PhpWord/Writer/EPub3/Part/ContentXhtml.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpWord\Writer\EPub3\Part; +use PhpOffice\PhpWord\Element\AbstractElement; use PhpOffice\PhpWord\Element\Text; use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\PhpWord; @@ -91,14 +92,14 @@ public function write(): string return $xmlWriter->outputMemory(true); } - protected function writeTextElement(\PhpOffice\PhpWord\Element\AbstractElement $textElement, XMLWriter $xmlWriter): void + protected function writeTextElement(AbstractElement $textElement, XMLWriter $xmlWriter): void { if ($textElement instanceof Text) { $text = $textElement->getText(); if ($text !== null) { $xmlWriter->text((string) $text); } - } elseif (is_object($textElement) && method_exists($textElement, 'getText')) { + } elseif (method_exists($textElement, 'getText')) { $text = $textElement->getText(); if ($text instanceof TextRun) { $this->writeTextRun($text, $xmlWriter); diff --git a/src/PhpWord/Writer/HTML.php b/src/PhpWord/Writer/HTML.php index 41229b45d5..acaa3c4800 100644 --- a/src/PhpWord/Writer/HTML.php +++ b/src/PhpWord/Writer/HTML.php @@ -21,7 +21,7 @@ use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Shared\Validate; -use PhpOffice\PhpWord\Style\Font; +use PhpOffice\PhpWord\Writer\HTML\Part\AbstractPart; /** * HTML writer. @@ -76,9 +76,9 @@ public function __construct(?PhpWord $phpWord = null) $this->parts = ['Head', 'Body']; foreach ($this->parts as $partName) { - $partClass = 'PhpOffice\\PhpWord\\Writer\\HTML\\Part\\' . $partName; + $partClass = self::class . '\\Part\\' . $partName; if (class_exists($partClass)) { - /** @var HTML\Part\AbstractPart $part Type hint */ + /** @var AbstractPart $part Type hint */ $part = new $partClass(); $part->setParentWriter($this); $this->writerParts[strtolower($partName)] = $part; diff --git a/src/PhpWord/Writer/HTML/Element/Ruby.php b/src/PhpWord/Writer/HTML/Element/Ruby.php index b3ab13c35e..5648d85e2f 100644 --- a/src/PhpWord/Writer/HTML/Element/Ruby.php +++ b/src/PhpWord/Writer/HTML/Element/Ruby.php @@ -100,10 +100,6 @@ private function getPropertyCssForRtTag(RubyProperties $properties): string private function getParagraphStyleForTextRun(TextRun $textRun, string $extraCSS): string { $style = ''; - if (!method_exists($textRun, 'getParagraphStyle')) { - return $style; - } - $paragraphStyle = $textRun->getParagraphStyle(); $pStyleIsObject = ($paragraphStyle instanceof Paragraph); if ($pStyleIsObject) { diff --git a/src/PhpWord/Writer/HTML/Style/Table.php b/src/PhpWord/Writer/HTML/Style/Table.php index a59d1cdba4..6d3e43e812 100644 --- a/src/PhpWord/Writer/HTML/Style/Table.php +++ b/src/PhpWord/Writer/HTML/Style/Table.php @@ -35,19 +35,19 @@ public function write() } $css = []; - if (is_object($style) && method_exists($style, 'getLayout')) { + if (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 (method_exists($style, 'isBidiVisual')) { if ($style->isBidiVisual()) { $css['direction'] = 'rtl'; } } - if (is_object($style) && method_exists($style, 'getVAlign')) { + if (method_exists($style, 'getVAlign')) { $css['vertical-align'] = $style->getVAlign(); } diff --git a/src/PhpWord/Writer/ODText/Element/Field.php b/src/PhpWord/Writer/ODText/Element/Field.php index 6b54807869..2f81eb3f3d 100644 --- a/src/PhpWord/Writer/ODText/Element/Field.php +++ b/src/PhpWord/Writer/ODText/Element/Field.php @@ -57,12 +57,12 @@ private function writeDefault(\PhpOffice\PhpWord\Element\Field $element, $type): $xmlWriter = $this->getXmlWriter(); $xmlWriter->startElement('text:span'); - if (method_exists($element, 'getFontStyle')) { - $fstyle = $element->getFontStyle(); - if (is_string($fstyle)) { - $xmlWriter->writeAttribute('text:style-name', $fstyle); - } + + $fstyle = $element->getFontStyle(); + if (is_string($fstyle)) { + $xmlWriter->writeAttribute('text:style-name', $fstyle); } + switch ($type) { case 'date': $xmlWriter->startElement('text:date'); diff --git a/src/PhpWord/Writer/ODText/Part/Content.php b/src/PhpWord/Writer/ODText/Part/Content.php index de82ed96d1..b4958e84e6 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -106,7 +106,8 @@ public function write() $xmlWriter->writeElement('dc:date', $trackedChange->getDate()->format('Y-m-d\TH:i:s\Z')); } $xmlWriter->endElement(); // office:change-info - if ($trackedChange->getChangeType() == TrackChange::DELETED) { + if ($trackedChange->getChangeType() == TrackChange::DELETED && method_exists($trackedElement, 'getText')) { + // @phpstan-ignore-next-line $xmlWriter->writeElement('text:p', $trackedElement->getText()); } diff --git a/src/PhpWord/Writer/ODText/Style/Font.php b/src/PhpWord/Writer/ODText/Style/Font.php index 85720f0274..95582ec48b 100644 --- a/src/PhpWord/Writer/ODText/Style/Font.php +++ b/src/PhpWord/Writer/ODText/Style/Font.php @@ -36,7 +36,7 @@ public function write(): void } $xmlWriter = $this->getXmlWriter(); - $stylep = (method_exists($style, 'getParagraph')) ? $style->getParagraph() : null; + $stylep = $style->getParagraph(); if ($stylep instanceof \PhpOffice\PhpWord\Style\Paragraph) { $temp1 = clone $stylep; $temp1->setStyleName($style->getStyleName()); diff --git a/src/PhpWord/Writer/ODText/Style/Paragraph.php b/src/PhpWord/Writer/ODText/Style/Paragraph.php index 99963bd4a3..ca22a0934c 100644 --- a/src/PhpWord/Writer/ODText/Style/Paragraph.php +++ b/src/PhpWord/Writer/ODText/Style/Paragraph.php @@ -76,9 +76,7 @@ public function write(): void $psm = 'Heading_' . substr($styleName, 2); $stylep = Style::getStyle($psm); if ($stylep instanceof Style\Font) { - if (method_exists($stylep, 'getParagraph')) { - $stylep = $stylep->getParagraph(); - } + $stylep = $stylep->getParagraph(); } if ($stylep instanceof Style\Paragraph) { if ($stylep->hasPageBreakBefore()) { diff --git a/src/PhpWord/Writer/RTF/Part/Document.php b/src/PhpWord/Writer/RTF/Part/Document.php index bd659c6794..484393477d 100644 --- a/src/PhpWord/Writer/RTF/Part/Document.php +++ b/src/PhpWord/Writer/RTF/Part/Document.php @@ -55,27 +55,33 @@ public function write() private function writeInfo() { $docProps = $this->getParentWriter()->getPhpWord()->getDocInfo(); - $properties = ['title', 'subject', 'category', 'keywords', 'comment', - 'author', 'operator', 'creatim', 'revtim', 'company', 'manager', ]; - $mapping = [ + $properties = [ + 'title' => 'title', + 'subject' => 'subject', + 'category' => 'category', + 'keywords' => 'keywords', 'comment' => 'description', 'author' => 'creator', 'operator' => 'lastModifiedBy', 'creatim' => 'created', - 'revtim' => 'modified', ]; + 'revtim' => 'modified', + 'company' => 'company', + 'manager' => 'manager', + ]; $dateFields = ['creatim', 'revtim']; $content = ''; $content .= '{'; $content .= '\info'; - foreach ($properties as $property) { - $method = 'get' . ($mapping[$property] ?? $property); + foreach ($properties as $property => $propertyMethod) { + $method = 'get' . $propertyMethod; + + $value = $docProps->$method(); if (!in_array($property, $dateFields) && Settings::isOutputEscapingEnabled()) { - $value = $this->escaper->escape($docProps->$method()); - } else { - $value = $docProps->$method(); + $value = $this->escaper->escape($value); } + $value = in_array($property, $dateFields) ? $this->getDateValue($value) : $value; $content .= "{\\{$property} {$value}}"; } diff --git a/src/PhpWord/Writer/RTF/Style/Border.php b/src/PhpWord/Writer/RTF/Style/Border.php index 8f3024493c..c8dc943579 100644 --- a/src/PhpWord/Writer/RTF/Style/Border.php +++ b/src/PhpWord/Writer/RTF/Style/Border.php @@ -85,7 +85,7 @@ private function writeSide($side, $width, $color = '') if ($rtfWriter !== null) { $colorTable = $rtfWriter->getColorTable(); $index = array_search($color, $colorTable); - if ($index !== false && $colorIndex !== null) { + if ($index !== false) { $colorIndex = $index + 1; } } diff --git a/src/PhpWord/Writer/Word2007.php b/src/PhpWord/Writer/Word2007.php index e54bfa8ad2..9702c210bd 100644 --- a/src/PhpWord/Writer/Word2007.php +++ b/src/PhpWord/Writer/Word2007.php @@ -222,7 +222,7 @@ private function addNotes(ZipArchive $zip, &$rId, $noteType = 'footnote'): void $phpWord = $this->getPhpWord(); $noteType = ($noteType == 'endnote') ? 'endnote' : 'footnote'; $partName = "{$noteType}s"; - $method = 'get' . $partName; + $method = 'get' . ucfirst($partName); $collection = $phpWord->$method(); // Add footnotes media files, relations, and contents diff --git a/src/PhpWord/Writer/Word2007/Element/FormField.php b/src/PhpWord/Writer/Word2007/Element/FormField.php index c5d59a4497..1e58f58e55 100644 --- a/src/PhpWord/Writer/Word2007/Element/FormField.php +++ b/src/PhpWord/Writer/Word2007/Element/FormField.php @@ -29,7 +29,7 @@ * @since 0.12.0 * @see http://www.datypic.com/sc/ooxml/t-w_CT_FFData.html * - * @SuppressWarnings(PHPMD.UnusedPrivateMethod) + * @SuppressWarnings("PHPMD.UnusedPrivateMethod") */ class FormField extends Text { diff --git a/src/PhpWord/Writer/Word2007/Element/SDT.php b/src/PhpWord/Writer/Word2007/Element/SDT.php index 950c293776..dfe5ca9bca 100644 --- a/src/PhpWord/Writer/Word2007/Element/SDT.php +++ b/src/PhpWord/Writer/Word2007/Element/SDT.php @@ -27,7 +27,7 @@ * @since 0.12.0 * @see http://www.datypic.com/sc/ooxml/t-w_CT_SdtBlock.html * - * @SuppressWarnings(PHPMD.UnusedPrivateMethod) + * @SuppressWarnings("PHPMD.UnusedPrivateMethod") */ class SDT extends Text { diff --git a/src/PhpWord/Writer/Word2007/Element/Shape.php b/src/PhpWord/Writer/Word2007/Element/Shape.php index 653c31809a..0af2831ba6 100644 --- a/src/PhpWord/Writer/Word2007/Element/Shape.php +++ b/src/PhpWord/Writer/Word2007/Element/Shape.php @@ -28,7 +28,7 @@ * * @since 0.12.0 * - * @SuppressWarnings(PHPMD.UnusedPrivateMethod) + * @SuppressWarnings("PHPMD.UnusedPrivateMethod") */ class Shape extends AbstractElement { diff --git a/src/PhpWord/Writer/Word2007/Part/Numbering.php b/src/PhpWord/Writer/Word2007/Part/Numbering.php index ca29cd01d5..2dee7c2b1e 100644 --- a/src/PhpWord/Writer/Word2007/Part/Numbering.php +++ b/src/PhpWord/Writer/Word2007/Part/Numbering.php @@ -69,10 +69,8 @@ public function write() $xmlWriter->writeAttribute('w:val', $style->getType()); $xmlWriter->endElement(); // w:multiLevelType - if (is_array($levels)) { - foreach ($levels as $level) { - $this->writeLevel($xmlWriter, $level); - } + foreach ($levels as $level) { + $this->writeLevel($xmlWriter, $level); } $xmlWriter->endElement(); // w:abstractNum } diff --git a/src/PhpWord/Writer/Word2007/Part/Styles.php b/src/PhpWord/Writer/Word2007/Part/Styles.php index edf0314cc2..0ed9d6b6fb 100644 --- a/src/PhpWord/Writer/Word2007/Part/Styles.php +++ b/src/PhpWord/Writer/Word2007/Part/Styles.php @@ -32,7 +32,7 @@ * * @todo Do something with the numbering style introduced in 0.10.0 * - * @SuppressWarnings(PHPMD.UnusedPrivateMethod) For writeFontStyle, writeParagraphStyle, and writeTableStyle + * @SuppressWarnings("PHPMD.UnusedPrivateMethod") For writeFontStyle, writeParagraphStyle, and writeTableStyle */ class Styles extends AbstractPart { diff --git a/src/PhpWord/Writer/Word2007/Style/Table.php b/src/PhpWord/Writer/Word2007/Style/Table.php index 446fc3b1a4..711f3ecde7 100644 --- a/src/PhpWord/Writer/Word2007/Style/Table.php +++ b/src/PhpWord/Writer/Word2007/Style/Table.php @@ -151,7 +151,7 @@ private function writeBorder(XMLWriter $xmlWriter, TableStyle $style): void * * @param string $elementName * @param string $unit - * @param float|int $width + * @param null|float|int $width */ private function writeTblWidth(XMLWriter $xmlWriter, $elementName, $unit, $width = null): void { @@ -159,7 +159,7 @@ private function writeTblWidth(XMLWriter $xmlWriter, $elementName, $unit, $width return; } $xmlWriter->startElement($elementName); - $xmlWriter->writeAttributeIf(null !== $width, 'w:w', $width); + $xmlWriter->writeAttribute('w:w', $width); $xmlWriter->writeAttribute('w:type', $unit); $xmlWriter->endElement(); } diff --git a/tests/PhpWordTests/ComplexType/RubyPropertiesTest.php b/tests/PhpWordTests/ComplexType/RubyPropertiesTest.php index 6d16ebb21d..62bc0b0739 100644 --- a/tests/PhpWordTests/ComplexType/RubyPropertiesTest.php +++ b/tests/PhpWordTests/ComplexType/RubyPropertiesTest.php @@ -34,15 +34,14 @@ class RubyPropertiesTest extends \PHPUnit\Framework\TestCase public function testConstruct(): void { $properties = new RubyProperties(); - self::assertInstanceOf('PhpOffice\\PhpWord\\ComplexType\\RubyProperties', $properties); self::assertIsString($properties->getAlignment()); - self::assertTrue($properties->getAlignment() !== '' && $properties->getAlignment() !== null); + self::assertNotEmpty($properties->getAlignment()); self::assertIsFloat($properties->getFontFaceSize()); self::assertIsFloat($properties->getFontPointsAboveBaseText()); self::assertIsFloat($properties->getFontSizeForBaseText()); self::assertIsString($properties->getLanguageId()); - self::assertTrue($properties->getLanguageId() !== '' && $properties->getLanguageId() !== null); + self::assertTrue($properties->getLanguageId() !== ''); } /** @@ -52,7 +51,7 @@ public function testAlignment(): void { $properties = new RubyProperties(); self::assertIsString($properties->getAlignment()); - self::assertTrue($properties->getAlignment() !== '' && $properties->getAlignment() !== null); + self::assertNotEmpty($properties->getAlignment()); $properties->setAlignment(RubyProperties::ALIGNMENT_RIGHT_VERTICAL); self::assertEquals(RubyProperties::ALIGNMENT_RIGHT_VERTICAL, $properties->getAlignment()); } @@ -133,7 +132,7 @@ public function testLanguageId(): void { $properties = new RubyProperties(); - self::assertTrue($properties->getLanguageId() !== '' && $properties->getLanguageId() !== null); + self::assertNotEmpty($properties->getLanguageId()); $properties->setLanguageId('en-US'); self::assertIsString($properties->getLanguageId()); self::assertEquals('en-US', $properties->getLanguageId()); diff --git a/tests/PhpWordTests/Element/AbstractElementTest.php b/tests/PhpWordTests/Element/AbstractElementTest.php index 307225b8f4..9ce05750b8 100644 --- a/tests/PhpWordTests/Element/AbstractElementTest.php +++ b/tests/PhpWordTests/Element/AbstractElementTest.php @@ -30,6 +30,7 @@ class AbstractElementTest extends \PHPUnit\Framework\TestCase */ public function testElementIndex(): void { + // @phpstan-ignore-next-line if (method_exists($this, 'getMockForAbstractClass')) { $stub = $this->getMockForAbstractClass(AbstractElement::class); } else { @@ -47,6 +48,7 @@ public function testElementIndex(): void */ public function testElementId(): void { + // @phpstan-ignore-next-line if (method_exists($this, 'getMockForAbstractClass')) { $stub = $this->getMockForAbstractClass(AbstractElement::class); } else { diff --git a/tests/PhpWordTests/Element/BookmarkTest.php b/tests/PhpWordTests/Element/BookmarkTest.php index 87abf971e5..097166736f 100644 --- a/tests/PhpWordTests/Element/BookmarkTest.php +++ b/tests/PhpWordTests/Element/BookmarkTest.php @@ -35,7 +35,6 @@ public function testConstruct(): void $bookmarkName = 'test'; $oBookmark = new Bookmark($bookmarkName); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Bookmark', $oBookmark); self::assertEquals($bookmarkName, $oBookmark->getName()); } } diff --git a/tests/PhpWordTests/Element/CellTest.php b/tests/PhpWordTests/Element/CellTest.php index 919d627bfb..2fedcafc24 100644 --- a/tests/PhpWordTests/Element/CellTest.php +++ b/tests/PhpWordTests/Element/CellTest.php @@ -36,7 +36,6 @@ public function testConstruct(): void { $oCell = new Cell(); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Cell', $oCell); self::assertNull($oCell->getWidth()); } diff --git a/tests/PhpWordTests/Element/CheckBoxTest.php b/tests/PhpWordTests/Element/CheckBoxTest.php index 761cfba649..fbdbf36aa3 100644 --- a/tests/PhpWordTests/Element/CheckBoxTest.php +++ b/tests/PhpWordTests/Element/CheckBoxTest.php @@ -36,7 +36,6 @@ public function testConstruct(): void { $oCheckBox = new CheckBox(); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\CheckBox', $oCheckBox); self::assertNull($oCheckBox->getText()); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Font', $oCheckBox->getFontStyle()); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $oCheckBox->getParagraphStyle()); diff --git a/tests/PhpWordTests/Element/CommentTest.php b/tests/PhpWordTests/Element/CommentTest.php index c887362cbc..f76316d890 100644 --- a/tests/PhpWordTests/Element/CommentTest.php +++ b/tests/PhpWordTests/Element/CommentTest.php @@ -45,7 +45,6 @@ public function testConstructDefault(): void $oComment->setStartElement($oText); $oComment->setEndElement($oText); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Comment', $oComment); self::assertEquals($author, $oComment->getAuthor()); self::assertEquals($date, $oComment->getDate()); self::assertEquals($initials, $oComment->getInitials()); diff --git a/tests/PhpWordTests/Element/FieldTest.php b/tests/PhpWordTests/Element/FieldTest.php index f3accf8789..f624e9294d 100644 --- a/tests/PhpWordTests/Element/FieldTest.php +++ b/tests/PhpWordTests/Element/FieldTest.php @@ -29,16 +29,6 @@ */ class FieldTest extends \PHPUnit\Framework\TestCase { - /** - * New instance. - */ - public function testConstructNull(): void - { - $oField = new Field(); - - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Field', $oField); - } - /** * New instance with type. */ @@ -46,7 +36,6 @@ public function testConstructWithType(): void { $oField = new Field('DATE'); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Field', $oField); self::assertEquals('DATE', $oField->getType()); } @@ -57,7 +46,6 @@ public function testConstructWithTypeProperties(): void { $oField = new Field('DATE', ['dateformat' => 'd-M-yyyy']); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Field', $oField); self::assertEquals('DATE', $oField->getType()); self::assertEquals(['dateformat' => 'd-M-yyyy'], $oField->getProperties()); } @@ -69,7 +57,6 @@ public function testConstructWithTypePropertiesOptions(): void { $oField = new Field('DATE', ['dateformat' => 'd-M-yyyy'], ['SakaEraCalendar', 'PreserveFormat']); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Field', $oField); self::assertEquals('DATE', $oField->getType()); self::assertEquals(['dateformat' => 'd-M-yyyy'], $oField->getProperties()); self::assertEquals(['SakaEraCalendar', 'PreserveFormat'], $oField->getOptions()); @@ -82,7 +69,6 @@ public function testConstructWithTypePropertiesOptionsText(): void { $oField = new Field('XE', [], ['Bold', 'Italic'], 'FieldValue'); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Field', $oField); self::assertEquals('XE', $oField->getType()); self::assertEquals([], $oField->getProperties()); self::assertEquals(['Bold', 'Italic'], $oField->getOptions()); @@ -99,7 +85,6 @@ public function testConstructWithTypePropertiesOptionsTextAsTextRun(): void $oField = new Field('XE', [], ['Bold', 'Italic'], $textRun); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Field', $oField); self::assertEquals('XE', $oField->getType()); self::assertEquals([], $oField->getProperties()); self::assertEquals(['Bold', 'Italic'], $oField->getOptions()); @@ -110,7 +95,6 @@ public function testConstructWithOptionValue(): void { $oField = new Field('INDEX', [], ['\\c "3" \\h "A"']); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Field', $oField); self::assertEquals('INDEX', $oField->getType()); self::assertEquals([], $oField->getProperties()); self::assertEquals(['\\c "3" \\h "A"'], $oField->getOptions()); diff --git a/tests/PhpWordTests/Element/FooterTest.php b/tests/PhpWordTests/Element/FooterTest.php index e167204f17..f97b159cb9 100644 --- a/tests/PhpWordTests/Element/FooterTest.php +++ b/tests/PhpWordTests/Element/FooterTest.php @@ -36,7 +36,6 @@ public function testConstruct(): void $iVal = mt_rand(1, 1000); $oFooter = new Footer($iVal); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Footer', $oFooter); self::assertEquals($iVal, $oFooter->getSectionId()); } diff --git a/tests/PhpWordTests/Element/FootnoteTest.php b/tests/PhpWordTests/Element/FootnoteTest.php index cd64d6ddf0..c6297cfc32 100644 --- a/tests/PhpWordTests/Element/FootnoteTest.php +++ b/tests/PhpWordTests/Element/FootnoteTest.php @@ -34,7 +34,6 @@ public function testConstruct(): void { $oFootnote = new Footnote(); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Footnote', $oFootnote); self::assertCount(0, $oFootnote->getElements()); self::assertNull($oFootnote->getParagraphStyle()); } diff --git a/tests/PhpWordTests/Element/FormulaTest.php b/tests/PhpWordTests/Element/FormulaTest.php index 0eb2805d0b..dcb730e9cc 100644 --- a/tests/PhpWordTests/Element/FormulaTest.php +++ b/tests/PhpWordTests/Element/FormulaTest.php @@ -30,16 +30,6 @@ */ class FormulaTest extends AbstractWebServerEmbedded { - /** - * @covers \PhpOffice\PhpWord\Element\Formula::__construct - */ - public function testConstruct(): void - { - $element = new Formula(new Math()); - - self::assertInstanceOf(Formula::class, $element); - } - /** * @covers \PhpOffice\PhpWord\Element\Formula::getMath * @covers \PhpOffice\PhpWord\Element\Formula::setMath @@ -54,11 +44,10 @@ public function testMath(): void $element = new Formula(new Math()); - self::assertInstanceOf(Formula::class, $element); self::assertEquals(new Math(), $element->getMath()); self::assertNotEquals($math, $element->getMath()); - self::assertInstanceOf(Formula::class, $element->setMath($math)); + $element->setMath($math); self::assertNotEquals(new Math(), $element->getMath()); self::assertEquals($math, $element->getMath()); } diff --git a/tests/PhpWordTests/Element/HeaderTest.php b/tests/PhpWordTests/Element/HeaderTest.php index 24b7dd32f9..6d659dbd7c 100644 --- a/tests/PhpWordTests/Element/HeaderTest.php +++ b/tests/PhpWordTests/Element/HeaderTest.php @@ -37,7 +37,6 @@ public function testConstructDefault(): void $iVal = mt_rand(1, 1000); $oHeader = new Header($iVal); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Header', $oHeader); self::assertEquals($iVal, $oHeader->getSectionId()); self::assertEquals(Header::AUTO, $oHeader->getType()); } diff --git a/tests/PhpWordTests/Element/ImageTest.php b/tests/PhpWordTests/Element/ImageTest.php index 86b6b77c58..f56b3da8a9 100644 --- a/tests/PhpWordTests/Element/ImageTest.php +++ b/tests/PhpWordTests/Element/ImageTest.php @@ -35,7 +35,6 @@ public function testConstruct(): void $src = __DIR__ . '/../_files/images/firefox.png'; $oImage = new Image($src); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $oImage); self::assertEquals($src, $oImage->getSource()); self::assertEquals(md5($src), $oImage->getMediaId()); self::assertFalse($oImage->isWatermark()); @@ -72,7 +71,6 @@ public function testImages($source, $type, $extension, $createFunction, $imageFu $nam = ucfirst((string) strtok($source, '.')); $source = __DIR__ . "/../_files/images/{$source}"; $image = new Image($source, null, null, $nam); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $image); self::assertEquals($source, $image->getSource()); self::assertEquals($nam, $image->getName()); self::assertEquals(md5($source), $image->getMediaId()); @@ -129,7 +127,7 @@ public function testInvalidImagePhp(): void { $this->expectException(\PhpOffice\PhpWord\Exception\InvalidImageException::class); $object = new Image('test.php'); - $object->getSource(); + $source = $object->getSource(); } /** @@ -147,7 +145,7 @@ public function testUnsupportedImage(): void ]; stream_context_set_default($arrContextOptions); $object = new Image(self::getRemoteBmpImageUrl()); - $object->getSource(); + $source = $object->getSource(); } /** @@ -204,7 +202,6 @@ public function testConstructFromString(): void $source = file_get_contents(__DIR__ . '/../_files/images/earth.jpg'); $image = new Image($source); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $image); self::assertEquals($source, $image->getSource()); self::assertEquals(md5((string) $source), $image->getMediaId()); self::assertEquals('image/jpeg', $image->getImageType()); @@ -226,7 +223,6 @@ public function testConstructFromGd(): void $source = self::getRemoteImageUrl(); $image = new Image($source); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $image); self::assertEquals($source, $image->getSource()); self::assertEquals(md5($source), $image->getMediaId()); self::assertEquals('image/png', $image->getImageType()); @@ -247,6 +243,6 @@ public function testInvalidImageString(): void { $this->expectException(\PhpOffice\PhpWord\Exception\InvalidImageException::class); $object = new Image('this_is-a_non_valid_image'); - $object->getSource(); + $source = $object->getSource(); } } diff --git a/tests/PhpWordTests/Element/LineTest.php b/tests/PhpWordTests/Element/LineTest.php index 98298fc76c..f4a39b38d1 100644 --- a/tests/PhpWordTests/Element/LineTest.php +++ b/tests/PhpWordTests/Element/LineTest.php @@ -36,7 +36,6 @@ public function testConstruct(): void { $oLine = new Line(); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Line', $oLine); self::assertNull($oLine->getStyle()); } diff --git a/tests/PhpWordTests/Element/LinkTest.php b/tests/PhpWordTests/Element/LinkTest.php index 6a87b308c1..5b5c6f77bf 100644 --- a/tests/PhpWordTests/Element/LinkTest.php +++ b/tests/PhpWordTests/Element/LinkTest.php @@ -37,7 +37,6 @@ public function testConstructDefault(): void { $oLink = new Link('https://github.com/PHPOffice/PHPWord'); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Link', $oLink); self::assertEquals('https://github.com/PHPOffice/PHPWord', $oLink->getSource()); self::assertEquals($oLink->getSource(), $oLink->getText()); self::assertNull($oLink->getFontStyle()); @@ -56,7 +55,6 @@ public function testConstructWithParamsArray(): void ['marginLeft' => 600, 'marginRight' => 600, 'marginTop' => 600, 'marginBottom' => 600] ); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Link', $oLink); self::assertEquals('https://github.com/PHPOffice/PHPWord', $oLink->getSource()); self::assertEquals('PHPWord on GitHub', $oLink->getText()); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Font', $oLink->getFontStyle()); diff --git a/tests/PhpWordTests/Element/ListItemRunTest.php b/tests/PhpWordTests/Element/ListItemRunTest.php index 633b8c3e26..69b5f990b0 100644 --- a/tests/PhpWordTests/Element/ListItemRunTest.php +++ b/tests/PhpWordTests/Element/ListItemRunTest.php @@ -34,7 +34,6 @@ public function testConstruct(): void { $oListItemRun = new ListItemRun(); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\ListItemRun', $oListItemRun); self::assertCount(0, $oListItemRun->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $oListItemRun->getParagraphStyle()); } @@ -46,7 +45,6 @@ public function testConstructString(): void { $oListItemRun = new ListItemRun(0, null, 'pStyle'); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\ListItemRun', $oListItemRun); self::assertCount(0, $oListItemRun->getElements()); self::assertEquals('pStyle', $oListItemRun->getParagraphStyle()); } @@ -58,7 +56,6 @@ public function testConstructListString(): void { $oListItemRun = new ListItemRun(0, 'numberingStyle'); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\ListItemRun', $oListItemRun); self::assertCount(0, $oListItemRun->getElements()); } @@ -69,7 +66,6 @@ public function testConstructArray(): void { $oListItemRun = new ListItemRun(0, null, ['spacing' => 100]); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\ListItemRun', $oListItemRun); self::assertCount(0, $oListItemRun->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $oListItemRun->getParagraphStyle()); } diff --git a/tests/PhpWordTests/Element/ObjectTest.php b/tests/PhpWordTests/Element/ObjectTest.php index 8ad856732b..2ef05567bc 100644 --- a/tests/PhpWordTests/Element/ObjectTest.php +++ b/tests/PhpWordTests/Element/ObjectTest.php @@ -37,7 +37,6 @@ public function testConstructWithSupportedFiles(): void $src = __DIR__ . '/../_files/documents/reader.docx'; $oObject = new OLEObject($src); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\OLEObject', $oObject); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Image', $oObject->getStyle()); self::assertEquals($src, $oObject->getSource()); } @@ -50,7 +49,6 @@ public function testConstructWithSupportedFilesLong(): void $src = __DIR__ . '/../_files/documents/sheet.xls'; $oObject = new OLEObject($src); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\OLEObject', $oObject); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Image', $oObject->getStyle()); self::assertEquals($src, $oObject->getSource()); } @@ -63,7 +61,7 @@ public function testConstructWithNotSupportedFiles(): void $this->expectException(\PhpOffice\PhpWord\Exception\InvalidObjectException::class); $src = __DIR__ . '/../_files/xsl/passthrough.xsl'; $oObject = new OLEObject($src); - $oObject->getSource(); + $source = $oObject->getSource(); } /** @@ -74,7 +72,6 @@ public function testConstructWithSupportedFilesAndStyle(): void $src = __DIR__ . '/../_files/documents/sheet.xls'; $oObject = new OLEObject($src, ['width' => '230px']); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\OLEObject', $oObject); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Image', $oObject->getStyle()); self::assertEquals($src, $oObject->getSource()); } diff --git a/tests/PhpWordTests/Element/PageBreakTest.php b/tests/PhpWordTests/Element/PageBreakTest.php deleted file mode 100644 index 13cfb937d3..0000000000 --- a/tests/PhpWordTests/Element/PageBreakTest.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/** - * This file is part of PHPWord - A pure PHP library for reading and writing - * word processing documents. - * - * PHPWord is free software distributed under the terms of the GNU Lesser - * General Public License version 3 as published by the Free Software Foundation. - * - * For the full copyright and license information, please read the LICENSE - * file that was distributed with this source code. For the full list of - * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. - * - * @see https://github.com/PHPOffice/PHPWord - * - * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 - */ - -namespace PhpOffice\PhpWordTests\Element; - -use PhpOffice\PhpWord\Element\PageBreak; - -/** - * Test class for PhpOffice\PhpWord\Element\PageBreak. - * - * @coversDefaultClass \PhpOffice\PhpWord\Element\PageBreak - * - * @runTestsInSeparateProcesses - */ -class PageBreakTest extends \PHPUnit\Framework\TestCase -{ - /** - * Executed before each method of the class. - */ - public function testConstruct(): void - { - $oPageBreak = new PageBreak(); - - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\PageBreak', $oPageBreak); - } -} diff --git a/tests/PhpWordTests/Element/PreserveTextTest.php b/tests/PhpWordTests/Element/PreserveTextTest.php index 98d133c45d..746db6aeee 100644 --- a/tests/PhpWordTests/Element/PreserveTextTest.php +++ b/tests/PhpWordTests/Element/PreserveTextTest.php @@ -35,7 +35,6 @@ public function testConstruct(): void { $oPreserveText = new PreserveText(); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\PreserveText', $oPreserveText); self::assertNull($oPreserveText->getText()); self::assertNull($oPreserveText->getFontStyle()); self::assertNull($oPreserveText->getParagraphStyle()); diff --git a/tests/PhpWordTests/Element/RowTest.php b/tests/PhpWordTests/Element/RowTest.php index c2881acbc2..6dc8335ffd 100644 --- a/tests/PhpWordTests/Element/RowTest.php +++ b/tests/PhpWordTests/Element/RowTest.php @@ -36,7 +36,6 @@ public function testConstruct(): void { $oRow = new Row(); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Row', $oRow); self::assertNull($oRow->getHeight()); self::assertIsArray($oRow->getCells()); self::assertCount(0, $oRow->getCells()); diff --git a/tests/PhpWordTests/Element/RubyTest.php b/tests/PhpWordTests/Element/RubyTest.php index 0e14994fd2..44d2e5ba3c 100644 --- a/tests/PhpWordTests/Element/RubyTest.php +++ b/tests/PhpWordTests/Element/RubyTest.php @@ -36,14 +36,10 @@ public function testConstruct(): void { $ruby = new Ruby(new TextRun(), new TextRun(), new RubyProperties()); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Ruby', $ruby); self::assertEquals('', $ruby->getBaseTextRun()->getText()); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $ruby->getBaseTextRun()); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $ruby->getBaseTextRun()->getParagraphStyle()); self::assertEquals('', $ruby->getRubyTextRun()->getText()); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $ruby->getRubyTextRun()); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $ruby->getRubyTextRun()->getParagraphStyle()); - self::assertInstanceOf('PhpOffice\\PhpWord\\ComplexType\\RubyProperties', $ruby->getProperties()); self::assertEquals(RubyProperties::ALIGNMENT_DISTRIBUTE_SPACE, $ruby->getProperties()->getAlignment()); } @@ -58,7 +54,6 @@ public function testBaseText(): void $tr = new TextRun(); $tr->addText('Hello, world'); $ruby->setBaseTextRun($tr); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $ruby->getBaseTextRun()); self::assertEquals('Hello, world', $ruby->getBaseTextRun()->getText()); } @@ -73,7 +68,6 @@ public function testRubyText(): void $tr = new TextRun(); $tr->addText('Hello, ruby'); $ruby->setRubyTextRun($tr); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $ruby->getRubyTextRun()); self::assertEquals('Hello, ruby', $ruby->getRubyTextRun()->getText()); } @@ -94,7 +88,6 @@ public function testRubyProperties(): void $properties->setLanguageId('en-US'); $ruby->setProperties($properties); - self::assertInstanceOf('PhpOffice\\PhpWord\\ComplexType\\RubyProperties', $ruby->getProperties()); self::assertEquals(RubyProperties::ALIGNMENT_RIGHT_VERTICAL, $ruby->getProperties()->getAlignment()); self::assertEquals(1, $ruby->getProperties()->getFontFaceSize()); self::assertEquals(2, $ruby->getProperties()->getFontPointsAboveBaseText()); diff --git a/tests/PhpWordTests/Element/SDTTest.php b/tests/PhpWordTests/Element/SDTTest.php index 505ef14fe4..d7617160be 100644 --- a/tests/PhpWordTests/Element/SDTTest.php +++ b/tests/PhpWordTests/Element/SDTTest.php @@ -44,7 +44,6 @@ public function testConstruct(): void $object->setAlias($alias); $object->setTag($tag); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\SDT', $object); self::assertEquals($type, $object->getType()); self::assertEquals($types, $object->getListItems()); self::assertEquals($value, $object->getValue()); diff --git a/tests/PhpWordTests/Element/TableTest.php b/tests/PhpWordTests/Element/TableTest.php index 8e941cd056..0628d269e6 100644 --- a/tests/PhpWordTests/Element/TableTest.php +++ b/tests/PhpWordTests/Element/TableTest.php @@ -36,7 +36,6 @@ public function testConstruct(): void { $oTable = new Table(); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Table', $oTable); self::assertNull($oTable->getStyle()); self::assertNull($oTable->getWidth()); self::assertEquals([], $oTable->getRows()); diff --git a/tests/PhpWordTests/Element/TextBoxTest.php b/tests/PhpWordTests/Element/TextBoxTest.php index 6305b4e7ed..9289d1ad47 100644 --- a/tests/PhpWordTests/Element/TextBoxTest.php +++ b/tests/PhpWordTests/Element/TextBoxTest.php @@ -36,7 +36,6 @@ public function testConstruct(): void { $oTextBox = new TextBox(); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextBox', $oTextBox); self::assertNull($oTextBox->getStyle()); } diff --git a/tests/PhpWordTests/Element/TextRunTest.php b/tests/PhpWordTests/Element/TextRunTest.php index e3a2826f0c..b18eca99e4 100644 --- a/tests/PhpWordTests/Element/TextRunTest.php +++ b/tests/PhpWordTests/Element/TextRunTest.php @@ -38,7 +38,6 @@ public function testConstruct(): void { $oTextRun = new TextRun(); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $oTextRun); self::assertCount(0, $oTextRun->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $oTextRun->getParagraphStyle()); } @@ -50,7 +49,6 @@ public function testConstructString(): void { $oTextRun = new TextRun('pStyle'); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $oTextRun); self::assertCount(0, $oTextRun->getElements()); self::assertEquals('pStyle', $oTextRun->getParagraphStyle()); } @@ -62,7 +60,6 @@ public function testConstructArray(): void { $oTextRun = new TextRun(['spacing' => 100]); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $oTextRun); self::assertCount(0, $oTextRun->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $oTextRun->getParagraphStyle()); } @@ -76,7 +73,6 @@ public function testConstructObject(): void $oParagraphStyle->setAlignment(Jc::BOTH); $oTextRun = new TextRun($oParagraphStyle); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $oTextRun); self::assertCount(0, $oTextRun->getElements()); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $oTextRun->getParagraphStyle()); self::assertEquals(Jc::BOTH, $oTextRun->getParagraphStyle()->getAlignment()); diff --git a/tests/PhpWordTests/Element/TextTest.php b/tests/PhpWordTests/Element/TextTest.php index ee3c67edd9..693430a87f 100644 --- a/tests/PhpWordTests/Element/TextTest.php +++ b/tests/PhpWordTests/Element/TextTest.php @@ -36,7 +36,6 @@ public function testConstruct(): void { $oText = new Text(); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Text', $oText); self::assertNull($oText->getText()); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Font', $oText->getFontStyle()); self::assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $oText->getParagraphStyle()); diff --git a/tests/PhpWordTests/Element/TitleTest.php b/tests/PhpWordTests/Element/TitleTest.php index 2663189dd6..ab1e38102f 100644 --- a/tests/PhpWordTests/Element/TitleTest.php +++ b/tests/PhpWordTests/Element/TitleTest.php @@ -40,7 +40,6 @@ public function testConstruct(): void { $title = new Title('text'); - self::assertInstanceOf(Title::class, $title); self::assertEquals('text', $title->getText()); self::assertEquals(1, $title->getDepth()); self::assertNull($title->getPageNumber()); @@ -73,7 +72,6 @@ public function testConstructWithPageNumber(): void { $title = new Title('text', 1, 0); - self::assertInstanceOf(Title::class, $title); self::assertEquals('text', $title->getText()); self::assertEquals(0, $title->getPageNumber()); self::assertNull($title->getStyle()); diff --git a/tests/PhpWordTests/Element/TrackChangeTest.php b/tests/PhpWordTests/Element/TrackChangeTest.php index bf2e1dea1c..1d37fb3dd4 100644 --- a/tests/PhpWordTests/Element/TrackChangeTest.php +++ b/tests/PhpWordTests/Element/TrackChangeTest.php @@ -41,7 +41,6 @@ public function testConstructDefault(): void $oText = new Text('dummy text'); $oText->setTrackChange($oTrackChange); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TrackChange', $oTrackChange); self::assertEquals($author, $oTrackChange->getAuthor()); self::assertEquals($date, $oTrackChange->getDate()); self::assertEquals(TrackChange::INSERTED, $oTrackChange->getChangeType()); @@ -59,7 +58,6 @@ public function testConstructDefaultWithInvalidDate(): void $oText = new Text('dummy text'); $oText->setTrackChange($oTrackChange); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TrackChange', $oTrackChange); self::assertEquals($author, $oTrackChange->getAuthor()); self::assertEquals($date, null); self::assertEquals(TrackChange::INSERTED, $oTrackChange->getChangeType()); diff --git a/tests/PhpWordTests/Exception/CopyFileExceptionTest.php b/tests/PhpWordTests/Exception/CopyFileExceptionTest.php index a11ac79afa..9ca06d2b09 100644 --- a/tests/PhpWordTests/Exception/CopyFileExceptionTest.php +++ b/tests/PhpWordTests/Exception/CopyFileExceptionTest.php @@ -29,8 +29,6 @@ class CopyFileExceptionTest extends \PHPUnit\Framework\TestCase { /** * CopyFileException can be thrown. - * - * @covers ::__construct() */ public function testCopyFileExceptionCanBeThrown(): void { diff --git a/tests/PhpWordTests/Exception/CreateTemporaryFileExceptionTest.php b/tests/PhpWordTests/Exception/CreateTemporaryFileExceptionTest.php index dd8f395318..31015c62a8 100644 --- a/tests/PhpWordTests/Exception/CreateTemporaryFileExceptionTest.php +++ b/tests/PhpWordTests/Exception/CreateTemporaryFileExceptionTest.php @@ -29,8 +29,6 @@ class CreateTemporaryFileExceptionTest extends \PHPUnit\Framework\TestCase { /** * CreateTemporaryFileException can be thrown. - * - * @covers ::__construct() */ public function testCreateTemporaryFileExceptionCanBeThrown(): void { diff --git a/tests/PhpWordTests/Metadata/SettingsTest.php b/tests/PhpWordTests/Metadata/SettingsTest.php index c7f165db28..0c5a6f1593 100644 --- a/tests/PhpWordTests/Metadata/SettingsTest.php +++ b/tests/PhpWordTests/Metadata/SettingsTest.php @@ -230,9 +230,11 @@ public function testDefaultDoNotHyphenateCaps(): void public function testBookFoldPrinting(): void { $oSettings = new Settings(); - self::assertInstanceOf(Settings::class, $oSettings->setBookFoldPrinting(true)); + + $oSettings->setBookFoldPrinting(true); self::assertTrue($oSettings->hasBookFoldPrinting()); - self::assertInstanceOf(Settings::class, $oSettings->setBookFoldPrinting(false)); + + $oSettings->setBookFoldPrinting(false); self::assertFalse($oSettings->hasBookFoldPrinting()); } diff --git a/tests/PhpWordTests/SettingsTest.php b/tests/PhpWordTests/SettingsTest.php index 13b32e1293..f8b9af661d 100644 --- a/tests/PhpWordTests/SettingsTest.php +++ b/tests/PhpWordTests/SettingsTest.php @@ -276,7 +276,7 @@ public function testSetGetDefaultFontColor(): void public function testSetGetDefaultPaper(): void { $dflt = Settings::DEFAULT_PAPER; - $chng = ($dflt === 'A4') ? 'Letter' : 'A4'; + $chng = 'A4'; $doc = new PhpWord(); self::assertEquals($dflt, Settings::getDefaultPaper()); $sec1 = $doc->addSection(); diff --git a/tests/PhpWordTests/Shared/XMLReaderTest.php b/tests/PhpWordTests/Shared/XMLReaderTest.php index 212f20e1ba..18750b5ef9 100644 --- a/tests/PhpWordTests/Shared/XMLReaderTest.php +++ b/tests/PhpWordTests/Shared/XMLReaderTest.php @@ -91,10 +91,7 @@ public function testThrowsExceptionOnNonExistingArchive(): void */ public function testThrowsExceptionOnZipArchiveOpenErrors(): void { - /** - * @var string - */ - $tempPath = tempnam(sys_get_temp_dir(), 'PhpWord'); + $tempPath = tempnam(sys_get_temp_dir(), 'PhpWord') ?: 'tempNameFile'; // Simulate a corrupt archive file_put_contents($tempPath, mt_rand()); @@ -150,6 +147,7 @@ public function testShouldThrowExceptionIfNamespaceIsNotKnown(): void self::assertEquals('AAA', $reader->getElement('/element/test:child')->textContent); self::fail(); } catch (Exception $e) { + // @phpstan-ignore-next-line self::assertTrue(true); } } diff --git a/tests/PhpWordTests/Style/AbstractStyleTest.php b/tests/PhpWordTests/Style/AbstractStyleTest.php index 2b8d3d8d17..679c9f5e49 100644 --- a/tests/PhpWordTests/Style/AbstractStyleTest.php +++ b/tests/PhpWordTests/Style/AbstractStyleTest.php @@ -36,6 +36,7 @@ class AbstractStyleTest extends \PHPUnit\Framework\TestCase */ public function testSetStyleByArray(): void { + // @phpstan-ignore-next-line if (method_exists($this, 'getMockForAbstractClass')) { $stub = $this->getMockForAbstractClass(AbstractStyle::class); } else { @@ -69,6 +70,7 @@ public function testSetStyleByArrayWithAlignment(): void */ public function testSetValNormal(): void { + // @phpstan-ignore-next-line if (method_exists($this, 'getMockForAbstractClass')) { $stub = $this->getMockForAbstractClass(AbstractStyle::class); } else { @@ -89,6 +91,7 @@ public function testSetValNormal(): void */ public function testSetValDefault(): void { + // @phpstan-ignore-next-line if (method_exists($this, 'getMockForAbstractClass')) { $stub = $this->getMockForAbstractClass(AbstractStyle::class); } else { @@ -109,6 +112,7 @@ public function testSetValDefault(): void public function testSetValEnumException(): void { $this->expectException(InvalidArgumentException::class); + // @phpstan-ignore-next-line if (method_exists($this, 'getMockForAbstractClass')) { $stub = $this->getMockForAbstractClass(AbstractStyle::class); } else { diff --git a/tests/PhpWordTests/Style/CellTest.php b/tests/PhpWordTests/Style/CellTest.php index 9015d0feea..56b099c05f 100644 --- a/tests/PhpWordTests/Style/CellTest.php +++ b/tests/PhpWordTests/Style/CellTest.php @@ -30,29 +30,42 @@ */ class CellTest extends \PHPUnit\Framework\TestCase { - /** - * Test setting style with normal value. - */ - public function testSetGetNormal(): void + public function testSetGetNormalInt(): void { $object = new Cell(); - $attributes = [ + foreach ([ + 'borderTopSize' => 120, + 'borderLeftSize' => 120, + 'borderRightSize' => 120, + 'borderBottomSize' => 120, + 'gridSpan' => 2, + ] as $key => $value) { + $set = "set{$key}"; + $get = "get{$key}"; + + self::assertNull($object->$get()); // Init with null value + + $object->$set($value); + + self::assertEquals($value, $object->$get()); + } + } + + public function testSetGetNormalString(): void + { + $object = new Cell(); + + foreach ([ 'valign' => VerticalJc::TOP, 'textDirection' => Cell::TEXT_DIR_BTLR, 'bgColor' => 'FFFF00', - 'borderTopSize' => 120, 'borderTopColor' => 'FFFF00', - 'borderLeftSize' => 120, 'borderLeftColor' => 'FFFF00', - 'borderRightSize' => 120, 'borderRightColor' => 'FFFF00', - 'borderBottomSize' => 120, 'borderBottomColor' => 'FFFF00', - 'gridSpan' => 2, 'vMerge' => Cell::VMERGE_RESTART, - ]; - foreach ($attributes as $key => $value) { + ] as $key => $value) { $set = "set{$key}"; $get = "get{$key}"; diff --git a/tests/PhpWordTests/Style/ChartTest.php b/tests/PhpWordTests/Style/ChartTest.php index cece336e0f..e8e75901d7 100644 --- a/tests/PhpWordTests/Style/ChartTest.php +++ b/tests/PhpWordTests/Style/ChartTest.php @@ -165,8 +165,6 @@ public function testSetGetCategoryAxisTitle(): void { $chart = new Chart(); - $chart->getCategoryAxisTitle(); - self::assertEquals($chart->getCategoryAxisTitle(), null); $chart->setCategoryAxisTitle('Test Category Axis Title'); @@ -181,8 +179,6 @@ public function testSetGetValueAxisTitle(): void { $chart = new Chart(); - $chart->getValueAxisTitle(); - self::assertEquals($chart->getValueAxisTitle(), null); $chart->setValueAxisTitle('Test Value Axis Title'); diff --git a/tests/PhpWordTests/Style/ImageTest.php b/tests/PhpWordTests/Style/ImageTest.php index 1223069c67..759a85441e 100644 --- a/tests/PhpWordTests/Style/ImageTest.php +++ b/tests/PhpWordTests/Style/ImageTest.php @@ -31,26 +31,33 @@ */ class ImageTest extends \PHPUnit\Framework\TestCase { - /** - * Test setting style with normal value. - */ - public function testSetGetNormal(): void + public function testSetGetNormalInt(): void { $object = new Image(); - - $properties = [ + foreach ([ 'width' => 200, 'height' => 200, - 'alignment' => Jc::START, 'marginTop' => 240, 'marginLeft' => 240, - 'wrappingStyle' => 'inline', 'wrapDistanceLeft' => 10, 'wrapDistanceRight' => 20, 'wrapDistanceTop' => 30, 'wrapDistanceBottom' => 40, - ]; - foreach ($properties as $key => $value) { + ] as $key => $value) { + $set = "set{$key}"; + $get = "get{$key}"; + $object->$set($value); + self::assertEquals($value, $object->$get()); + } + } + + public function testSetGetNormalString(): void + { + $object = new Image(); + foreach ([ + 'alignment' => Jc::START, + 'wrappingStyle' => 'inline', + ] as $key => $value) { $set = "set{$key}"; $get = "get{$key}"; $object->$set($value); diff --git a/tests/PhpWordTests/Style/LanguageTest.php b/tests/PhpWordTests/Style/LanguageTest.php index e6b6d1630a..848284e5e3 100644 --- a/tests/PhpWordTests/Style/LanguageTest.php +++ b/tests/PhpWordTests/Style/LanguageTest.php @@ -29,19 +29,32 @@ */ class LanguageTest extends \PHPUnit\Framework\TestCase { - /** - * Test get/set. - */ - public function testGetSetProperties(): void + public function testGetSetPropertiesInt(): void + { + $object = new Language(); + foreach ([ + 'langId' => [null, 1036], + ] as $property => $value) { + [$default, $expected] = $value; + $get = "get{$property}"; + $set = "set{$property}"; + + self::assertEquals($default, $object->$get()); // Default value + + $object->$set($expected); + + self::assertEquals($expected, $object->$get()); // New value + } + } + + public function testGetSetPropertiesString(): void { $object = new Language(); - $properties = [ + foreach ([ 'latin' => [null, 'fr-BE'], 'eastAsia' => [null, 'ja-JP'], 'bidirectional' => [null, 'ar-SA'], - 'langId' => [null, 1036], - ]; - foreach ($properties as $property => $value) { + ] as $property => $value) { [$default, $expected] = $value; $get = "get{$property}"; $set = "set{$property}"; diff --git a/tests/PhpWordTests/Style/LineNumberingTest.php b/tests/PhpWordTests/Style/LineNumberingTest.php index d91e7ccfbc..c76bddf56c 100644 --- a/tests/PhpWordTests/Style/LineNumberingTest.php +++ b/tests/PhpWordTests/Style/LineNumberingTest.php @@ -27,19 +27,32 @@ */ class LineNumberingTest extends \PHPUnit\Framework\TestCase { - /** - * Test get/set. - */ - public function testGetSetProperties(): void + public function testGetSetPropertiesInt(): void { $object = new LineNumbering(); - $properties = [ + foreach ([ 'start' => [1, 2], 'increment' => [1, 10], 'distance' => [null, 10], + ] as $property => $value) { + [$default, $expected] = $value; + $get = "get{$property}"; + $set = "set{$property}"; + + self::assertEquals($default, $object->$get()); // Default value + + $object->$set($expected); + + self::assertEquals($expected, $object->$get()); // New value + } + } + + public function testGetSetPropertiesString(): void + { + $object = new LineNumbering(); + foreach ([ 'restart' => [null, 'continuous'], - ]; - foreach ($properties as $property => $value) { + ] as $property => $value) { [$default, $expected] = $value; $get = "get{$property}"; $set = "set{$property}"; diff --git a/tests/PhpWordTests/Style/LineTest.php b/tests/PhpWordTests/Style/LineTest.php index 3e4db2438f..26049d5cd8 100644 --- a/tests/PhpWordTests/Style/LineTest.php +++ b/tests/PhpWordTests/Style/LineTest.php @@ -29,22 +29,31 @@ */ class LineTest extends \PHPUnit\Framework\TestCase { - /** - * Test setting style with normal value. - */ - public function testSetGetNormal(): void + public function testSetGetNormalInt(): void { $object = new Line(); - $properties = [ + foreach ([ + 'weight' => 10, + ] as $key => $value) { + $set = "set{$key}"; + $get = "get{$key}"; + $object->$set($value); + self::assertEquals($value, $object->$get()); + } + } + + public function testSetGetNormalString(): void + { + $object = new Line(); + + foreach ([ 'connectorType' => Line::CONNECTOR_TYPE_STRAIGHT, 'beginArrow' => Line::ARROW_STYLE_BLOCK, 'endArrow' => Line::ARROW_STYLE_OVAL, 'dash' => Line::DASH_STYLE_LONG_DASH_DOT_DOT, - 'weight' => 10, 'color' => 'red', - ]; - foreach ($properties as $key => $value) { + ] as $key => $value) { $set = "set{$key}"; $get = "get{$key}"; $object->$set($value); diff --git a/tests/PhpWordTests/Style/NumberingLevelTest.php b/tests/PhpWordTests/Style/NumberingLevelTest.php index 07721408bf..b34e445e94 100644 --- a/tests/PhpWordTests/Style/NumberingLevelTest.php +++ b/tests/PhpWordTests/Style/NumberingLevelTest.php @@ -28,25 +28,36 @@ */ class NumberingLevelTest extends \PHPUnit\Framework\TestCase { - /** - * Test setting style with normal value. - */ - public function testSetGetNormal(): void + public function testSetGetNormalInt(): void { $object = new NumberingLevel(); $attributes = [ 'level' => 1, 'start' => 1, - 'format' => 'decimal', 'restart' => 1, + 'left' => 360, + 'hanging' => 360, + 'tabPos' => 360, + ]; + foreach ($attributes as $key => $value) { + $set = "set{$key}"; + $get = "get{$key}"; + $object->$set($value); + self::assertEquals($value, $object->$get()); + } + } + + public function testSetGetNormalString(): void + { + $object = new NumberingLevel(); + + $attributes = [ + 'format' => 'decimal', 'pStyle' => 'pStyle', 'suffix' => 'space', 'text' => '%1.', 'alignment' => Jc::START, - 'left' => 360, - 'hanging' => 360, - 'tabPos' => 360, 'font' => 'Arial', 'hint' => 'default', ]; diff --git a/tests/PhpWordTests/Style/NumberingTest.php b/tests/PhpWordTests/Style/NumberingTest.php index ce39509d0b..153e4b9284 100644 --- a/tests/PhpWordTests/Style/NumberingTest.php +++ b/tests/PhpWordTests/Style/NumberingTest.php @@ -27,17 +27,30 @@ */ class NumberingTest extends \PHPUnit\Framework\TestCase { - /** - * Test get/set. - */ - public function testGetSetProperties(): void + public function testGetSetPropertiesInt(): void { $object = new Numbering(); - $properties = [ + foreach ([ 'numId' => [null, 1], + ] as $property => $value) { + [$default, $expected] = $value; + $get = "get{$property}"; + $set = "set{$property}"; + + self::assertEquals($default, $object->$get()); // Default value + + $object->$set($expected); + + self::assertEquals($expected, $object->$get()); // New value + } + } + + public function testGetSetPropertiesString(): void + { + $object = new Numbering(); + foreach ([ 'type' => [null, 'singleLevel'], - ]; - foreach ($properties as $property => $value) { + ] as $property => $value) { [$default, $expected] = $value; $get = "get{$property}"; $set = "set{$property}"; @@ -50,9 +63,6 @@ public function testGetSetProperties(): void } } - /** - * Test get level. - */ public function testGetLevels(): void { $object = new Numbering(); diff --git a/tests/PhpWordTests/Style/ParagraphTest.php b/tests/PhpWordTests/Style/ParagraphTest.php index 6a6e777cfc..67645fa4d8 100644 --- a/tests/PhpWordTests/Style/ParagraphTest.php +++ b/tests/PhpWordTests/Style/ParagraphTest.php @@ -150,13 +150,17 @@ public function testHanging(): void $object = new Paragraph(); self::assertNull($object->getHanging()); - self::assertInstanceOf(Paragraph::class, $object->setHanging($rand)); + + $object->setHanging($rand); self::assertEquals($rand, $object->getHanging()); - self::assertInstanceOf(Paragraph::class, $object->setHanging(null)); + + $object->setHanging(null); self::assertNull($object->getHanging()); - self::assertInstanceOf(Paragraph::class, $object->setHanging($rand)); + + $object->setHanging($rand); self::assertEquals($rand, $object->getHanging()); - self::assertInstanceOf(Paragraph::class, $object->setHanging()); + + $object->setHanging(); self::assertNull($object->getHanging()); } @@ -166,13 +170,17 @@ public function testIndent(): void $object = new Paragraph(); self::assertNull($object->getIndent()); - self::assertInstanceOf(Paragraph::class, $object->setIndent($rand)); + + $object->setIndent($rand); self::assertEquals($rand, $object->getIndent()); - self::assertInstanceOf(Paragraph::class, $object->setIndent(null)); + + $object->setIndent(null); self::assertNull($object->getIndent()); - self::assertInstanceOf(Paragraph::class, $object->setIndent($rand)); + + $object->setIndent($rand); self::assertEquals($rand, $object->getIndent()); - self::assertInstanceOf(Paragraph::class, $object->setIndent()); + + $object->setIndent(); self::assertNull($object->getIndent()); } @@ -184,60 +192,60 @@ public function testIndentation(): void $object = new Paragraph(); self::assertNull($object->getIndentation()); // Set Basic indentation - self::assertInstanceOf(Paragraph::class, $object->setIndentation([])); + $object->setIndentation([]); self::assertNotNull($object->getIndentation()); self::assertEquals(0, $object->getIndentation()->getLeft()); self::assertEquals(0, $object->getIndentation()->getRight()); self::assertEquals(0, $object->getIndentation()->getHanging()); self::assertEquals(0, $object->getIndentation()->getFirstLine()); // Set indentation : left - self::assertInstanceOf(Paragraph::class, $object->setIndentation([ + $object->setIndentation([ 'left' => $rand, - ])); + ]); self::assertNotNull($object->getIndentation()); self::assertEquals($rand, $object->getIndentation()->getLeft()); self::assertEquals(0, $object->getIndentation()->getRight()); self::assertEquals(0, $object->getIndentation()->getHanging()); self::assertEquals(0, $object->getIndentation()->getFirstLine()); // Set indentation : right - self::assertInstanceOf(Paragraph::class, $object->setIndentation([ + $object->setIndentation([ 'right' => $rand, - ])); + ]); self::assertNotNull($object->getIndentation()); self::assertEquals($rand, $object->getIndentation()->getLeft()); self::assertEquals($rand, $object->getIndentation()->getRight()); self::assertEquals(0, $object->getIndentation()->getHanging()); self::assertEquals(0, $object->getIndentation()->getFirstLine()); // Set indentation : hanging - self::assertInstanceOf(Paragraph::class, $object->setIndentation([ + $object->setIndentation([ 'hanging' => $rand, - ])); + ]); self::assertNotNull($object->getIndentation()); self::assertEquals($rand, $object->getIndentation()->getLeft()); self::assertEquals($rand, $object->getIndentation()->getRight()); self::assertEquals($rand, $object->getIndentation()->getHanging()); self::assertEquals(0, $object->getIndentation()->getFirstLine()); // Set indentation : firstline - self::assertInstanceOf(Paragraph::class, $object->setIndentation([ + $object->setIndentation([ 'firstline' => $rand, - ])); + ]); self::assertNotNull($object->getIndentation()); self::assertEquals($rand, $object->getIndentation()->getLeft()); self::assertEquals($rand, $object->getIndentation()->getRight()); self::assertEquals($rand, $object->getIndentation()->getHanging()); self::assertEquals($rand, $object->getIndentation()->getFirstLine()); // Replace indentation : left & firstline - self::assertInstanceOf(Paragraph::class, $object->setIndentation([ + $object->setIndentation([ 'left' => $rand2, 'firstline' => $rand2, - ])); + ]); self::assertNotNull($object->getIndentation()); self::assertEquals($rand2, $object->getIndentation()->getLeft()); self::assertEquals($rand, $object->getIndentation()->getRight()); self::assertEquals($rand, $object->getIndentation()->getHanging()); self::assertEquals($rand2, $object->getIndentation()->getFirstLine()); // Replace indentation : N/A - self::assertInstanceOf(Paragraph::class, $object->setIndentation()); + $object->setIndentation(); self::assertNotNull($object->getIndentation()); self::assertEquals($rand2, $object->getIndentation()->getLeft()); self::assertEquals($rand, $object->getIndentation()->getRight()); @@ -251,13 +259,13 @@ public function testIndentFirstLine(): void $object = new Paragraph(); self::assertNull($object->getIndentFirstLine()); - self::assertInstanceOf(Paragraph::class, $object->setIndentFirstLine($rand)); + $object->setIndentFirstLine($rand); self::assertEquals($rand, $object->getIndentFirstLine()); - self::assertInstanceOf(Paragraph::class, $object->setIndentFirstLine(null)); + $object->setIndentFirstLine(null); self::assertNull($object->getIndentFirstLine()); - self::assertInstanceOf(Paragraph::class, $object->setIndentFirstLine($rand)); + $object->setIndentFirstLine($rand); self::assertEquals($rand, $object->getIndentFirstLine()); - self::assertInstanceOf(Paragraph::class, $object->setIndentFirstLine()); + $object->setIndentFirstLine(); self::assertNull($object->getIndentFirstLine()); } @@ -267,13 +275,13 @@ public function testIndentLeft(): void $object = new Paragraph(); self::assertNull($object->getIndentLeft()); - self::assertInstanceOf(Paragraph::class, $object->setIndentLeft($rand)); + $object->setIndentLeft($rand); self::assertEquals($rand, $object->getIndentLeft()); - self::assertInstanceOf(Paragraph::class, $object->setIndentLeft(null)); + $object->setIndentLeft(null); self::assertNull($object->getIndentLeft()); - self::assertInstanceOf(Paragraph::class, $object->setIndentLeft($rand)); + $object->setIndentLeft($rand); self::assertEquals($rand, $object->getIndentLeft()); - self::assertInstanceOf(Paragraph::class, $object->setIndentLeft()); + $object->setIndentLeft(); self::assertNull($object->getIndentLeft()); } @@ -283,13 +291,13 @@ public function testIndentRight(): void $object = new Paragraph(); self::assertNull($object->getIndentRight()); - self::assertInstanceOf(Paragraph::class, $object->setIndentRight($rand)); + $object->setIndentRight($rand); self::assertEquals($rand, $object->getIndentRight()); - self::assertInstanceOf(Paragraph::class, $object->setIndentRight(null)); + $object->setIndentRight(null); self::assertNull($object->getIndentRight()); - self::assertInstanceOf(Paragraph::class, $object->setIndentRight($rand)); + $object->setIndentRight($rand); self::assertEquals($rand, $object->getIndentRight()); - self::assertInstanceOf(Paragraph::class, $object->setIndentRight()); + $object->setIndentRight(); self::assertNull($object->getIndentRight()); } @@ -350,11 +358,11 @@ public function testBidiVisual(): void { $object = new Paragraph(); self::assertNull($object->isBidi()); - self::assertInstanceOf(Paragraph::class, $object->setBidi(true)); + $object->setBidi(true); self::assertTrue($object->isBidi()); - self::assertInstanceOf(Paragraph::class, $object->setBidi(false)); + $object->setBidi(false); self::assertFalse($object->isBidi()); - self::assertInstanceOf(Paragraph::class, $object->setBidi(null)); + $object->setBidi(null); self::assertNull($object->isBidi()); } diff --git a/tests/PhpWordTests/Style/RowTest.php b/tests/PhpWordTests/Style/RowTest.php index 688a6b7b35..d3cc480ac7 100644 --- a/tests/PhpWordTests/Style/RowTest.php +++ b/tests/PhpWordTests/Style/RowTest.php @@ -56,24 +56,4 @@ public function testBooleanValue(): void self::assertEquals($expected, $object->$get()); } } - - /** - * Test properties with nonboolean values, which will return default value. - */ - public function testNonBooleanValue(): void - { - $object = new Row(); - - $properties = [ - 'tblHeader' => 'a', - 'cantSplit' => 'b', - 'exactHeight' => 'c', - ]; - foreach ($properties as $key => $value) { - $set = "set{$key}"; - $get = "is{$key}"; - $object->$set($value); - self::assertFalse($object->$get()); - } - } } diff --git a/tests/PhpWordTests/Style/SpacingTest.php b/tests/PhpWordTests/Style/SpacingTest.php index 874fd5c5dd..351b9f1b54 100644 --- a/tests/PhpWordTests/Style/SpacingTest.php +++ b/tests/PhpWordTests/Style/SpacingTest.php @@ -27,16 +27,31 @@ */ class SpacingTest extends \PHPUnit\Framework\TestCase { - /** - * Test get/set. - */ - public function testGetSetProperties(): void + public function testGetSetPropertiesInt(): void { $object = new Spacing(); $properties = [ 'before' => [null, 10], 'after' => [null, 10], 'line' => [null, 10], + ]; + foreach ($properties as $property => $value) { + [$default, $expected] = $value; + $get = "get{$property}"; + $set = "set{$property}"; + + self::assertEquals($default, $object->$get()); // Default value + + $object->$set($expected); + + self::assertEquals($expected, $object->$get()); // New value + } + } + + public function testGetSetPropertiesString(): void + { + $object = new Spacing(); + $properties = [ 'lineRule' => ['auto', 'exact'], ]; foreach ($properties as $property => $value) { diff --git a/tests/PhpWordTests/Style/TOCTest.php b/tests/PhpWordTests/Style/TOCTest.php index 118c8c4199..039bc11340 100644 --- a/tests/PhpWordTests/Style/TOCTest.php +++ b/tests/PhpWordTests/Style/TOCTest.php @@ -27,18 +27,31 @@ */ class TOCTest extends \PHPUnit\Framework\TestCase { - /** - * Test get/set. - */ - public function testGetSet(): void + public function testGetSetInt(): void { $object = new TOC(); - $properties = [ - 'tabLeader' => [TOC::TAB_LEADER_DOT, TOC::TAB_LEADER_UNDERSCORE], + foreach ([ 'tabPos' => [9062, 10], 'indent' => [200, 10], - ]; - foreach ($properties as $property => $value) { + ] as $property => $value) { + [$default, $expected] = $value; + $get = "get{$property}"; + $set = "set{$property}"; + + self::assertEquals($default, $object->$get()); // Default value + + $object->$set($expected); + + self::assertEquals($expected, $object->$get()); // New value + } + } + + public function testGetSetString(): void + { + $object = new TOC(); + foreach ([ + 'tabLeader' => [TOC::TAB_LEADER_DOT, TOC::TAB_LEADER_UNDERSCORE], + ] as $property => $value) { [$default, $expected] = $value; $get = "get{$property}"; $set = "set{$property}"; diff --git a/tests/PhpWordTests/Style/TabTest.php b/tests/PhpWordTests/Style/TabTest.php index a1a6a2e0db..43b9ff2c85 100644 --- a/tests/PhpWordTests/Style/TabTest.php +++ b/tests/PhpWordTests/Style/TabTest.php @@ -30,15 +30,34 @@ class TabTest extends \PHPUnit\Framework\TestCase /** * Test get/set. */ - public function testGetSetProperties(): void + public function testGetSetPropertiesInt(): void { $object = new Tab(); - $properties = [ + foreach ([ + 'position' => [0, 10], + ] as $property => $value) { + [$default, $expected] = $value; + $get = "get{$property}"; + $set = "set{$property}"; + + self::assertEquals($default, $object->$get()); // Default value + + $object->$set($expected); + + self::assertEquals($expected, $object->$get()); // New value + } + } + + /** + * Test get/set. + */ + public function testGetSetPropertiesString(): void + { + $object = new Tab(); + foreach ([ 'type' => [Tab::TAB_STOP_CLEAR, Tab::TAB_STOP_RIGHT], 'leader' => [Tab::TAB_LEADER_NONE, Tab::TAB_LEADER_DOT], - 'position' => [0, 10], - ]; - foreach ($properties as $property => $value) { + ] as $property => $value) { [$default, $expected] = $value; $get = "get{$property}"; $set = "set{$property}"; diff --git a/tests/PhpWordTests/Style/TablePositionTest.php b/tests/PhpWordTests/Style/TablePositionTest.php index ba0bb9dd09..695bb3d297 100644 --- a/tests/PhpWordTests/Style/TablePositionTest.php +++ b/tests/PhpWordTests/Style/TablePositionTest.php @@ -42,23 +42,38 @@ public function testConstruct(): void /** * Test setting style with normal value. */ - public function testSetGetNormal(): void + public function testSetGetNormalInt(): void { $object = new TablePosition(); - $attributes = [ + foreach ([ 'leftFromText' => 4, 'rightFromText' => 4, 'topFromText' => 4, 'bottomFromText' => 4, + 'tblpX' => 5, + 'tblpY' => 6, + ] as $key => $value) { + $set = "set{$key}"; + $get = "get{$key}"; + $object->$set($value); + self::assertEquals($value, $object->$get()); + } + } + + /** + * Test setting style with normal value. + */ + public function testSetGetNormalString(): void + { + $object = new TablePosition(); + + foreach ([ 'vertAnchor' => TablePosition::VANCHOR_PAGE, 'horzAnchor' => TablePosition::HANCHOR_TEXT, 'tblpXSpec' => TablePosition::XALIGN_CENTER, - 'tblpX' => 5, 'tblpYSpec' => TablePosition::YALIGN_OUTSIDE, - 'tblpY' => 6, - ]; - foreach ($attributes as $key => $value) { + ] as $key => $value) { $set = "set{$key}"; $get = "get{$key}"; $object->$set($value); diff --git a/tests/PhpWordTests/TemplateProcessorTest.php b/tests/PhpWordTests/TemplateProcessorTest.php index 093879a042..8ae4dfa59a 100644 --- a/tests/PhpWordTests/TemplateProcessorTest.php +++ b/tests/PhpWordTests/TemplateProcessorTest.php @@ -70,7 +70,6 @@ protected function tearDown(): void public function testTheConstruct(): void { $object = $this->getTemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); - self::assertInstanceOf('PhpOffice\\PhpWord\\TemplateProcessor', $object); self::assertEquals([], $object->getVariables()); $object->save(); diff --git a/tests/PhpWordTests/Writer/EPub3/Part/AbstractPartTest.php b/tests/PhpWordTests/Writer/EPub3/Part/AbstractPartTest.php index c12980c7e2..24db959f6e 100644 --- a/tests/PhpWordTests/Writer/EPub3/Part/AbstractPartTest.php +++ b/tests/PhpWordTests/Writer/EPub3/Part/AbstractPartTest.php @@ -15,6 +15,7 @@ class AbstractPartTest extends TestCase protected function setUp(): void { + // @phpstan-ignore-next-line if (method_exists($this, 'getMockForAbstractClass')) { $this->part = $this->getMockForAbstractClass(AbstractPart::class); } else { diff --git a/tests/PhpWordTests/Writer/EPub3/Style/AbstractStyleTest.php b/tests/PhpWordTests/Writer/EPub3/Style/AbstractStyleTest.php index 12be0f2e4f..e06cef8a3b 100644 --- a/tests/PhpWordTests/Writer/EPub3/Style/AbstractStyleTest.php +++ b/tests/PhpWordTests/Writer/EPub3/Style/AbstractStyleTest.php @@ -14,6 +14,7 @@ class AbstractStyleTest extends TestCase public function testParentWriter(): void { $parentWriter = new EPub3(); + // @phpstan-ignore-next-line if (method_exists($this, 'getMockForAbstractClass')) { $style = $this->getMockForAbstractClass(AbstractStyle::class); } else { diff --git a/tests/PhpWordTests/Writer/HTMLTest.php b/tests/PhpWordTests/Writer/HTMLTest.php index 6dba003eb4..cedd9f2f32 100644 --- a/tests/PhpWordTests/Writer/HTMLTest.php +++ b/tests/PhpWordTests/Writer/HTMLTest.php @@ -57,11 +57,13 @@ public function testEditCallback(): void $object = new HTML(new PhpWord()); self::assertNull($object->getEditCallback()); - self::assertInstanceOf(HTML::class, $object->setEditCallback(function (string $html): string { + + $object->setEditCallback(function (string $html): string { return $html; - })); + }); self::assertIsCallable($object->getEditCallback()); - self::assertInstanceOf(HTML::class, $object->setEditCallback(null)); + + $object->setEditCallback(null); self::assertNull($object->getEditCallback()); } @@ -70,9 +72,11 @@ public function testDefaultGenericFont(): void $object = new HTML(new PhpWord()); self::assertEquals('', $object->getDefaultGenericFont()); - self::assertInstanceOf(HTML::class, $object->setDefaultGenericFont('test')); + + $object->setDefaultGenericFont('test'); self::assertEquals('', $object->getDefaultGenericFont()); - self::assertInstanceOf(HTML::class, $object->setDefaultGenericFont('cursive')); + + $object->setDefaultGenericFont('cursive'); self::assertEquals('cursive', $object->getDefaultGenericFont()); } @@ -81,9 +85,11 @@ public function testDefaultWhiteSpace(): void $object = new HTML(new PhpWord()); self::assertEquals('', $object->getDefaultWhiteSpace()); - self::assertInstanceOf(HTML::class, $object->setDefaultWhiteSpace('test')); + + $object->setDefaultWhiteSpace('test'); self::assertEquals('', $object->getDefaultWhiteSpace()); - self::assertInstanceOf(HTML::class, $object->setDefaultWhiteSpace('pre-line')); + + $object->setDefaultWhiteSpace('pre-line'); self::assertEquals('pre-line', $object->getDefaultWhiteSpace()); } diff --git a/tests/PhpWordTests/Writer/ODText/ElementTest.php b/tests/PhpWordTests/Writer/ODText/ElementTest.php index 4df140aaa4..8ca327717c 100644 --- a/tests/PhpWordTests/Writer/ODText/ElementTest.php +++ b/tests/PhpWordTests/Writer/ODText/ElementTest.php @@ -113,8 +113,10 @@ public function testTableElements(): void $p2s = '/office:document-content/office:automatic-styles'; $tableStyleNum = 1; - $tableStyleName = ''; - while ($tableStyleName === '') { + /** @var null|string $tableStyleName */ + $tableStyleName = null; + $element = ''; + while ($tableStyleName === null) { $element = "$p2s/style:style[$tableStyleNum]"; if (!$doc->elementExists($element)) { break; @@ -126,7 +128,7 @@ public function testTableElements(): void } ++$tableStyleNum; } - self::AssertNotEquals('', $tableStyleName); + self::assertNotNull($tableStyleName); $element = "$element/style:table-properties"; self::assertTrue($doc->elementExists($element)); self::assertEquals(\PhpOffice\PhpWord\SimpleType\JcTable::CENTER, $doc->getElementAttribute($element, 'table:align')); diff --git a/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php b/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php index 27008dae82..049b9e7cb4 100644 --- a/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php +++ b/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php @@ -34,6 +34,7 @@ class AbstractPartTest extends \PHPUnit\Framework\TestCase */ public function testSetGetParentWriter(): void { + // @phpstan-ignore-next-line if (method_exists($this, 'getMockForAbstractClass')) { $object = $this->getMockForAbstractClass(ODText\Part\AbstractPart::class); } else { @@ -56,6 +57,7 @@ public function testSetGetParentWriterNull(): void { $this->expectException(Exception::class); $this->expectExceptionMessage('No parent WriterInterface assigned.'); + // @phpstan-ignore-next-line if (method_exists($this, 'getMockForAbstractClass')) { $object = $this->getMockForAbstractClass(ODText\Part\AbstractPart::class); } else { diff --git a/tests/PhpWordTests/Writer/Word2007/Part/AbstractPartTest.php b/tests/PhpWordTests/Writer/Word2007/Part/AbstractPartTest.php index ca38d5d3fc..1bcd43f50e 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/AbstractPartTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/AbstractPartTest.php @@ -32,6 +32,7 @@ class AbstractPartTest extends \PHPUnit\Framework\TestCase */ public function testSetGetParentWriter(): void { + // @phpstan-ignore-next-line if (method_exists($this, 'getMockForAbstractClass')) { $stub = $this->getMockForAbstractClass(Word2007\Part\AbstractPart::class); } else { @@ -54,6 +55,7 @@ public function testSetGetParentWriterNull(): void { $this->expectException(Exception::class); $this->expectExceptionMessage('No parent WriterInterface assigned.'); + // @phpstan-ignore-next-line if (method_exists($this, 'getMockForAbstractClass')) { $stub = $this->getMockForAbstractClass(Word2007\Part\AbstractPart::class); } else { diff --git a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php index ed38c57ac6..d1f5b2585d 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php @@ -407,9 +407,10 @@ public function testWriteImage(): void // behind $element = $doc->getElement('/w:document/w:body/w:p[2]/w:r/w:pict/v:shape'); $style = $element->getAttribute('style'); + // @phpstan-ignore-next-line if (method_exists(self::class, 'assertMatchesRegularExpression')) { self::assertMatchesRegularExpression('/z\-index:\-[0-9]*/', $style); - } elseif (method_exists(self::class, 'assertRegExp')) { + } elseif (method_exists(self::class, 'assertRegExp')) { // @phpstan-ignore-line self::assertRegExp('/z\-index:\-[0-9]*/', $style); } else { self::fail('Unsure how to test regexp'); diff --git a/tests/PhpWordTests/Writer/Word2007/StyleTest.php b/tests/PhpWordTests/Writer/Word2007/StyleTest.php index d458ea45e7..0c0d0b854a 100644 --- a/tests/PhpWordTests/Writer/Word2007/StyleTest.php +++ b/tests/PhpWordTests/Writer/Word2007/StyleTest.php @@ -19,6 +19,9 @@ namespace PhpOffice\PhpWordTests\Writer\Word2007; use PhpOffice\PhpWord\Shared\XMLWriter; +use PhpOffice\PhpWord\Writer\Word2007\Style\Frame; +use PhpOffice\PhpWord\Writer\Word2007\Style\Line; +use PhpOffice\PhpWord\Writer\Word2007\Style\TextBox; /** * Test class for PhpOffice\PhpWord\Writer\Word2007\Style subnamespace. @@ -48,20 +51,36 @@ public function testEmptyStyles(): void /** * Test method exceptions. */ - public function testMethodExceptions(): void + public function testMethodExceptionsFrame(): void { - $styles = [ - 'Frame' => 'writeAlignment', - 'Line' => 'writeStroke', - 'TextBox' => 'writeBorder', - ]; - foreach ($styles as $style => $method) { - $objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Style\\' . $style; - $xmlWriter = new XMLWriter(); - $object = new $objectClass($xmlWriter); - $object->$method(); + $xmlWriter = new XMLWriter(); + $object = new Frame($xmlWriter); + $object->writeAlignment(); - self::assertEquals('', $xmlWriter->getData()); - } + self::assertEquals('', $xmlWriter->getData()); + } + + /** + * Test method exceptions. + */ + public function testMethodExceptionsLine(): void + { + $xmlWriter = new XMLWriter(); + $object = new Line($xmlWriter); + $object->writeStroke(); + + self::assertEquals('', $xmlWriter->getData()); + } + + /** + * Test method exceptions. + */ + public function testMethodExceptionsTextBox(): void + { + $xmlWriter = new XMLWriter(); + $object = new TextBox($xmlWriter); + $object->writeBorder(); + + self::assertEquals('', $xmlWriter->getData()); } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index f9e0ca2388..d94d68d880 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -59,6 +59,7 @@ function utf8decode(string $value, string $toEncoding = 'ISO-8859-1'): string return $result === false ? '' : $result; } +// @phpstan-ignore-next-line if (!method_exists(PHPUnit\Framework\TestCase::class, 'setOutputCallback')) { ini_set('error_reporting', (string) E_ALL); set_error_handler('phpunit10ErrorHandler');

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%0Dd|ys(|72LHx*7?WSRU>I#W(p{eg!)q@zw( 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