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 c679317049..c8450f666b 100644
--- a/docs/changes/2.x/2.0.0.md
+++ b/docs/changes/2.x/2.0.0.md
@@ -7,7 +7,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 = '