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