From ed1d5b8f3365ee17d95faf63e93f0f7a45dcf446 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Fri, 5 Jan 2024 17:11:46 -0800 Subject: [PATCH 1/4] TemplateProcessor Persist File After Destruct Fix #2539. Inadvertent break in TemplateProcessor behavior with #2475. Deleted temp file on destruct. It will now persist, restoring prior behavior, unless user specifies otherwise in constructor. --- src/PhpWord/TemplateProcessor.php | 13 +++- tests/PhpWordTests/TemplateProcessorTest.php | 69 ++++++++++++++------ 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index f740212a2c..2ef07db328 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -99,13 +99,22 @@ class TemplateProcessor protected static $macroClosingChars = '}'; + /** + * Delete temp file at destruct? + * + * @var bool + */ + protected $deleteAtDestruct = false; + /** * @since 0.12.0 Throws CreateTemporaryFileException and CopyFileException instead of Exception * * @param string $documentTemplate The fully qualified template filename + * @param bool $deleteAtDestruct Delete temp file at destruct */ - public function __construct($documentTemplate) + public function __construct($documentTemplate, $deleteAtDestruct = false) { + $this->deleteAtDestruct = $deleteAtDestruct; // Temporary document filename initialization $this->tempDocumentFilename = tempnam(Settings::getTempDir(), 'PhpWord'); if (false === $this->tempDocumentFilename) { @@ -147,7 +156,7 @@ public function __destruct() } } // Temporary file - if ($this->tempDocumentFilename && file_exists($this->tempDocumentFilename)) { + if ($this->deleteAtDestruct && $this->tempDocumentFilename && file_exists($this->tempDocumentFilename)) { unlink($this->tempDocumentFilename); } } diff --git a/tests/PhpWordTests/TemplateProcessorTest.php b/tests/PhpWordTests/TemplateProcessorTest.php index 843ac798e2..3b814afe8c 100644 --- a/tests/PhpWordTests/TemplateProcessorTest.php +++ b/tests/PhpWordTests/TemplateProcessorTest.php @@ -38,16 +38,45 @@ */ final class TemplateProcessorTest extends \PHPUnit\Framework\TestCase { + private const DELETE_AT_DESTRUCT = true; + /** * Construct test. * * @covers ::__construct + * @covers ::__destruct */ public function testTheConstruct(): void { - $object = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); + $object = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx', self::DELETE_AT_DESTRUCT); self::assertInstanceOf('PhpOffice\\PhpWord\\TemplateProcessor', $object); self::assertEquals([], $object->getVariables()); + $filename1 = $object->save(); + self::assertFileExists($filename1); + unset($object); + gc_collect_cycles(); + if (method_exists(self::class, 'assertFileDoesNotExist')) { + self::assertFileDoesNotExist($filename1); + } else { + self::assertFileNotExists($filename1); + } + } + + /** + * Do not delete tempfile test. + * + * @covers ::__construct + * @covers ::__destruct + */ + public function testDoNotDeleteTempfile(): void + { + $object = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); + $filename1 = $object->save(); + self::assertFileExists($filename1); + unset($object); + gc_collect_cycles(); + self::assertFileExists($filename1); + @unlink($filename1); } /** @@ -106,7 +135,7 @@ public function xtestTemplateCanBeSavedInTemporaryLocation(string $templateFqfn, public function testXslStyleSheetCanBeApplied(): void { $templateFqfn = __DIR__ . '/_files/templates/with_table_macros.docx'; - $templateProcessor = new TemplateProcessor($templateFqfn); + $templateProcessor = new TemplateProcessor($templateFqfn, self::DELETE_AT_DESTRUCT); $actualDocumentFqfn = $this->xtestTemplateCanBeSavedInTemporaryLocation($templateFqfn, $templateProcessor); $expectedDocumentFqfn = __DIR__ . '/_files/documents/without_table_macros.docx'; @@ -150,7 +179,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 = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx', self::DELETE_AT_DESTRUCT); $xslDomDocument = new DOMDocument(); $xslDomDocument->load(__DIR__ . '/_files/xsl/passthrough.xsl'); @@ -171,7 +200,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 = new TemplateProcessor(__DIR__ . '/_files/templates/corrupted_main_document_part.docx', self::DELETE_AT_DESTRUCT); $xslDomDocument = new DOMDocument(); $xslDomDocument->load(__DIR__ . '/_files/xsl/passthrough.xsl'); @@ -190,7 +219,7 @@ public function testXslStyleSheetCanNotBeAppliedOnFailureOfLoadingXmlFromTemplat */ public function testDeleteRow(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/delete-row.docx'); + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/delete-row.docx', self::DELETE_AT_DESTRUCT); self::assertEquals( ['deleteMe', 'deleteMeToo'], @@ -216,7 +245,7 @@ public function testDeleteRow(): void */ public function testCloneRow(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx'); + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx', self::DELETE_AT_DESTRUCT); self::assertEquals( ['tableHeader', 'userId', 'userName', 'userLocation'], @@ -240,7 +269,7 @@ public function testCloneRow(): void */ public function testCloneRowWithCustomMacro(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx'); + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx', self::DELETE_AT_DESTRUCT); $templateProcessor->setMacroOpeningChars('{#'); $templateProcessor->setMacroClosingChars('#}'); @@ -397,7 +426,7 @@ public function testCloneRowAndSetValuesWithCustomMacro(): void */ public function testMacrosCanBeReplacedInHeaderAndFooter(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx'); + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx', self::DELETE_AT_DESTRUCT); self::assertEquals(['documentContent', 'headerValue:100:100', 'footerValue'], $templateProcessor->getVariables()); @@ -418,7 +447,7 @@ public function testMacrosCanBeReplacedInHeaderAndFooter(): void */ public function testCustomMacrosCanBeReplacedInHeaderAndFooter(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer-with-custom-macro.docx'); + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer-with-custom-macro.docx', self::DELETE_AT_DESTRUCT); $templateProcessor->setMacroOpeningChars('{{'); $templateProcessor->setMacroClosingChars('}}'); @@ -440,7 +469,7 @@ public function testCustomMacrosCanBeReplacedInHeaderAndFooter(): void */ public function testSetValue(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx'); + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx', self::DELETE_AT_DESTRUCT); Settings::setOutputEscapingEnabled(true); $helloworld = "hello\nworld"; $templateProcessor->setValue('userName', $helloworld); @@ -455,7 +484,7 @@ public function testSetValue(): void */ public function testSetValueWithCustomMacro(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx'); + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx', self::DELETE_AT_DESTRUCT); $templateProcessor->setMacroChars('{#', '#}'); Settings::setOutputEscapingEnabled(true); $helloworld = "hello\nworld"; @@ -615,7 +644,7 @@ public function testSetValuesWithCustomMacro(): void */ public function testSetImageValue(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx'); + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx', self::DELETE_AT_DESTRUCT); $imagePath = __DIR__ . '/_files/images/earth.jpg'; $variablesReplace = [ @@ -695,7 +724,7 @@ public function testSetImageValue(): void */ public function testCloneDeleteBlock(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-delete-block.docx'); + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-delete-block.docx', self::DELETE_AT_DESTRUCT); self::assertEquals( ['DELETEME', '/DELETEME', 'CLONEME', 'blockVariable', '/CLONEME'], @@ -735,7 +764,7 @@ public function testGetVariableCountCountsHowManyTimesEachPlaceholderIsPresent() $templatePath = 'test.docx'; $objWriter->save($templatePath); - $templateProcessor = new TemplateProcessor($templatePath); + $templateProcessor = new TemplateProcessor($templatePath, self::DELETE_AT_DESTRUCT); $variableCount = $templateProcessor->getVariableCount(); unlink($templatePath); @@ -772,7 +801,7 @@ public function testGetVariableCountCountsHowManyTimesEachPlaceholderIsPresentWi $templatePath = 'test.docx'; $objWriter->save($templatePath); - $templateProcessor = new TemplateProcessor($templatePath); + $templateProcessor = new TemplateProcessor($templatePath, self::DELETE_AT_DESTRUCT); $templateProcessor->setMacroChars('{{', '}}'); $variableCount = $templateProcessor->getVariableCount(); unlink($templatePath); @@ -810,7 +839,7 @@ public function testCloneBlockCanCloneABlockTwice(): void $objWriter->save($templatePath); // replace placeholders and save the file - $templateProcessor = new TemplateProcessor($templatePath); + $templateProcessor = new TemplateProcessor($templatePath, self::DELETE_AT_DESTRUCT); $templateProcessor->setValue('title', 'Some title'); $templateProcessor->cloneBlock('subreport', 2); $templateProcessor->setValue('subreport.id', '123', 1); @@ -863,7 +892,7 @@ public function testCloneBlockCanCloneABlockTwiceWithCustomMacro(): void $objWriter->save($templatePath); // replace placeholders and save the file - $templateProcessor = new TemplateProcessor($templatePath); + $templateProcessor = new TemplateProcessor($templatePath, self::DELETE_AT_DESTRUCT); $templateProcessor->setMacroChars('{{', '}}'); $templateProcessor->setValue('title', 'Some title'); $templateProcessor->cloneBlock('subreport', 2); @@ -1152,7 +1181,7 @@ public function testFixBrokenMacrosWithCustomMacro(): void */ public function testMainPartNameDetection(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/document22-xml.docx'); + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/document22-xml.docx', self::DELETE_AT_DESTRUCT); $variables = ['test']; @@ -1164,7 +1193,7 @@ public function testMainPartNameDetection(): void */ public function testMainPartNameDetectionWithCustomMacro(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/document22-with-custom-macro-xml.docx'); + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/document22-with-custom-macro-xml.docx', self::DELETE_AT_DESTRUCT); $templateProcessor->setMacroOpeningChars('{#'); $templateProcessor->setMacroClosingChars('#}'); $variables = ['test']; @@ -1431,7 +1460,7 @@ public function testUnserialize(): void { $this->expectException(WordException::class); $this->expectExceptionMessage('unserialize not permitted'); - $object = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); + $object = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx', self::DELETE_AT_DESTRUCT); $serialized = serialize($object); $object2 = unserialize($serialized); } From f8059d8cdaa54d663069d9f586c498860eb9afc0 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Sat, 6 Jan 2024 09:27:40 -0800 Subject: [PATCH 2/4] Less Complicated Approach --- src/PhpWord/TemplateProcessor.php | 29 ++---- tests/PhpWordTests/TemplateProcessorTest.php | 96 ++++++++------------ 2 files changed, 46 insertions(+), 79 deletions(-) diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 2ef07db328..443f4ead54 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -99,22 +99,13 @@ class TemplateProcessor protected static $macroClosingChars = '}'; - /** - * Delete temp file at destruct? - * - * @var bool - */ - protected $deleteAtDestruct = false; - /** * @since 0.12.0 Throws CreateTemporaryFileException and CopyFileException instead of Exception * * @param string $documentTemplate The fully qualified template filename - * @param bool $deleteAtDestruct Delete temp file at destruct */ - public function __construct($documentTemplate, $deleteAtDestruct = false) + public function __construct($documentTemplate) { - $this->deleteAtDestruct = $deleteAtDestruct; // Temporary document filename initialization $this->tempDocumentFilename = tempnam(Settings::getTempDir(), 'PhpWord'); if (false === $this->tempDocumentFilename) { @@ -155,18 +146,6 @@ public function __destruct() // Nothing to do here. } } - // Temporary file - if ($this->deleteAtDestruct && $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'); } /** @@ -1003,6 +982,12 @@ public function save() return $this->tempDocumentFilename; } + /** @return string */ + public function getTempDocumentFilename() + { + return $this->tempDocumentFilename; + } + /** * @param string $fileName * @param string $xml diff --git a/tests/PhpWordTests/TemplateProcessorTest.php b/tests/PhpWordTests/TemplateProcessorTest.php index 3b814afe8c..5fcd9e35ce 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,45 +37,40 @@ */ final class TemplateProcessorTest extends \PHPUnit\Framework\TestCase { - private const DELETE_AT_DESTRUCT = true; + /** @var ?TemplateProcessor */ + private $templateProcessor; - /** - * Construct test. - * - * @covers ::__construct - * @covers ::__destruct - */ - public function testTheConstruct(): void + private function getTemplateProcessor(string $filename): TemplateProcessor { - $object = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx', self::DELETE_AT_DESTRUCT); - self::assertInstanceOf('PhpOffice\\PhpWord\\TemplateProcessor', $object); - self::assertEquals([], $object->getVariables()); - $filename1 = $object->save(); - self::assertFileExists($filename1); - unset($object); - gc_collect_cycles(); - if (method_exists(self::class, 'assertFileDoesNotExist')) { - self::assertFileDoesNotExist($filename1); - } else { - self::assertFileNotExists($filename1); + $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); + } } } /** - * Do not delete tempfile test. + * Construct test. * * @covers ::__construct * @covers ::__destruct */ - public function testDoNotDeleteTempfile(): void + 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()); $filename1 = $object->save(); self::assertFileExists($filename1); - unset($object); - gc_collect_cycles(); - self::assertFileExists($filename1); - @unlink($filename1); } /** @@ -135,7 +129,7 @@ public function xtestTemplateCanBeSavedInTemporaryLocation(string $templateFqfn, public function testXslStyleSheetCanBeApplied(): void { $templateFqfn = __DIR__ . '/_files/templates/with_table_macros.docx'; - $templateProcessor = new TemplateProcessor($templateFqfn, self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor($templateFqfn); $actualDocumentFqfn = $this->xtestTemplateCanBeSavedInTemporaryLocation($templateFqfn, $templateProcessor); $expectedDocumentFqfn = __DIR__ . '/_files/documents/without_table_macros.docx'; @@ -179,7 +173,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', self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); $xslDomDocument = new DOMDocument(); $xslDomDocument->load(__DIR__ . '/_files/xsl/passthrough.xsl'); @@ -200,7 +194,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', self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/corrupted_main_document_part.docx'); $xslDomDocument = new DOMDocument(); $xslDomDocument->load(__DIR__ . '/_files/xsl/passthrough.xsl'); @@ -219,7 +213,7 @@ public function testXslStyleSheetCanNotBeAppliedOnFailureOfLoadingXmlFromTemplat */ public function testDeleteRow(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/delete-row.docx', self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/delete-row.docx'); self::assertEquals( ['deleteMe', 'deleteMeToo'], @@ -245,7 +239,7 @@ public function testDeleteRow(): void */ public function testCloneRow(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx', self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx'); self::assertEquals( ['tableHeader', 'userId', 'userName', 'userLocation'], @@ -269,7 +263,7 @@ public function testCloneRow(): void */ public function testCloneRowWithCustomMacro(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx', self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx'); $templateProcessor->setMacroOpeningChars('{#'); $templateProcessor->setMacroClosingChars('#}'); @@ -426,7 +420,7 @@ public function testCloneRowAndSetValuesWithCustomMacro(): void */ public function testMacrosCanBeReplacedInHeaderAndFooter(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx', self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx'); self::assertEquals(['documentContent', 'headerValue:100:100', 'footerValue'], $templateProcessor->getVariables()); @@ -447,7 +441,7 @@ public function testMacrosCanBeReplacedInHeaderAndFooter(): void */ public function testCustomMacrosCanBeReplacedInHeaderAndFooter(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer-with-custom-macro.docx', self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/header-footer-with-custom-macro.docx'); $templateProcessor->setMacroOpeningChars('{{'); $templateProcessor->setMacroClosingChars('}}'); @@ -469,7 +463,7 @@ public function testCustomMacrosCanBeReplacedInHeaderAndFooter(): void */ public function testSetValue(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx', self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx'); Settings::setOutputEscapingEnabled(true); $helloworld = "hello\nworld"; $templateProcessor->setValue('userName', $helloworld); @@ -484,7 +478,7 @@ public function testSetValue(): void */ public function testSetValueWithCustomMacro(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx', self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx'); $templateProcessor->setMacroChars('{#', '#}'); Settings::setOutputEscapingEnabled(true); $helloworld = "hello\nworld"; @@ -644,7 +638,7 @@ public function testSetValuesWithCustomMacro(): void */ public function testSetImageValue(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx', self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx'); $imagePath = __DIR__ . '/_files/images/earth.jpg'; $variablesReplace = [ @@ -724,7 +718,7 @@ public function testSetImageValue(): void */ public function testCloneDeleteBlock(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-delete-block.docx', self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/clone-delete-block.docx'); self::assertEquals( ['DELETEME', '/DELETEME', 'CLONEME', 'blockVariable', '/CLONEME'], @@ -764,7 +758,7 @@ public function testGetVariableCountCountsHowManyTimesEachPlaceholderIsPresent() $templatePath = 'test.docx'; $objWriter->save($templatePath); - $templateProcessor = new TemplateProcessor($templatePath, self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor($templatePath); $variableCount = $templateProcessor->getVariableCount(); unlink($templatePath); @@ -801,7 +795,7 @@ public function testGetVariableCountCountsHowManyTimesEachPlaceholderIsPresentWi $templatePath = 'test.docx'; $objWriter->save($templatePath); - $templateProcessor = new TemplateProcessor($templatePath, self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor($templatePath); $templateProcessor->setMacroChars('{{', '}}'); $variableCount = $templateProcessor->getVariableCount(); unlink($templatePath); @@ -839,7 +833,7 @@ public function testCloneBlockCanCloneABlockTwice(): void $objWriter->save($templatePath); // replace placeholders and save the file - $templateProcessor = new TemplateProcessor($templatePath, self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor($templatePath); $templateProcessor->setValue('title', 'Some title'); $templateProcessor->cloneBlock('subreport', 2); $templateProcessor->setValue('subreport.id', '123', 1); @@ -892,7 +886,7 @@ public function testCloneBlockCanCloneABlockTwiceWithCustomMacro(): void $objWriter->save($templatePath); // replace placeholders and save the file - $templateProcessor = new TemplateProcessor($templatePath, self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor($templatePath); $templateProcessor->setMacroChars('{{', '}}'); $templateProcessor->setValue('title', 'Some title'); $templateProcessor->cloneBlock('subreport', 2); @@ -1181,7 +1175,7 @@ public function testFixBrokenMacrosWithCustomMacro(): void */ public function testMainPartNameDetection(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/document22-xml.docx', self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/document22-xml.docx'); $variables = ['test']; @@ -1193,7 +1187,7 @@ public function testMainPartNameDetection(): void */ public function testMainPartNameDetectionWithCustomMacro(): void { - $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/document22-with-custom-macro-xml.docx', self::DELETE_AT_DESTRUCT); + $templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/document22-with-custom-macro-xml.docx'); $templateProcessor->setMacroOpeningChars('{#'); $templateProcessor->setMacroClosingChars('#}'); $variables = ['test']; @@ -1453,18 +1447,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', self::DELETE_AT_DESTRUCT); - $serialized = serialize($object); - $object2 = unserialize($serialized); - } - public function testShouldMakeFieldsUpdateOnOpenWithCustomMacro(): void { $settingsPart = ' From 7e92c2956615bbd5351927038ae583e0db4d8f74 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Sun, 7 Jan 2024 09:30:02 -0800 Subject: [PATCH 3/4] Update Change Logs plus One Very Minor Code Change --- docs/changes/1.x/1.2.0.md | 3 ++- docs/changes/2.x/2.0.0.md | 22 ++++++++++++++++++++++ src/PhpWord/TemplateProcessor.php | 3 +-- 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 docs/changes/2.x/2.0.0.md diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index 1b8e1daea9..c2e0da6b3f 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -60,4 +60,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 [#2542](https://github.com/PHPOffice/PHPWord/pull/2542 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..c5806c994a --- /dev/null +++ b/docs/changes/2.x/2.0.0.md @@ -0,0 +1,22 @@ +# [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) +- TemplateProcessor Persist File After Destruct [@oleibman](https://github.com/oleibman) fixing [#2539](https://github.com/PHPOffice/PHPWord/issues/2539) in [#2542](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) +- 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) +- 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/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 443f4ead54..054790767c 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -982,8 +982,7 @@ public function save() return $this->tempDocumentFilename; } - /** @return string */ - public function getTempDocumentFilename() + public function getTempDocumentFilename(): string { return $this->tempDocumentFilename; } From 4b1844b0fb524e18c21e88c10004546aa7a240cb Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Sun, 7 Jan 2024 20:03:15 -0800 Subject: [PATCH 4/4] Update docs/changes/2.x/2.0.0.md Co-authored-by: Progi1984 --- docs/changes/2.x/2.0.0.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index c5806c994a..d1965a3f80 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -17,6 +17,5 @@ - 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