@@ -94,6 +94,10 @@ class TemplateProcessor
9494 */
9595 protected $ tempDocumentNewImages = [];
9696
97+ protected static $ macroOpeningChars = '${ ' ;
98+
99+ protected static $ macroClosingChars = '} ' ;
100+
97101 /**
98102 * @since 0.12.0 Throws CreateTemporaryFileException and CopyFileException instead of Exception
99103 *
@@ -238,8 +242,8 @@ public function applyXslStyleSheet($xslDomDocument, $xslOptions = [], $xslOption
238242 */
239243 protected static function ensureMacroCompleted ($ macro )
240244 {
241- if (substr ($ macro , 0 , 2 ) !== ' ${ ' && substr ($ macro , -1 ) !== ' } ' ) {
242- $ macro = ' ${ ' . $ macro . ' } ' ;
245+ if (substr ($ macro , 0 , 2 ) !== self :: $ macroOpeningChars && substr ($ macro , -1 ) !== self :: $ macroClosingChars ) {
246+ $ macro = self :: $ macroOpeningChars . $ macro . self :: $ macroClosingChars ;
243247 }
244248
245249 return $ macro ;
@@ -856,8 +860,12 @@ public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVaria
856860 {
857861 $ xmlBlock = null ;
858862 $ matches = [];
863+ $ escapedMacroOpeningChars = self ::$ macroOpeningChars ;
864+ $ escapedMacroClosingChars = self ::$ macroClosingChars ;
859865 preg_match (
860- '/(.*((?s)<w:p\b(?:(?!<w:p\b).)*?\${ ' . $ blockname . '}<\/w:.*?p>))(.*)((?s)<w:p\b(?:(?!<w:p\b).)[^$]*?\${\/ ' . $ blockname . '}<\/w:.*?p>)/is ' ,
866+ //'/(.*((?s)<w:p\b(?:(?!<w:p\b).)*?\{{' . $blockname . '}<\/w:.*?p>))(.*)((?s)<w:p\b(?:(?!<w:p\b).)[^$]*?\{{\/' . $blockname . '}<\/w:.*?p>)/is',
867+ '/(.*((?s)<w:p\b(?:(?!<w:p\b).)*? \\' . $ escapedMacroOpeningChars . $ blockname . $ escapedMacroClosingChars . '<\/w:.*?p>))(.*)((?s)<w:p\b(?:(?!<w:p\b).)[^$]*? \\' . $ escapedMacroOpeningChars . '\/ ' . $ blockname . $ escapedMacroClosingChars . '<\/w:.*?p>)/is ' ,
868+ //'/(.*((?s)<w:p\b(?:(?!<w:p\b).)*?\\'. $escapedMacroOpeningChars . $blockname . '}<\/w:.*?p>))(.*)((?s)<w:p\b(?:(?!<w:p\b).)[^$]*?\\'.$escapedMacroOpeningChars.'\/' . $blockname . '}<\/w:.*?p>)/is',
861869 $ this ->tempDocumentMainPart ,
862870 $ matches
863871 );
@@ -896,8 +904,10 @@ public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVaria
896904 public function replaceBlock ($ blockname , $ replacement ): void
897905 {
898906 $ matches = [];
907+ $ escapedMacroOpeningChars = preg_quote (self ::$ macroOpeningChars );
908+ $ escapedMacroClosingChars = preg_quote (self ::$ macroClosingChars );
899909 preg_match (
900- '/(<\?xml.*)(<w:p.*>\${ ' . $ blockname . ' } <\/w:.*?p>)(.*)(<w:p.*\${ \/ ' . $ blockname . ' } <\/w:.*?p>)/is ' ,
910+ '/(<\?xml.*)(<w:p.*> ' . $ escapedMacroOpeningChars . $ blockname . $ escapedMacroClosingChars . ' <\/w:.*?p>)(.*)(<w:p.* ' . $ escapedMacroOpeningChars . ' \/ ' . $ blockname . $ escapedMacroClosingChars . ' <\/w:.*?p>)/is ' ,
901911 $ this ->tempDocumentMainPart ,
902912 $ matches
903913 );
@@ -1013,8 +1023,12 @@ public function saveAs($fileName): void
10131023 */
10141024 protected function fixBrokenMacros ($ documentPart )
10151025 {
1026+ $ brokenMacroOpeningChars = substr (self ::$ macroOpeningChars , 0 , 1 );
1027+ $ endMacroOpeningChars = substr (self ::$ macroOpeningChars , 1 );
1028+ $ macroClosingChars = self ::$ macroClosingChars ;
1029+
10161030 return preg_replace_callback (
1017- '/\$ (?:\{ |[^{$]*\>\{)[^} $]*\}/U ' ,
1031+ '/ \\' . $ brokenMacroOpeningChars . ' (?: \\' . $ endMacroOpeningChars . ' |[^{$]*\>\{)[^ ' . $ macroClosingChars . ' $]*\}/U ' ,
10181032 function ($ match ) {
10191033 return strip_tags ($ match [0 ]);
10201034 },
@@ -1053,7 +1067,10 @@ protected function setValueForPart($search, $replace, $documentPartXML, $limit)
10531067 protected function getVariablesForPart ($ documentPartXML )
10541068 {
10551069 $ matches = [];
1056- preg_match_all ('/\$\{(.*?)}/i ' , $ documentPartXML , $ matches );
1070+ $ escapedMacroOpeningChars = preg_quote (self ::$ macroOpeningChars );
1071+ $ escapedMacroClosingChars = preg_quote (self ::$ macroClosingChars );
1072+
1073+ preg_match_all ("/ $ escapedMacroOpeningChars(.*?) $ escapedMacroClosingChars/i " , $ documentPartXML , $ matches );
10571074
10581075 return $ matches [1 ];
10591076 }
@@ -1238,8 +1255,11 @@ protected function getSlice($startPosition, $endPosition = 0)
12381255 protected function indexClonedVariables ($ count , $ xmlBlock )
12391256 {
12401257 $ results = [];
1258+ $ escapedMacroOpeningChars = preg_quote (self ::$ macroOpeningChars );
1259+ $ escapedMacroClosingChars = preg_quote (self ::$ macroClosingChars );
1260+
12411261 for ($ i = 1 ; $ i <= $ count ; ++$ i ) {
1242- $ results [] = preg_replace (' /\$\{ ([^:]*?)(:.*?)?\}/ ' , ' \${\ 1# ' . $ i . '\2} ' , $ xmlBlock );
1262+ $ results [] = preg_replace (" / $ escapedMacroOpeningChars ([^:]*?)(:.*?)? $ escapedMacroClosingChars / " , self :: $ macroOpeningChars . ' \ 1# ' . $ i . '\2 ' . self :: $ macroClosingChars , $ xmlBlock );
12431263 }
12441264
12451265 return $ results ;
@@ -1394,7 +1414,7 @@ protected function splitTextIntoTexts($text)
13941414 }
13951415
13961416 $ unformattedText = preg_replace ('/>\s+</ ' , '>< ' , $ text );
1397- $ result = str_replace ([' ${ ' , ' } ' ], ['</w:t></w:r><w:r> ' . $ extractedStyle . '<w:t xml:space="preserve">${ ' , ' } </w:t></w:r><w:r> ' . $ extractedStyle . '<w:t xml:space="preserve"> ' ], $ unformattedText );
1417+ $ result = str_replace ([self :: $ macroOpeningChars , self :: $ macroClosingChars ], ['</w:t></w:r><w:r> ' . $ extractedStyle . '<w:t xml:space="preserve"> ' . self :: $ macroOpeningChars , self :: $ macroClosingChars . ' </w:t></w:r><w:r> ' . $ extractedStyle . '<w:t xml:space="preserve"> ' ], $ unformattedText );
13981418
13991419 return str_replace (['<w:r> ' . $ extractedStyle . '<w:t xml:space="preserve"></w:t></w:r> ' , '<w:r><w:t xml:space="preserve"></w:t></w:r> ' , '<w:t> ' ], ['' , '' , '<w:t xml:space="preserve"> ' ], $ result );
14001420 }
@@ -1408,6 +1428,25 @@ protected function splitTextIntoTexts($text)
14081428 */
14091429 protected function textNeedsSplitting ($ text )
14101430 {
1411- return preg_match ('/[^>]\${|}[^<]/i ' , $ text ) == 1 ;
1431+ $ escapedMacroOpeningChars = preg_quote (self ::$ macroOpeningChars );
1432+ $ escapedMacroClosingChars = preg_quote (self ::$ macroClosingChars );
1433+
1434+ return 1 === preg_match ('/[^>] ' . $ escapedMacroOpeningChars . '| ' . $ escapedMacroClosingChars . '[^<]/i ' , $ text );
1435+ }
1436+
1437+ public function setMacroOpeningChars (string $ macroOpeningChars ): void
1438+ {
1439+ self ::$ macroOpeningChars = $ macroOpeningChars ;
1440+ }
1441+
1442+ public function setMacroClosingChars (string $ macroClosingChars ): void
1443+ {
1444+ self ::$ macroClosingChars = $ macroClosingChars ;
1445+ }
1446+
1447+ public function setMacroChars (string $ macroOpeningChars , string $ macroClosingChars ): void
1448+ {
1449+ self ::$ macroOpeningChars = $ macroOpeningChars ;
1450+ self ::$ macroClosingChars = $ macroClosingChars ;
14121451 }
14131452}
0 commit comments