Skip to content

Commit

Permalink
Handle custom macro chars
Browse files Browse the repository at this point in the history
Update main regexp so that the full macro is matched (only `{{var}` was matched instead of `{{var}}`, which is a problem because we want to move tags after the whole macro)
  • Loading branch information
chapa committed Dec 1, 2023
1 parent 2a0307a commit 838b63e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 9 deletions.
22 changes: 16 additions & 6 deletions src/PhpWord/TemplateProcessor.php
Expand Up @@ -1063,14 +1063,24 @@ public function saveAs($fileName): void
*/
protected function fixBrokenMacros($documentPart)
{
$brokenMacroOpeningChars = substr(self::$macroOpeningChars, 0, 1);
$endMacroOpeningChars = substr(self::$macroOpeningChars, 1);
$macroClosingChars = self::$macroClosingChars;

return preg_replace_callback(
'/\\' . $brokenMacroOpeningChars . '(?:\\' . $endMacroOpeningChars . '|[^{$]*\>\{)[^' . $macroClosingChars . '$]*\}/U',
sprintf(
'/%s.+%s/U',
implode('', array_map(
function (string $char) {
return preg_quote($char) . '(?:<[^>]+>)*';
},
str_split(self::$macroOpeningChars)
)),
implode('', array_map(
function (string $char) {
return '(?:<[^>]+>)*' . preg_quote($char);
},
str_split(self::$macroClosingChars)
))
),
function ($match) {
preg_match_all('/<.+?\s*\/?\s*>/si', $match[0], $tags);
preg_match_all('/<[^>]+>/s', $match[0], $tags);
$tags = implode('', $tags[0]);
$tags = str_replace('<w:t>', '<w:t xml:space="preserve">', $tags);

Expand Down
18 changes: 15 additions & 3 deletions tests/PhpWordTests/TemplateProcessorTest.php
Expand Up @@ -1294,19 +1294,31 @@ public function testFixBrokenMacrosWithCustomMacro(): void
self::assertEquals('<w:r><w:t>{{documentContent}}</w:t></w:r>', $fixed);

$fixed = $templateProcessor->fixBrokenMacros('<w:r><w:t>{</w:t><w:t>{documentContent}}</w:t></w:r>');
self::assertEquals('<w:r><w:t>{{documentContent}}</w:t></w:r>', $fixed);
self::assertEquals('<w:r><w:t>{{documentContent}}</w:t><w:t xml:space="preserve"></w:t></w:r>', $fixed);

$fixed = $templateProcessor->fixBrokenMacros('<w:r><w:t>{</w:t><w:t>{documentContent}}</w:t></w:r>');
self::assertEquals('<w:r><w:t>{{documentContent}}</w:t><w:t xml:space="preserve"></w:t></w:r>', $fixed);

$fixed = $templateProcessor->fixBrokenMacros('<w:r><w:t>$1500</w:t><w:t>{{documentContent}}</w:t></w:r>');
self::assertEquals('<w:r><w:t>$1500</w:t><w:t>{{documentContent}}</w:t></w:r>', $fixed);

$fixed = $templateProcessor->fixBrokenMacros('<w:r><w:t>$1500</w:t><w:t>{</w:t><w:t>{documentContent}}</w:t></w:r>');
self::assertEquals('<w:r><w:t>$1500</w:t><w:t>{{documentContent}}</w:t></w:r>', $fixed);
self::assertEquals('<w:r><w:t>$1500</w:t><w:t>{{documentContent}}</w:t><w:t xml:space="preserve"></w:t></w:r>', $fixed);

$fixed = $templateProcessor->fixBrokenMacros('<w:r><w:t>25$ plus some info {hint}</w:t></w:r>');
self::assertEquals('<w:r><w:t>25$ plus some info {hint}</w:t></w:r>', $fixed);

$fixed = $templateProcessor->fixBrokenMacros('<w:t>$</w:t></w:r><w:bookmarkStart w:id="0" w:name="_GoBack"/><w:bookmarkEnd w:id="0"/><w:r><w:t xml:space="preserve">15,000.00. </w:t></w:r><w:r w:rsidR="0056499B"><w:t>{</w:t></w:r><w:r w:rsidR="00573DFD" w:rsidRPr="00573DFD"><w:rPr><w:iCs/></w:rPr><w:t>{</w:t></w:r><w:proofErr w:type="spellStart"/><w:r w:rsidR="00573DFD" w:rsidRPr="00573DFD"><w:rPr><w:iCs/></w:rPr><w:t>variable_name</w:t></w:r><w:proofErr w:type="spellEnd"/><w:r w:rsidR="00573DFD" w:rsidRPr="00573DFD"><w:rPr><w:iCs/></w:rPr><w:t>}}</w:t></w:r>');
self::assertEquals('<w:t>$</w:t></w:r><w:bookmarkStart w:id="0" w:name="_GoBack"/><w:bookmarkEnd w:id="0"/><w:r><w:t xml:space="preserve">15,000.00. </w:t></w:r><w:r w:rsidR="0056499B"><w:t>{{variable_name}}</w:t></w:r>', $fixed);
self::assertEquals('<w:t>$</w:t></w:r><w:bookmarkStart w:id="0" w:name="_GoBack"/><w:bookmarkEnd w:id="0"/><w:r><w:t xml:space="preserve">15,000.00. </w:t></w:r><w:r w:rsidR="0056499B"><w:t>{{variable_name}}</w:t></w:r><w:r w:rsidR="00573DFD" w:rsidRPr="00573DFD"><w:rPr><w:iCs/></w:rPr><w:t xml:space="preserve"></w:t></w:r><w:proofErr w:type="spellStart"/><w:r w:rsidR="00573DFD" w:rsidRPr="00573DFD"><w:rPr><w:iCs/></w:rPr><w:t xml:space="preserve"></w:t></w:r><w:proofErr w:type="spellEnd"/><w:r w:rsidR="00573DFD" w:rsidRPr="00573DFD"><w:rPr><w:iCs/></w:rPr><w:t xml:space="preserve"></w:t></w:r>', $fixed);

$fixed = $templateProcessor->fixBrokenMacros('<w:r><w:t>before {{</w:t></w:r><w:r><w:t xml:space="preserve">variable}} </w:t></w:r><w:r><w:t>after</w:t></w:r>');
self::assertEquals('<w:r><w:t>before {{variable}}</w:t></w:r><w:r><w:t xml:space="preserve"> </w:t></w:r><w:r><w:t>after</w:t></w:r>', $fixed);

$fixed = $templateProcessor->fixBrokenMacros('<w:r><w:t>before {{</w:t></w:r><w:r><w:t>variable</w:t></w:r><w:r><w:t xml:space="preserve">}} </w:t></w:r><w:r><w:t>after</w:t></w:r>');
self::assertEquals('<w:r><w:t>before {{variable}}</w:t></w:r><w:r><w:t xml:space="preserve"></w:t></w:r><w:r><w:t xml:space="preserve"> </w:t></w:r><w:r><w:t>after</w:t></w:r>', $fixed);

$fixed = $templateProcessor->fixBrokenMacros('<w:r><w:t>{{</w:t></w:r><w:r><w:t>variable1</w:t></w:r><w:r><w:t>}} {{</w:t></w:r><w:r><w:t>variable2</w:t></w:r><w:r><w:t>}}</w:t></w:r>');
self::assertEquals('<w:r><w:t>{{variable1}}</w:t></w:r><w:r><w:t xml:space="preserve"></w:t></w:r><w:r><w:t xml:space="preserve"> {{variable2}}</w:t></w:r><w:r><w:t xml:space="preserve"></w:t></w:r><w:r><w:t xml:space="preserve"></w:t></w:r>', $fixed);
}

/**
Expand Down

0 comments on commit 838b63e

Please sign in to comment.