@@ -321,28 +321,26 @@ public function cloneRow($search, $numberOfClones)
321
321
public function cloneBlock ($ blockname , $ clones = 1 , $ replace = true )
322
322
{
323
323
$ xmlBlock = null ;
324
-
325
- $ matches = $ this ->findBlock ($ blockname );
326
-
327
- if (isset ($ matches [1 ]))
328
- {
329
- $ xmlBlock = $ matches [1 ];
330
-
331
- $ cloned = array ();
332
-
333
- for ($ i = 1 ; $ i <= $ clones ; $ i ++)
334
- {
335
- $ cloned [] = preg_replace ('/\${(.*?)}/ ' ,'${$1_ ' .$ i .'} ' , $ xmlBlock );
336
- }
337
324
338
- if ($ replace )
339
- {
340
- $ this ->tempDocumentMainPart = str_replace
341
- (
342
- $ matches [0 ],
343
- implode ('' , $ cloned ),
344
- $ this ->tempDocumentMainPart
345
- );
325
+ $ matches = $ this ->findBlocks ($ blockname );
326
+
327
+ foreach ($ matches as $ match ) {
328
+ if (isset ($ match [1 ])) {
329
+ $ xmlBlock = $ match [1 ];
330
+
331
+ $ cloned = array ();
332
+
333
+ for ($ i = 1 ; $ i <= $ clones ; $ i ++) {
334
+ $ cloned [] = preg_replace ('/\${(.*?)}/ ' , '${$1_ ' . $ i . '} ' , $ xmlBlock );
335
+ }
336
+
337
+ if ($ replace ) {
338
+ $ this ->tempDocumentMainPart = str_replace (
339
+ $ match [0 ],
340
+ implode ('' , $ cloned ),
341
+ $ this ->tempDocumentMainPart
342
+ );
343
+ }
346
344
}
347
345
}
348
346
@@ -357,16 +355,16 @@ public function cloneBlock($blockname, $clones = 1, $replace = true)
357
355
*/
358
356
public function replaceBlock ($ blockname , $ replacement )
359
357
{
360
- $ matches = $ this ->findBlock ($ blockname );
361
-
362
- if (isset ($ matches [1 ]))
363
- {
364
- $ this ->tempDocumentMainPart = str_replace
365
- (
366
- $ matches [0 ],
358
+ $ matches = $ this ->findBlocks ($ blockname );
359
+
360
+ foreach ($ matches as $ match ) {
361
+ if (isset ($ match [1 ])) {
362
+ $ this ->tempDocumentMainPart = str_replace (
363
+ $ match [0 ],
367
364
$ replacement ,
368
365
$ this ->tempDocumentMainPart
369
366
);
367
+ }
370
368
}
371
369
}
372
370
@@ -573,59 +571,62 @@ protected function getSlice($startPosition, $endPosition = 0)
573
571
574
572
return substr ($ this ->tempDocumentMainPart , $ startPosition , ($ endPosition - $ startPosition ));
575
573
}
576
-
577
- private function findBlock ($ blockname )
574
+
575
+ private function findBlocks ($ blockname )
578
576
{
579
577
// Parse the XML
580
578
$ xml = new \SimpleXMLElement ($ this ->tempDocumentMainPart );
581
-
579
+
582
580
// Find the starting and ending tags
583
- $ startNode = false ; $ endNode = false ;
584
- foreach ($ xml ->xpath ('//w:t ' ) as $ node )
585
- {
586
- if (strpos ($ node , '${ ' .$ blockname .'} ' ) !== false )
587
- {
581
+ $ startNode = false ;
582
+ $ endNode = false ;
583
+ $ state = 'outside ' ;
584
+ $ pairs = array ();
585
+ foreach ($ xml ->xpath ('//w:t ' ) as $ node ) {
586
+ if (strpos ($ node , '${ ' . $ blockname . '} ' ) !== false ) {
588
587
$ startNode = $ node ;
588
+ $ state = 'inside ' ;
589
589
continue ;
590
590
}
591
-
592
- if (strpos ($ node , '${/ ' .$ blockname .'} ' ) !== false )
593
- {
591
+
592
+ if ($ state === 'inside ' && strpos ($ node , '${/ ' . $ blockname . '} ' ) !== false ) {
594
593
$ endNode = $ node ;
595
- break ;
594
+ $ pairs [] = array ($ startNode , $ endNode );
595
+ $ startNode = false ;
596
+ $ endNode = false ;
597
+ $ state = 'outside ' ;
596
598
}
597
599
}
598
-
600
+
599
601
// Make sure we found the tags
600
- if ($ startNode === false || $ endNode === false )
601
- {
602
+ if (count ($ pairs ) === 0 ) {
602
603
return null ;
603
604
}
604
-
605
- // Find the parent <w:p> node for the start tag
606
- $ node = $ startNode ; $ startNode = null ;
607
- while (is_null ($ startNode ))
608
- {
609
- $ node = $ node ->xpath ('.. ' )[0 ];
610
-
611
- if ($ node ->getName () == 'p ' )
612
- {
613
- $ startNode = $ node ;
614
- }
605
+
606
+ $ result = array ();
607
+ foreach ($ pairs as $ pair ) {
608
+ $ result [] = $ this ->findEnclosing ($ pair [0 ], $ pair [1 ], $ xml );
615
609
}
616
-
617
- // Find the parent <w:p> node for the end tag
618
- $ node = $ endNode ; $ endNode = null ;
619
- while (is_null ($ endNode ))
620
- {
621
- $ node = $ node ->xpath ('.. ' )[0 ];
622
-
623
- if ($ node ->getName () == 'p ' )
624
- {
625
- $ endNode = $ node ;
626
- }
610
+
611
+ return $ result ;
612
+ }
613
+
614
+ private static function getParentByName ($ node , $ name )
615
+ {
616
+ while ($ node ->getName () !== $ name ) {
617
+ $ parents = $ node ->xpath ('.. ' );
618
+ $ node = $ parents [0 ];
627
619
}
628
-
620
+
621
+ return $ node ;
622
+ }
623
+
624
+ private function findEnclosing ($ startNode , $ endNode , $ xml )
625
+ {
626
+ // Find the parent <w:p> nodes for startNode & endNode
627
+ $ startNode = self ::getParentByName ($ startNode , 'p ' );
628
+ $ endNode = self ::getParentByName ($ endNode , 'p ' );
629
+
629
630
/*
630
631
* NOTE: Because SimpleXML reduces empty tags to "self-closing" tags.
631
632
* We need to replace the original XML with the version of XML as
@@ -662,18 +663,16 @@ private function findBlock($blockname)
662
663
* </w:p>
663
664
* ```
664
665
*/
665
-
666
+
666
667
$ this ->tempDocumentMainPart = $ xml ->asXml ();
667
-
668
+
668
669
// Find the xml in between the tags
669
- $ xmlBlock = null ;
670
- preg_match
671
- (
672
- '/ ' .preg_quote ($ startNode ->asXml (), '/ ' ).'(.*?) ' .preg_quote ($ endNode ->asXml (), '/ ' ).'/is ' ,
670
+ preg_match (
671
+ '/ ' . preg_quote ($ startNode ->asXml (), '/ ' ) . '(.*?) ' . preg_quote ($ endNode ->asXml (), '/ ' ) . '/is ' ,
673
672
$ this ->tempDocumentMainPart ,
674
673
$ matches
675
674
);
676
-
675
+
677
676
return $ matches ;
678
677
}
679
678
}
0 commit comments