Merge pull request #1565 from troosan/set_complex_type_in_template

Set complex type in template
This commit is contained in:
troosan 2019-02-04 23:27:13 +01:00 committed by GitHub
commit 98026aefaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 439 additions and 1 deletions

1
.gitignore vendored
View File

@ -13,7 +13,6 @@ composer.phar
vendor vendor
/report /report
/build /build
/samples/resources
/samples/results /samples/results
/.settings /.settings
phpword.ini phpword.ini

View File

@ -215,3 +215,32 @@ Applies the XSL stylesheet passed to header part, footer part and main part
$xslDomDocument = new \DOMDocument(); $xslDomDocument = new \DOMDocument();
$xslDomDocument->load('/path/to/my/stylesheet.xsl'); $xslDomDocument->load('/path/to/my/stylesheet.xsl');
$templateProcessor->applyXslStyleSheet($xslDomDocument); $templateProcessor->applyXslStyleSheet($xslDomDocument);
setComplexValue
"""""""""""""""
Raplaces a ${macro} with the ComplexType passed.
See ``Sample_40_TemplateSetComplexValue.php`` for examples.
.. code-block:: php
$inline = new TextRun();
$inline->addText('by a red italic text', array('italic' => true, 'color' => 'red'));
$templateProcessor->setComplexValue('inline', $inline);
setComplexBlock
"""""""""""""""
Raplaces a ${macro} with the ComplexType passed.
See ``Sample_40_TemplateSetComplexValue.php`` for examples.
.. code-block:: php
$table = new Table(array('borderSize' => 12, 'borderColor' => 'green', 'width' => 6000, 'unit' => TblWidth::TWIP));
$table->addRow();
$table->addCell(150)->addText('Cell A1');
$table->addCell(150)->addText('Cell A2');
$table->addCell(150)->addText('Cell A3');
$table->addRow();
$table->addCell(150)->addText('Cell B1');
$table->addCell(150)->addText('Cell B2');
$table->addCell(150)->addText('Cell B3');
$templateProcessor->setComplexBlock('table', $table);

View File

@ -0,0 +1,45 @@
<?php
use PhpOffice\PhpWord\Element\Field;
use PhpOffice\PhpWord\Element\Table;
use PhpOffice\PhpWord\Element\TextRun;
use PhpOffice\PhpWord\SimpleType\TblWidth;
include_once 'Sample_Header.php';
// Template processor instance creation
echo date('H:i:s'), ' Creating new TemplateProcessor instance...', EOL;
$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('resources/Sample_40_TemplateSetComplexValue.docx');
$title = new TextRun();
$title->addText('This title has been set ', array('bold' => true, 'italic' => true, 'color' => 'blue'));
$title->addText('dynamically', array('bold' => true, 'italic' => true, 'color' => 'red', 'underline' => 'single'));
$templateProcessor->setComplexBlock('title', $title);
$inline = new TextRun();
$inline->addText('by a red italic text', array('italic' => true, 'color' => 'red'));
$templateProcessor->setComplexValue('inline', $inline);
$table = new Table(array('borderSize' => 12, 'borderColor' => 'green', 'width' => 6000, 'unit' => TblWidth::TWIP));
$table->addRow();
$table->addCell(150)->addText('Cell A1');
$table->addCell(150)->addText('Cell A2');
$table->addCell(150)->addText('Cell A3');
$table->addRow();
$table->addCell(150)->addText('Cell B1');
$table->addCell(150)->addText('Cell B2');
$table->addCell(150)->addText('Cell B3');
$templateProcessor->setComplexBlock('table', $table);
$field = new Field('DATE', array('dateformat' => 'dddd d MMMM yyyy H:mm:ss'), array('PreserveFormat'));
$templateProcessor->setComplexValue('field', $field);
// $link = new Link('https://github.com/PHPOffice/PHPWord');
// $templateProcessor->setComplexValue('link', $link);
echo date('H:i:s'), ' Saving the result document...', EOL;
$templateProcessor->saveAs('results/Sample_40_TemplateSetComplexValue.docx');
echo getEndingNotes(array('Word2007' => 'docx'), 'results/Sample_40_TemplateSetComplexValue.docx');
if (!CLI) {
include_once 'Sample_Footer.php';
}

View File

@ -18,6 +18,7 @@
namespace PhpOffice\PhpWord; namespace PhpOffice\PhpWord;
use PhpOffice\Common\Text; use PhpOffice\Common\Text;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Escaper\RegExp; use PhpOffice\PhpWord\Escaper\RegExp;
use PhpOffice\PhpWord\Escaper\Xml; use PhpOffice\PhpWord\Escaper\Xml;
use PhpOffice\PhpWord\Exception\CopyFileException; use PhpOffice\PhpWord\Exception\CopyFileException;
@ -249,6 +250,46 @@ class TemplateProcessor
return $subject; return $subject;
} }
/**
* @param string $search
* @param \PhpOffice\PhpWord\Element\AbstractElement $complexType
*/
public function setComplexValue($search, \PhpOffice\PhpWord\Element\AbstractElement $complexType)
{
$elementName = substr(get_class($complexType), strrpos(get_class($complexType), '\\') + 1);
$objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $elementName;
$xmlWriter = new XMLWriter();
/** @var \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement $elementWriter */
$elementWriter = new $objectClass($xmlWriter, $complexType, true);
$elementWriter->write();
$where = $this->findContainingXmlBlockForMacro($search, 'w:r');
$block = $this->getSlice($where['start'], $where['end']);
$textParts = $this->splitTextIntoTexts($block);
$this->replaceXmlBlock($search, $textParts, 'w:r');
$search = static::ensureMacroCompleted($search);
$this->replaceXmlBlock($search, $xmlWriter->getData(), 'w:r');
}
/**
* @param string $search
* @param \PhpOffice\PhpWord\Element\AbstractElement $complexType
*/
public function setComplexBlock($search, \PhpOffice\PhpWord\Element\AbstractElement $complexType)
{
$elementName = substr(get_class($complexType), strrpos(get_class($complexType), '\\') + 1);
$objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $elementName;
$xmlWriter = new XMLWriter();
/** @var \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement $elementWriter */
$elementWriter = new $objectClass($xmlWriter, $complexType, false);
$elementWriter->write();
$this->replaceXmlBlock($search, $xmlWriter->getData(), 'w:p');
}
/** /**
* @param mixed $search * @param mixed $search
* @param mixed $replace * @param mixed $replace
@ -685,6 +726,7 @@ class TemplateProcessor
public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVariables = false, $variableReplacements = null) public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVariables = false, $variableReplacements = null)
{ {
$xmlBlock = null; $xmlBlock = null;
$matches = array();
preg_match( preg_match(
'/(<\?xml.*)(<w:p\b.*>\${' . $blockname . '}<\/w:.*?p>)(.*)(<w:p\b.*\${\/' . $blockname . '}<\/w:.*?p>)/is', '/(<\?xml.*)(<w:p\b.*>\${' . $blockname . '}<\/w:.*?p>)(.*)(<w:p\b.*\${\/' . $blockname . '}<\/w:.*?p>)/is',
$this->tempDocumentMainPart, $this->tempDocumentMainPart,
@ -724,6 +766,7 @@ class TemplateProcessor
*/ */
public function replaceBlock($blockname, $replacement) public function replaceBlock($blockname, $replacement)
{ {
$matches = array();
preg_match( preg_match(
'/(<\?xml.*)(<w:p.*>\${' . $blockname . '}<\/w:.*?p>)(.*)(<w:p.*\${\/' . $blockname . '}<\/w:.*?p>)/is', '/(<\?xml.*)(<w:p.*>\${' . $blockname . '}<\/w:.*?p>)(.*)(<w:p.*\${\/' . $blockname . '}<\/w:.*?p>)/is',
$this->tempDocumentMainPart, $this->tempDocumentMainPart,
@ -865,6 +908,7 @@ class TemplateProcessor
*/ */
protected function getVariablesForPart($documentPartXML) protected function getVariablesForPart($documentPartXML)
{ {
$matches = array();
preg_match_all('/\$\{(.*?)}/i', $documentPartXML, $matches); preg_match_all('/\$\{(.*?)}/i', $documentPartXML, $matches);
return $matches[1]; return $matches[1];
@ -893,6 +937,7 @@ class TemplateProcessor
$pattern = '~PartName="\/(word\/document.*?\.xml)" ContentType="application\/vnd\.openxmlformats-officedocument\.wordprocessingml\.document\.main\+xml"~'; $pattern = '~PartName="\/(word\/document.*?\.xml)" ContentType="application\/vnd\.openxmlformats-officedocument\.wordprocessingml\.document\.main\+xml"~';
$matches = array();
preg_match($pattern, $contentTypes, $matches); preg_match($pattern, $contentTypes, $matches);
return array_key_exists(1, $matches) ? $matches[1] : 'word/document.xml'; return array_key_exists(1, $matches) ? $matches[1] : 'word/document.xml';
@ -1031,4 +1076,141 @@ class TemplateProcessor
return $results; return $results;
} }
/**
* Replace an XML block surrounding a macro with a new block
*
* @param string $macro Name of macro
* @param string $block New block content
* @param string $blockType XML tag type of block
* @return \PhpOffice\PhpWord\TemplateProcessor Fluent interface
*/
protected function replaceXmlBlock($macro, $block, $blockType = 'w:p')
{
$where = $this->findContainingXmlBlockForMacro($macro, $blockType);
if (is_array($where)) {
$this->tempDocumentMainPart = $this->getSlice(0, $where['start']) . $block . $this->getSlice($where['end']);
}
return $this;
}
/**
* Find start and end of XML block containing the given macro
* e.g. <w:p>...${macro}...</w:p>
*
* 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 findContainingXmlBlockForMacro($macro, $blockType = 'w:p')
{
$macroPos = $this->findMacro($macro);
if (0 > $macroPos) {
return false;
}
$start = $this->findXmlBlockStart($macroPos, $blockType);
if (0 > $start) {
return false;
}
$end = $this->findXmlBlockEnd($start, $blockType);
//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;
}
return array('start' => $start, 'end' => $end);
}
/**
* Find the position of (the start of) a macro
*
* Returns -1 if not found, otherwise position of opening $
*
* Note that only the first instance of the macro will be found
*
* @param string $search Macro name
* @param int $offset Offset from which to start searching
* @return int -1 if macro not found
*/
protected function findMacro($search, $offset = 0)
{
$search = static::ensureMacroCompleted($search);
$pos = strpos($this->tempDocumentMainPart, $search, $offset);
return ($pos === false) ? -1 : $pos;
}
/**
* Find the start position of the nearest XML block start before $offset
*
* @param int $offset Search position
* @param string $blockType XML Block tag
* @return int -1 if block start not found
*/
protected function findXmlBlockStart($offset, $blockType)
{
$reverseOffset = (strlen($this->tempDocumentMainPart) - $offset) * -1;
// first try XML tag with attributes
$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 . '>', $reverseOffset);
}
return ($blockStart === false) ? -1 : $blockStart;
}
/**
* Find the nearest block end position after $offset
*
* @param int $offset Search position
* @param string $blockType XML Block tag
* @return int -1 if block end not found
*/
protected function findXmlBlockEnd($offset, $blockType)
{
$blockEndStart = strpos($this->tempDocumentMainPart, '</' . $blockType . '>', $offset);
// return position of end of tag if found, otherwise -1
return ($blockEndStart === false) ? -1 : $blockEndStart + 3 + strlen($blockType);
}
/**
* Splits a w:r/w:t into a list of w:r where each ${macro} is in a separate w:r
*
* @param string $text
* @return string
*/
protected function splitTextIntoTexts($text)
{
if (!$this->textNeedsSplitting($text)) {
return $text;
}
$matches = array();
if (preg_match('/(<w:rPr.*<\/w:rPr>)/i', $text, $matches)) {
$extractedStyle = $matches[0];
} else {
$extractedStyle = '';
}
$unformattedText = preg_replace('/>\s+</', '><', $text);
$result = str_replace(array('${', '}'), array('</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);
return str_replace(array('<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>'), array('', '', '<w:t xml:space="preserve">'), $result);
}
/**
* Returns true if string contains a macro that is not in it's own w:r
*
* @param string $text
* @return bool
*/
protected function textNeedsSplitting($text)
{
return preg_match('/[^>]\${|}[^<]/i', $text) == 1;
}
} }

View File

@ -17,6 +17,9 @@
namespace PhpOffice\PhpWord; namespace PhpOffice\PhpWord;
use PhpOffice\PhpWord\Element\Text;
use PhpOffice\PhpWord\Element\TextRun;
/** /**
* @covers \PhpOffice\PhpWord\TemplateProcessor * @covers \PhpOffice\PhpWord\TemplateProcessor
* @coversDefaultClass \PhpOffice\PhpWord\TemplateProcessor * @coversDefaultClass \PhpOffice\PhpWord\TemplateProcessor
@ -307,6 +310,59 @@ final class TemplateProcessorTest extends \PHPUnit\Framework\TestCase
); );
} }
public function testSetComplexValue()
{
$title = new TextRun();
$title->addText('This is my title');
$firstname = new Text('Donald');
$lastname = new Text('Duck');
$mainPart = '<?xml version="1.0" encoding="UTF-8"?>
<w:p>
<w:r>
<w:t xml:space="preserve">Hello ${document-title}</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Hello ${firstname} ${lastname}</w:t>
</w:r>
</w:p>';
$result = '<?xml version="1.0" encoding="UTF-8"?>
<w:p>
<w:pPr/>
<w:r>
<w:rPr/>
<w:t xml:space="preserve">This is my title</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Hello </w:t>
</w:r>
<w:r>
<w:rPr/>
<w:t xml:space="preserve">Donald</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> </w:t>
</w:r>
<w:r>
<w:rPr/>
<w:t xml:space="preserve">Duck</w:t>
</w:r>
</w:p>';
$templateProcessor = new TestableTemplateProcesor($mainPart);
$templateProcessor->setComplexBlock('document-title', $title);
$templateProcessor->setComplexValue('firstname', $firstname);
$templateProcessor->setComplexValue('lastname', $lastname);
$this->assertEquals(preg_replace('/>\s+</', '><', $result), preg_replace('/>\s+</', '><', $templateProcessor->getMainPart()));
}
/** /**
* @covers ::setValues * @covers ::setValues
* @test * @test
@ -675,4 +731,103 @@ final class TemplateProcessorTest extends \PHPUnit\Framework\TestCase
$variables = $templateProcessor->getVariablesForPart('<w:t>$</w:t></w:r><w:bookmarkStart w:id="0" w:name="_GoBack"/><w:bookmarkEnd w:id="0"/><w:r><w:t xml:space="preserve">15,000.00. </w:t></w:r><w:r w:rsidR="0056499B"><w:t>$</w:t></w:r><w:r w:rsidR="00573DFD" w:rsidRPr="00573DFD"><w:rPr><w:iCs/></w:rPr><w:t>{</w:t></w:r><w:proofErr w:type="spellStart"/><w:r w:rsidR="00573DFD" w:rsidRPr="00573DFD"><w:rPr><w:iCs/></w:rPr><w:t>variable_name</w:t></w:r><w:proofErr w:type="spellEnd"/><w:r w:rsidR="00573DFD" w:rsidRPr="00573DFD"><w:rPr><w:iCs/></w:rPr><w:t>}</w:t></w:r>'); $variables = $templateProcessor->getVariablesForPart('<w:t>$</w:t></w:r><w:bookmarkStart w:id="0" w:name="_GoBack"/><w:bookmarkEnd w:id="0"/><w:r><w:t xml:space="preserve">15,000.00. </w:t></w:r><w:r w:rsidR="0056499B"><w:t>$</w:t></w:r><w:r w:rsidR="00573DFD" w:rsidRPr="00573DFD"><w:rPr><w:iCs/></w:rPr><w:t>{</w:t></w:r><w:proofErr w:type="spellStart"/><w:r w:rsidR="00573DFD" w:rsidRPr="00573DFD"><w:rPr><w:iCs/></w:rPr><w:t>variable_name</w:t></w:r><w:proofErr w:type="spellEnd"/><w:r w:rsidR="00573DFD" w:rsidRPr="00573DFD"><w:rPr><w:iCs/></w:rPr><w:t>}</w:t></w:r>');
$this->assertEquals(array('variable_name'), $variables); $this->assertEquals(array('variable_name'), $variables);
} }
/**
* @covers ::textNeedsSplitting
*/
public function testTextNeedsSplitting()
{
$templateProcessor = new TestableTemplateProcesor();
$this->assertFalse($templateProcessor->textNeedsSplitting('<w:r><w:rPr><w:b/><w:i/></w:rPr><w:t xml:space="preserve">${nothing-to-replace}</w:t></w:r>'));
$text = '<w:r><w:rPr><w:b/><w:i/></w:rPr><w:t xml:space="preserve">Hello ${firstname} ${lastname}</w:t></w:r>';
$this->assertTrue($templateProcessor->textNeedsSplitting($text));
$splitText = $templateProcessor->splitTextIntoTexts($text);
$this->assertFalse($templateProcessor->textNeedsSplitting($splitText));
}
/**
* @covers ::splitTextIntoTexts
*/
public function testSplitTextIntoTexts()
{
$templateProcessor = new TestableTemplateProcesor();
$splitText = $templateProcessor->splitTextIntoTexts('<w:r><w:rPr><w:b/><w:i/></w:rPr><w:t xml:space="preserve">${nothing-to-replace}</w:t></w:r>');
$this->assertEquals('<w:r><w:rPr><w:b/><w:i/></w:rPr><w:t xml:space="preserve">${nothing-to-replace}</w:t></w:r>', $splitText);
$splitText = $templateProcessor->splitTextIntoTexts('<w:r><w:rPr><w:b/><w:i/></w:rPr><w:t xml:space="preserve">Hello ${firstname} ${lastname}</w:t></w:r>');
$this->assertEquals('<w:r><w:rPr><w:b/><w:i/></w:rPr><w:t xml:space="preserve">Hello </w:t></w:r><w:r><w:rPr><w:b/><w:i/></w:rPr><w:t xml:space="preserve">${firstname}</w:t></w:r><w:r><w:rPr><w:b/><w:i/></w:rPr><w:t xml:space="preserve"> </w:t></w:r><w:r><w:rPr><w:b/><w:i/></w:rPr><w:t xml:space="preserve">${lastname}</w:t></w:r>', $splitText);
}
public function testFindXmlBlockStart()
{
$toFind = '<w:r>
<w:rPr>
<w:rFonts w:ascii="Calibri" w:hAnsi="Calibri" w:cs="Calibri"/>
<w:lang w:val="en-GB"/>
</w:rPr>
<w:t>This whole paragraph will be replaced with my ${title}</w:t>
</w:r>';
$mainPart = '<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex" xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex" xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink" xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se w16cid wp14">
<w:p w14:paraId="165D45AF" w14:textId="7FEC9B41" w:rsidR="005B1098" w:rsidRDefault="005B1098">
<w:r w:rsidR="00A045B2">
<w:rPr>
<w:rFonts w:ascii="Calibri" w:hAnsi="Calibri" w:cs="Calibri"/>
<w:lang w:val="en-GB"/>
</w:rPr>
<w:t xml:space="preserve"> ${value1} ${value2}</w:t>
</w:r>
<w:r>
<w:rPr>
<w:rFonts w:ascii="Calibri" w:hAnsi="Calibri" w:cs="Calibri"/>
<w:lang w:val="en-GB"/>
</w:rPr>
<w:t>.</w:t>
</w:r>
</w:p>
<w:p w14:paraId="330D1954" w14:textId="0AB1D347" w:rsidR="00156568" w:rsidRDefault="00156568">
<w:pPr>
<w:rPr>
<w:rFonts w:ascii="Calibri" w:hAnsi="Calibri" w:cs="Calibri"/>
<w:lang w:val="en-GB"/>
</w:rPr>
</w:pPr>
' . $toFind . '
</w:p>
</w:document>';
$templateProcessor = new TestableTemplateProcesor($mainPart);
$position = $templateProcessor->findContainingXmlBlockForMacro('${title}', 'w:r');
$this->assertEquals($toFind, $templateProcessor->getSlice($position['start'], $position['end']));
}
public function testShouldReturnFalseIfXmlBlockNotFound()
{
$mainPart = '<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:p>
<w:r>
<w:rPr>
<w:lang w:val="en-GB"/>
</w:rPr>
<w:t xml:space="preserve">this is my text containing a ${macro}</w:t>
</w:r>
</w:p>
</w:document>';
$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);
}
} }

View File

@ -35,6 +35,16 @@ class TestableTemplateProcesor extends TemplateProcessor
return parent::fixBrokenMacros($documentPart); return parent::fixBrokenMacros($documentPart);
} }
public function splitTextIntoTexts($text)
{
return parent::splitTextIntoTexts($text);
}
public function textNeedsSplitting($text)
{
return parent::textNeedsSplitting($text);
}
public function getVariablesForPart($documentPartXML) public function getVariablesForPart($documentPartXML)
{ {
$documentPartXML = parent::fixBrokenMacros($documentPartXML); $documentPartXML = parent::fixBrokenMacros($documentPartXML);
@ -42,6 +52,24 @@ class TestableTemplateProcesor extends TemplateProcessor
return parent::getVariablesForPart($documentPartXML); return parent::getVariablesForPart($documentPartXML);
} }
public function findXmlBlockStart($offset, $blockType)
{
return parent::findXmlBlockStart($offset, $blockType);
}
public function findContainingXmlBlockForMacro($macro, $blockType = 'w:p')
{
return parent::findContainingXmlBlockForMacro($macro, $blockType);
}
public function getSlice($startPosition, $endPosition = 0)
{
return parent::getSlice($startPosition, $endPosition);
}
/**
* @return string
*/
public function getMainPart() public function getMainPart()
{ {
return $this->tempDocumentMainPart; return $this->tempDocumentMainPart;