diff --git a/docs/changes/1.x/1.3.0.md b/docs/changes/1.x/1.3.0.md index 4e38e38f91..2496313bf3 100644 --- a/docs/changes/1.x/1.3.0.md +++ b/docs/changes/1.x/1.3.0.md @@ -27,8 +27,6 @@ - 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) -- 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 @@ -45,5 +43,6 @@ - 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) +- 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) ### BC Breaks diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index f6fe1d8887..5fd790674b 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); } } @@ -893,7 +893,7 @@ public function cloneRowAndSetValues($search, $values): void * * @return null|string */ - public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVariables = false, $variableReplacements = null) + public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVariables = false, $variableReplacements = null, int $limit = self::MAXIMUM_REPLACEMENTS_DEFAULT) { $xmlBlock = null; $matches = []; @@ -921,11 +921,21 @@ public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVaria } if ($replace) { - $this->tempDocumentMainPart = str_replace( - $matches[2] . $matches[3] . $matches[4], - implode('', $cloned), - $this->tempDocumentMainPart - ); + if (self::MAXIMUM_REPLACEMENTS_DEFAULT === $limit) { + $this->tempDocumentMainPart = str_replace( + $matches[2] . $matches[3] . $matches[4], + implode('', $cloned), + $this->tempDocumentMainPart + ); + } else { + $regExpEscaper = new RegExp(); + $this->tempDocumentMainPart = preg_replace( + $regExpEscaper->escape($matches[2] . $matches[3] . $matches[4]), + implode('', $cloned), + $this->tempDocumentMainPart, + $limit + ); + } } } diff --git a/tests/PhpWordTests/TemplateProcessorTest.php b/tests/PhpWordTests/TemplateProcessorTest.php index b8ad970ced..a88c8cf7a0 100644 --- a/tests/PhpWordTests/TemplateProcessorTest.php +++ b/tests/PhpWordTests/TemplateProcessorTest.php @@ -614,12 +614,53 @@ public function testSetValues(): void Hello ${firstname} ${lastname} - '; + + + + Hello ${firstname} ${lastname} + + + + + Hello ${firstname} ${lastname} + + + '; $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']); } /**