Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/templates-processing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,17 @@ multirow from a single row in a template by using ``TemplateProcessor::cloneRow`
See ``Sample_23_TemplateBlock.php`` for example on how to clone a block
of text using ``TemplateProcessor::cloneBlock`` and delete a block of text using
``TemplateProcessor::deleteBlock``.

It is also possible to repeat a block with macros in the block (aka foreach).

Example:

.. code-block:: php

$templateProcessor = new TemplateProcessor('Template.docx');
$templateProcessor->repeatBlock('REPEATME', array(
array('FORENAME' => 'John', 'LASTNAME' => 'Donut'),
array('FORENAME' => 'Cat', 'LASTNAME' => 'Stefano')
));

See ``Sample_23_TemplateBlock.php`` for example on how to repeat a block.
6 changes: 6 additions & 0 deletions samples/Sample_23_TemplateBlock.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
// Everything between ${tag} and ${/tag}, will be deleted/erased.
$templateProcessor->deleteBlock('DELETEME');

// Everything between ${tag} and ${/tag}, will be repeated and macros within the block will be filled.
$templateProcessor->repeatBlock('REPEATME', array(
array('FORENAME' => 'John', 'LASTNAME' => 'Donut'),
array('FORENAME' => 'Cat', 'LASTNAME' => 'Stefano')
));

echo date('H:i:s'), ' Saving the result document...', EOL;
$templateProcessor->saveAs('results/Sample_23_TemplateBlock.docx');

Expand Down
Binary file modified samples/resources/Sample_23_TemplateBlock.docx
Binary file not shown.
32 changes: 32 additions & 0 deletions src/PhpWord/TemplateProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,38 @@ public function cloneRow($search, $numberOfClones)
$this->tempDocumentMainPart = $result;
}

public function repeatBlock($blockname, $replacements)
{

$xmlBlock = null;
preg_match(
'/(<\?xml.*)(<w:p.*>\${' . $blockname . '}<\/w:.*?p>)(.*)(<w:p.*\${\/' . $blockname . '}<\/w:.*?p>)/is',
$this->tempDocumentMainPart,
$matches
);

if (isset($matches[3])) {
$xmlBlock = $matches[3];
$cloned = array();
foreach ($replacements as $replacementArray) {
$localXmlBlock = $xmlBlock;
foreach ($replacementArray as $search => $replacement) {
$localXmlBlock = $this->setValueForPart(self::ensureMacroCompleted($search), $replacement, $localXmlBlock, self::MAXIMUM_REPLACEMENTS_DEFAULT);
}

$cloned[] = $localXmlBlock;
}

$this->tempDocumentMainPart = str_replace(
$matches[2] . $matches[3] . $matches[4],
implode('', $cloned),
$this->tempDocumentMainPart
);
}

return $xmlBlock;
}

/**
* Clone a block.
*
Expand Down
34 changes: 34 additions & 0 deletions tests/PhpWord/TemplateProcessorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,40 @@ public function testCloneDeleteBlock()
$this->assertTrue($docFound);
}

public function testRepeatBlock()
{
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/repeat-block.docx');

$this->assertEquals(
array('REPEATME', 'FORENAME', 'LASTNAME', '/REPEATME'),
$templateProcessor->getVariables()
);

$docName = 'repeat-block-result.docx';
$templateProcessor->repeatBlock('REPEATME', array(
array('FORENAME' => 'John', 'LASTNAME' => 'Donut'),
array('FORENAME' => 'Cat', 'LASTNAME' => 'Stefano')
));
$templateProcessor->saveAs($docName);
$docFound = file_exists($docName);
$this->assertTrue($docFound);

$actualDocumentZip = new \ZipArchive();
$actualDocumentZip->open($docName);
$actualMainPartXml = $actualDocumentZip->getFromName('word/document.xml');

if (false === $actualDocumentZip->close()) {
throw new \Exception("Could not close zip file \"{$docName}\".");
}

$this->assertRegexp('/John/', $actualMainPartXml);
$this->assertRegexp('/Cat/', $actualMainPartXml);
$this->assertRegexp('/Donut/', $actualMainPartXml);
$this->assertRegexp('/Stefano/', $actualMainPartXml);

unlink($docName);
}

/**
* @covers ::cloneBlock
* @test
Expand Down
Binary file added tests/PhpWord/_files/templates/repeat-block.docx
Binary file not shown.