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