Skip to content

Commit 41cf4eb

Browse files
authoredJan 8, 2024
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
1 parent 98d038e commit 41cf4eb

File tree

4 files changed

+49
-46
lines changed

4 files changed

+49
-46
lines changed
 

‎docs/changes/1.x/1.2.0.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,5 @@
6464

6565

6666
### BC Breaks
67-
- Removed dependency `laminas/laminas-escaper`
67+
- Removed dependency `laminas/laminas-escaper`
68+
- *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

‎docs/changes/2.x/2.0.0.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
### Bug fixes
1010

1111
- 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)
12-
12+
- 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)
1313
- 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)
1414

1515
### Miscellaneous

‎src/PhpWord/TemplateProcessor.php

+5-12
Original file line numberDiff line numberDiff line change
@@ -146,18 +146,6 @@ public function __destruct()
146146
// Nothing to do here.
147147
}
148148
}
149-
// Temporary file
150-
if ($this->tempDocumentFilename && file_exists($this->tempDocumentFilename)) {
151-
unlink($this->tempDocumentFilename);
152-
}
153-
}
154-
155-
public function __wakeup(): void
156-
{
157-
$this->tempDocumentFilename = '';
158-
$this->zipClass = null;
159-
160-
throw new Exception('unserialize not permitted for this class');
161149
}
162150

163151
/**
@@ -1506,4 +1494,9 @@ public function setMacroChars(string $macroOpeningChars, string $macroClosingCha
15061494
self::$macroOpeningChars = $macroOpeningChars;
15071495
self::$macroClosingChars = $macroClosingChars;
15081496
}
1497+
1498+
public function getTempDocumentFilename(): string
1499+
{
1500+
return $this->tempDocumentFilename;
1501+
}
15091502
}

‎tests/PhpWordTests/TemplateProcessorTest.php

+41-32
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
use Exception;
2222
use PhpOffice\PhpWord\Element\Text;
2323
use PhpOffice\PhpWord\Element\TextRun;
24-
use PhpOffice\PhpWord\Exception\Exception as WordException;
2524
use PhpOffice\PhpWord\IOFactory;
2625
use PhpOffice\PhpWord\PhpWord;
2726
use PhpOffice\PhpWord\Settings;
@@ -38,14 +37,36 @@
3837
*/
3938
final class TemplateProcessorTest extends \PHPUnit\Framework\TestCase
4039
{
40+
/** @var ?TemplateProcessor */
41+
private $templateProcessor;
42+
43+
private function getTemplateProcessor(string $filename): TemplateProcessor
44+
{
45+
$this->templateProcessor = new TemplateProcessor($filename);
46+
47+
return $this->templateProcessor;
48+
}
49+
50+
protected function tearDown(): void
51+
{
52+
if ($this->templateProcessor !== null) {
53+
$filename = $this->templateProcessor->getTempDocumentFilename();
54+
$this->templateProcessor = null;
55+
if (file_exists($filename)) {
56+
@unlink($filename);
57+
}
58+
}
59+
}
60+
4161
/**
4262
* Construct test.
4363
*
4464
* @covers ::__construct
65+
* @covers ::__destruct
4566
*/
4667
public function testTheConstruct(): void
4768
{
48-
$object = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx');
69+
$object = $this->getTemplateProcessor(__DIR__ . '/_files/templates/blank.docx');
4970
self::assertInstanceOf('PhpOffice\\PhpWord\\TemplateProcessor', $object);
5071
self::assertEquals([], $object->getVariables());
5172
}
@@ -106,7 +127,7 @@ public function xtestTemplateCanBeSavedInTemporaryLocation(string $templateFqfn,
106127
public function testXslStyleSheetCanBeApplied(): void
107128
{
108129
$templateFqfn = __DIR__ . '/_files/templates/with_table_macros.docx';
109-
$templateProcessor = new TemplateProcessor($templateFqfn);
130+
$templateProcessor = $this->getTemplateProcessor($templateFqfn);
110131

111132
$actualDocumentFqfn = $this->xtestTemplateCanBeSavedInTemporaryLocation($templateFqfn, $templateProcessor);
112133
$expectedDocumentFqfn = __DIR__ . '/_files/documents/without_table_macros.docx';
@@ -150,7 +171,7 @@ public function testXslStyleSheetCanNotBeAppliedOnFailureOfSettingParameterValue
150171
$this->expectExceptionMessage('Could not set values for the given XSL style sheet parameters.');
151172
}
152173

153-
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx');
174+
$templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/blank.docx');
154175

155176
$xslDomDocument = new DOMDocument();
156177
$xslDomDocument->load(__DIR__ . '/_files/xsl/passthrough.xsl');
@@ -171,7 +192,7 @@ public function testXslStyleSheetCanNotBeAppliedOnFailureOfLoadingXmlFromTemplat
171192
{
172193
$this->expectException(\PhpOffice\PhpWord\Exception\Exception::class);
173194
$this->expectExceptionMessage('Could not load the given XML document.');
174-
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/corrupted_main_document_part.docx');
195+
$templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/corrupted_main_document_part.docx');
175196

176197
$xslDomDocument = new DOMDocument();
177198
$xslDomDocument->load(__DIR__ . '/_files/xsl/passthrough.xsl');
@@ -190,7 +211,7 @@ public function testXslStyleSheetCanNotBeAppliedOnFailureOfLoadingXmlFromTemplat
190211
*/
191212
public function testDeleteRow(): void
192213
{
193-
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/delete-row.docx');
214+
$templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/delete-row.docx');
194215

195216
self::assertEquals(
196217
['deleteMe', 'deleteMeToo'],
@@ -216,7 +237,7 @@ public function testDeleteRow(): void
216237
*/
217238
public function testCloneRow(): void
218239
{
219-
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx');
240+
$templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx');
220241

221242
self::assertEquals(
222243
['tableHeader', 'userId', 'userName', 'userLocation'],
@@ -240,7 +261,7 @@ public function testCloneRow(): void
240261
*/
241262
public function testCloneRowWithCustomMacro(): void
242263
{
243-
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx');
264+
$templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx');
244265

245266
$templateProcessor->setMacroOpeningChars('{#');
246267
$templateProcessor->setMacroClosingChars('#}');
@@ -397,7 +418,7 @@ public function testCloneRowAndSetValuesWithCustomMacro(): void
397418
*/
398419
public function testMacrosCanBeReplacedInHeaderAndFooter(): void
399420
{
400-
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx');
421+
$templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx');
401422

402423
self::assertEquals(['documentContent', 'headerValue:100:100', 'footerValue'], $templateProcessor->getVariables());
403424

@@ -418,7 +439,7 @@ public function testMacrosCanBeReplacedInHeaderAndFooter(): void
418439
*/
419440
public function testCustomMacrosCanBeReplacedInHeaderAndFooter(): void
420441
{
421-
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer-with-custom-macro.docx');
442+
$templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/header-footer-with-custom-macro.docx');
422443
$templateProcessor->setMacroOpeningChars('{{');
423444
$templateProcessor->setMacroClosingChars('}}');
424445

@@ -440,7 +461,7 @@ public function testCustomMacrosCanBeReplacedInHeaderAndFooter(): void
440461
*/
441462
public function testSetValue(): void
442463
{
443-
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx');
464+
$templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx');
444465
Settings::setOutputEscapingEnabled(true);
445466
$helloworld = "hello\nworld";
446467
$templateProcessor->setValue('userName', $helloworld);
@@ -455,7 +476,7 @@ public function testSetValue(): void
455476
*/
456477
public function testSetValueWithCustomMacro(): void
457478
{
458-
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx');
479+
$templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/clone-merge-with-custom-macro.docx');
459480
$templateProcessor->setMacroChars('{#', '#}');
460481
Settings::setOutputEscapingEnabled(true);
461482
$helloworld = "hello\nworld";
@@ -786,7 +807,7 @@ public function testSetCheckboxWithCustomMacro(): void
786807
*/
787808
public function testSetImageValue(): void
788809
{
789-
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx');
810+
$templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx');
790811
$imagePath = __DIR__ . '/_files/images/earth.jpg';
791812

792813
$variablesReplace = [
@@ -866,7 +887,7 @@ public function testSetImageValue(): void
866887
*/
867888
public function testCloneDeleteBlock(): void
868889
{
869-
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-delete-block.docx');
890+
$templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/clone-delete-block.docx');
870891

871892
self::assertEquals(
872893
['DELETEME', '/DELETEME', 'CLONEME', 'blockVariable', '/CLONEME'],
@@ -906,7 +927,7 @@ public function testGetVariableCountCountsHowManyTimesEachPlaceholderIsPresent()
906927
$templatePath = 'test.docx';
907928
$objWriter->save($templatePath);
908929

909-
$templateProcessor = new TemplateProcessor($templatePath);
930+
$templateProcessor = $this->getTemplateProcessor($templatePath);
910931
$variableCount = $templateProcessor->getVariableCount();
911932
unlink($templatePath);
912933

@@ -943,7 +964,7 @@ public function testGetVariableCountCountsHowManyTimesEachPlaceholderIsPresentWi
943964
$templatePath = 'test.docx';
944965
$objWriter->save($templatePath);
945966

946-
$templateProcessor = new TemplateProcessor($templatePath);
967+
$templateProcessor = $this->getTemplateProcessor($templatePath);
947968
$templateProcessor->setMacroChars('{{', '}}');
948969
$variableCount = $templateProcessor->getVariableCount();
949970
unlink($templatePath);
@@ -981,7 +1002,7 @@ public function testCloneBlockCanCloneABlockTwice(): void
9811002
$objWriter->save($templatePath);
9821003

9831004
// replace placeholders and save the file
984-
$templateProcessor = new TemplateProcessor($templatePath);
1005+
$templateProcessor = $this->getTemplateProcessor($templatePath);
9851006
$templateProcessor->setValue('title', 'Some title');
9861007
$templateProcessor->cloneBlock('subreport', 2);
9871008
$templateProcessor->setValue('subreport.id', '123', 1);
@@ -1034,7 +1055,7 @@ public function testCloneBlockCanCloneABlockTwiceWithCustomMacro(): void
10341055
$objWriter->save($templatePath);
10351056

10361057
// replace placeholders and save the file
1037-
$templateProcessor = new TemplateProcessor($templatePath);
1058+
$templateProcessor = $this->getTemplateProcessor($templatePath);
10381059
$templateProcessor->setMacroChars('{{', '}}');
10391060
$templateProcessor->setValue('title', 'Some title');
10401061
$templateProcessor->cloneBlock('subreport', 2);
@@ -1323,7 +1344,7 @@ public function testFixBrokenMacrosWithCustomMacro(): void
13231344
*/
13241345
public function testMainPartNameDetection(): void
13251346
{
1326-
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/document22-xml.docx');
1347+
$templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/document22-xml.docx');
13271348

13281349
$variables = ['test'];
13291350

@@ -1335,7 +1356,7 @@ public function testMainPartNameDetection(): void
13351356
*/
13361357
public function testMainPartNameDetectionWithCustomMacro(): void
13371358
{
1338-
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/document22-with-custom-macro-xml.docx');
1359+
$templateProcessor = $this->getTemplateProcessor(__DIR__ . '/_files/templates/document22-with-custom-macro-xml.docx');
13391360
$templateProcessor->setMacroOpeningChars('{#');
13401361
$templateProcessor->setMacroClosingChars('#}');
13411362
$variables = ['test'];
@@ -1595,18 +1616,6 @@ public function testShouldMakeFieldsUpdateOnOpen(): void
15951616
self::assertStringContainsString('<w:updateFields w:val="false"/>', $templateProcessor->getSettingsPart());
15961617
}
15971618

1598-
/**
1599-
* Should not allow unserialize to avoid malware.
1600-
*/
1601-
public function testUnserialize(): void
1602-
{
1603-
$this->expectException(WordException::class);
1604-
$this->expectExceptionMessage('unserialize not permitted');
1605-
$object = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx');
1606-
$serialized = serialize($object);
1607-
$object2 = unserialize($serialized);
1608-
}
1609-
16101619
public function testShouldMakeFieldsUpdateOnOpenWithCustomMacro(): void
16111620
{
16121621
$settingsPart = '<w:settings xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">

0 commit comments

Comments
 (0)
Please sign in to comment.