@@ -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 ;
@@ -792,8 +796,12 @@ public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVaria
792796 {
793797 $ xmlBlock = null ;
794798 $ matches = [];
799+ $ escapedMacroOpeningChars = self ::$ macroOpeningChars ;
800+ $ escapedMacroClosingChars = self ::$ macroClosingChars ;
795801 preg_match (
796- '/(.*((?s)<w:p\b(?:(?!<w:p\b).)*?\${ ' . $ blockname . '}<\/w:.*?p>))(.*)((?s)<w:p\b(?:(?!<w:p\b).)[^$]*?\${\/ ' . $ blockname . '}<\/w:.*?p>)/is ' ,
802+ //'/(.*((?s)<w:p\b(?:(?!<w:p\b).)*?\{{' . $blockname . '}<\/w:.*?p>))(.*)((?s)<w:p\b(?:(?!<w:p\b).)[^$]*?\{{\/' . $blockname . '}<\/w:.*?p>)/is',
803+ '/(.*((?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 ' ,
804+ //'/(.*((?s)<w:p\b(?:(?!<w:p\b).)*?\\'. $escapedMacroOpeningChars . $blockname . '}<\/w:.*?p>))(.*)((?s)<w:p\b(?:(?!<w:p\b).)[^$]*?\\'.$escapedMacroOpeningChars.'\/' . $blockname . '}<\/w:.*?p>)/is',
797805 $ this ->tempDocumentMainPart ,
798806 $ matches
799807 );
@@ -832,8 +840,10 @@ public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVaria
832840 public function replaceBlock ($ blockname , $ replacement ): void
833841 {
834842 $ matches = [];
843+ $ escapedMacroOpeningChars = preg_quote (self ::$ macroOpeningChars );
844+ $ escapedMacroClosingChars = preg_quote (self ::$ macroClosingChars );
835845 preg_match (
836- '/(<\?xml.*)(<w:p.*>\${ ' . $ blockname . ' } <\/w:.*?p>)(.*)(<w:p.*\${ \/ ' . $ blockname . ' } <\/w:.*?p>)/is ' ,
846+ '/(<\?xml.*)(<w:p.*> ' . $ escapedMacroOpeningChars . $ blockname . $ escapedMacroClosingChars . ' <\/w:.*?p>)(.*)(<w:p.* ' . $ escapedMacroOpeningChars . ' \/ ' . $ blockname . $ escapedMacroClosingChars . ' <\/w:.*?p>)/is ' ,
837847 $ this ->tempDocumentMainPart ,
838848 $ matches
839849 );
@@ -949,8 +959,12 @@ public function saveAs($fileName): void
949959 */
950960 protected function fixBrokenMacros ($ documentPart )
951961 {
962+ $ brokenMacroOpeningChars = substr (self ::$ macroOpeningChars , 0 , 1 );
963+ $ endMacroOpeningChars = substr (self ::$ macroOpeningChars , 1 );
964+ $ macroClosingChars = self ::$ macroClosingChars ;
965+
952966 return preg_replace_callback (
953- '/\$ (?:\{ |[^{$]*\>\{)[^} $]*\}/U ' ,
967+ '/ \\' . $ brokenMacroOpeningChars . ' (?: \\' . $ endMacroOpeningChars . ' |[^{$]*\>\{)[^ ' . $ macroClosingChars . ' $]*\}/U ' ,
954968 function ($ match ) {
955969 return strip_tags ($ match [0 ]);
956970 },
@@ -989,7 +1003,10 @@ protected function setValueForPart($search, $replace, $documentPartXML, $limit)
9891003 protected function getVariablesForPart ($ documentPartXML )
9901004 {
9911005 $ matches = [];
992- preg_match_all ('/\$\{(.*?)}/i ' , $ documentPartXML , $ matches );
1006+ $ escapedMacroOpeningChars = preg_quote (self ::$ macroOpeningChars );
1007+ $ escapedMacroClosingChars = preg_quote (self ::$ macroClosingChars );
1008+
1009+ preg_match_all ("/ $ escapedMacroOpeningChars(.*?) $ escapedMacroClosingChars/i " , $ documentPartXML , $ matches );
9931010
9941011 return $ matches [1 ];
9951012 }
@@ -1141,8 +1158,11 @@ protected function getSlice($startPosition, $endPosition = 0)
11411158 protected function indexClonedVariables ($ count , $ xmlBlock )
11421159 {
11431160 $ results = [];
1161+ $ escapedMacroOpeningChars = preg_quote (self ::$ macroOpeningChars );
1162+ $ escapedMacroClosingChars = preg_quote (self ::$ macroClosingChars );
1163+
11441164 for ($ i = 1 ; $ i <= $ count ; ++$ i ) {
1145- $ results [] = preg_replace (' /\$\{ ([^:]*?)(:.*?)?\}/ ' , ' \${\ 1# ' . $ i . '\2} ' , $ xmlBlock );
1165+ $ results [] = preg_replace (" / $ escapedMacroOpeningChars ([^:]*?)(:.*?)? $ escapedMacroClosingChars / " , self :: $ macroOpeningChars . ' \ 1# ' . $ i . '\2 ' . self :: $ macroClosingChars , $ xmlBlock );
11461166 }
11471167
11481168 return $ results ;
@@ -1297,7 +1317,7 @@ protected function splitTextIntoTexts($text)
12971317 }
12981318
12991319 $ unformattedText = preg_replace ('/>\s+</ ' , '>< ' , $ text );
1300- $ 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 );
1320+ $ 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 );
13011321
13021322 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 );
13031323 }
@@ -1311,6 +1331,25 @@ protected function splitTextIntoTexts($text)
13111331 */
13121332 protected function textNeedsSplitting ($ text )
13131333 {
1314- return preg_match ('/[^>]\${|}[^<]/i ' , $ text ) == 1 ;
1334+ $ escapedMacroOpeningChars = preg_quote (self ::$ macroOpeningChars );
1335+ $ escapedMacroClosingChars = preg_quote (self ::$ macroClosingChars );
1336+
1337+ return 1 === preg_match ('/[^>] ' . $ escapedMacroOpeningChars . '| ' . $ escapedMacroClosingChars . '[^<]/i ' , $ text );
1338+ }
1339+
1340+ public function setMacroOpeningChars (string $ macroOpeningChars ): void
1341+ {
1342+ self ::$ macroOpeningChars = $ macroOpeningChars ;
1343+ }
1344+
1345+ public function setMacroClosingChars (string $ macroClosingChars ): void
1346+ {
1347+ self ::$ macroClosingChars = $ macroClosingChars ;
1348+ }
1349+
1350+ public function setMacroChars (string $ macroOpeningChars , string $ macroClosingChars ): void
1351+ {
1352+ self ::$ macroOpeningChars = $ macroOpeningChars ;
1353+ self ::$ macroClosingChars = $ macroClosingChars ;
13151354 }
13161355}
0 commit comments