diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 498cf701..9e12028d 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -1108,7 +1108,7 @@ class TemplateProcessor protected function findContainingXmlBlockForMacro($macro, $blockType = 'w:p') { $macroPos = $this->findMacro($macro); - if (false === $macroPos) { + if (0 > $macroPos) { return false; } $start = $this->findXmlBlockStart($macroPos, $blockType); @@ -1116,39 +1116,8 @@ class TemplateProcessor return false; } $end = $this->findXmlBlockEnd($start, $blockType); - if (0 > $end) { - return false; - } - - return array('start' => $start, 'end' => $end); - } - - /** - * Find start and end of XML block containing the given block macro - * e.g. ...${macro}...${/macro}... - * - * Note that only the first instance of the macro will be found - * - * @param string $macro Name of macro - * @param string $blockType XML tag for block - * @return bool|int[] FALSE if not found, otherwise array with start and end - */ - protected function findContainingXmlBlockForBlockMacro($macro, $blockType = 'w:p') - { - $macroStartPos = $this->findMacro($macro); - if (0 > $macroStartPos) { - return false; - } - $macroEndPos = $this->findMacro('/' . $macro, $macroStartPos); - if (0 > $macroEndPos) { - return false; - } - $start = $this->findXmlBlockStart($macroStartPos, $blockType); - if (0 > $start) { - return false; - } - $end = $this->findXmlBlockEnd($macroEndPos, $blockType); - if (0 > $end) { + //if not found or if resulting string does not contain the macro we are searching for + if (0 > $end || strstr($this->getSlice($start, $end), $macro) === false) { return false; } @@ -1183,12 +1152,13 @@ class TemplateProcessor */ protected function findXmlBlockStart($offset, $blockType) { + $reverseOffset = (strlen($this->tempDocumentMainPart) - $offset) * -1; // first try XML tag with attributes - $blockStart = strrpos($this->tempDocumentMainPart, '<' . $blockType . ' ', ((strlen($this->tempDocumentMainPart) - $offset) * -1)); + $blockStart = strrpos($this->tempDocumentMainPart, '<' . $blockType . ' ', $reverseOffset); // if not found, or if found but contains the XML tag without attribute if (false === $blockStart || strrpos($this->getSlice($blockStart, $offset), '<' . $blockType . '>')) { // also try XML tag without attributes - $blockStart = strrpos($this->tempDocumentMainPart, '<' . $blockType . '>', ((strlen($this->tempDocumentMainPart) - $offset) * -1)); + $blockStart = strrpos($this->tempDocumentMainPart, '<' . $blockType . '>', $reverseOffset); } return ($blockStart === false) ? -1 : $blockStart; diff --git a/tests/PhpWord/TemplateProcessorTest.php b/tests/PhpWord/TemplateProcessorTest.php index 4c9f2358..043ad1ff 100644 --- a/tests/PhpWord/TemplateProcessorTest.php +++ b/tests/PhpWord/TemplateProcessorTest.php @@ -803,4 +803,31 @@ final class TemplateProcessorTest extends \PHPUnit\Framework\TestCase $this->assertEquals($toFind, $templateProcessor->getSlice($position['start'], $position['end'])); } + + public function testShouldReturnFalseIfXmlBlockNotFound() + { + $mainPart = ' + + + + + + this is my text containing a ${macro} + + + '; + $templateProcessor = new TestableTemplateProcesor($mainPart); + + //non-existing macro + $result = $templateProcessor->findContainingXmlBlockForMacro('${fake-macro}', 'w:p'); + $this->assertFalse($result); + + //existing macro but not inside node looked for + $result = $templateProcessor->findContainingXmlBlockForMacro('${macro}', 'w:fake-node'); + $this->assertFalse($result); + + //existing macro but end tag not found after macro + $result = $templateProcessor->findContainingXmlBlockForMacro('${macro}', 'w:rPr'); + $this->assertFalse($result); + } }