Skip to content

Feature: add limit option to cloneBlock #2641

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 19 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
9660d59
adding limit option to setValues for multiple values
moghwan Jul 12, 2024
5fbf82c
add parameter type
moghwan Jul 12, 2024
8ae7312
Update 2.0.0.md
moghwan Jul 12, 2024
2bb2190
adding limit oprion to cloneblock
moghwan Aug 4, 2024
eb5f82b
phpcs improved
moghwan Aug 4, 2024
ca05abb
Merge branch 'master' of github.com:moghwan/PHPWord into feat/add-lim…
moghwan Aug 26, 2024
18728f0
Merge branch 'feat/add-limit-to-cloneblock' of github.com:moghwan/PHP…
moghwan Aug 26, 2024
5ed31c4
Merge branch 'master' of github.com:moghwan/PHPWord into feat/add-lim…
moghwan Aug 26, 2024
88a2646
add more replacement for testSetValues
moghwan Aug 27, 2024
16a6f23
testSetValues with different limit values
moghwan Aug 27, 2024
98d0127
Merge branch 'master' of github.com:moghwan/PHPWord into feat/add-lim…
moghwan Aug 27, 2024
aa13b54
testSetValues with a zero replacement
moghwan Aug 27, 2024
e58a590
Update 1.3.0.md
moghwan Aug 27, 2024
32b796d
improve tests with variables count check to ensure number of occurren…
moghwan Aug 27, 2024
8d5d1aa
Merge remote-tracking branch 'origin/feat/add-limit-to-setvalues' int…
moghwan Aug 27, 2024
b4ca413
Merge pull request #1 from moghwan/feat/add-limit-to-setvalues
moghwan Sep 23, 2024
2aae591
Merge branch 'leyton-stt' of github.com:moghwan/PHPWord into feat/add…
moghwan Sep 24, 2024
299f18e
improve large regex expression
moghwan Dec 18, 2024
4a9583b
Update TemplateProcessor.php
moghwan Dec 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions docs/changes/1.x/1.3.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
36 changes: 28 additions & 8 deletions src/PhpWord/TemplateProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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 = [];
Expand Down Expand Up @@ -921,11 +921,31 @@ 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();

// Process each match individually to avoid a single large regex
foreach ($matches as $key => $match) {
if (isset($matches[2][$key], $matches[3][$key], $matches[4][$key])) {
$escapedPattern = $regExpEscaper->escape(
$matches[2][$key] . $matches[3][$key] . $matches[4][$key]
);

$this->tempDocumentMainPart = preg_replace(
$escapedPattern,
is_array($cloned) ? implode('', $cloned) : $cloned,
$this->tempDocumentMainPart,
$limit
);
}
}
}
}
}

Expand Down
45 changes: 43 additions & 2 deletions tests/PhpWordTests/TemplateProcessorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -614,12 +614,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']);
}

/**
Expand Down