diff --git a/CHANGELOG.md b/CHANGELOG.md
index d440989c..af226cf5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ v0.16.0 (xx dec 2018)
- Add support for setting images in TemplateProcessor @SailorMax #1170
- Add "Plain Text" type to SDT (Structured Document Tags) @morrisdj #1541
- Added possibility to index variables inside cloned block in TemplateProcessor @JPBetley #817
+- Added possibility to replace variables inside cloned block with values in TemplateProcessor @DIDoS #1392
### Fixed
- Fix regex in `cloneBlock` function @nicoder #1269
diff --git a/docs/templates-processing.rst b/docs/templates-processing.rst
index 6513cb24..095093b2 100644
--- a/docs/templates-processing.rst
+++ b/docs/templates-processing.rst
@@ -79,11 +79,34 @@ The result will be
Customer: ${customer_name#1}
Address: ${customer_address#1}
+
Customer: ${customer_name#2}
Address: ${customer_address#2}
+
Customer: ${customer_name#3}
Address: ${customer_address#3}
+It is also possible to pass an array with the values to replace the marcros with.
+If an array with replacements is passed, the ``count`` argument is ignored, it is the size of the array that counts.
+
+.. code-block:: php
+
+ $replacements = array(
+ array('customer_name' => 'Batman', 'customer_address' => 'Gotham City'),
+ array('customer_name' => 'Superman', 'customer_address' => 'Metropolis'),
+ );
+ $templateProcessor->cloneBlock('block_name', 0, true, false, $replacements);
+
+The result will then be
+
+.. code-block:: clean
+
+ Customer: Batman
+ Address: Gotham City
+
+ Customer: Superman
+ Address: Metropolis
+
replaceBlock
""""""""""""
Given a template containing
diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php
index 727dd74c..704352d4 100644
--- a/src/PhpWord/TemplateProcessor.php
+++ b/src/PhpWord/TemplateProcessor.php
@@ -632,10 +632,11 @@ class TemplateProcessor
* @param int $clones How many time the block should be cloned
* @param bool $replace
* @param bool $indexVariables If true, any variables inside the block will be indexed (postfixed with #1, #2, ...)
+ * @param array $variableReplacements Array containing replacements for macros found inside the block to clone
*
* @return string|null
*/
- public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVariables = false)
+ public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVariables = false, $variableReplacements = null)
{
$xmlBlock = null;
preg_match(
@@ -648,6 +649,8 @@ class TemplateProcessor
$xmlBlock = $matches[3];
if ($indexVariables) {
$cloned = $this->indexClonedVariables($clones, $xmlBlock);
+ } elseif ($variableReplacements !== null && is_array($variableReplacements)) {
+ $cloned = $this->replaceClonedVariables($variableReplacements, $xmlBlock);
} else {
$cloned = array();
for ($i = 1; $i <= $clones; $i++) {
@@ -960,4 +963,26 @@ class TemplateProcessor
return $results;
}
+
+ /**
+ * Raplaces variables with values from array, array keys are the variable names
+ *
+ * @param array $variableReplacements
+ * @param string $xmlBlock
+ *
+ * @return string[]
+ */
+ protected function replaceClonedVariables($variableReplacements, $xmlBlock)
+ {
+ $results = array();
+ foreach ($variableReplacements as $replacementArray) {
+ $localXmlBlock = $xmlBlock;
+ foreach ($replacementArray as $search => $replacement) {
+ $localXmlBlock = $this->setValueForPart(self::ensureMacroCompleted($search), $replacement, $localXmlBlock, self::MAXIMUM_REPLACEMENTS_DEFAULT);
+ }
+ $results[] = $localXmlBlock;
+ }
+
+ return $results;
+ }
}
diff --git a/tests/PhpWord/TemplateProcessorTest.php b/tests/PhpWord/TemplateProcessorTest.php
index 2c388299..2bca64ef 100644
--- a/tests/PhpWord/TemplateProcessorTest.php
+++ b/tests/PhpWord/TemplateProcessorTest.php
@@ -456,6 +456,39 @@ final class TemplateProcessorTest extends \PHPUnit\Framework\TestCase
$this->assertContains('Address ${address#3}, Street ${street#3}', $templateProcessor->getMainPart());
}
+ public function testCloneBlockWithVariableReplacements()
+ {
+ $mainPart = '
+
+
+
+ ${CLONEME}
+
+
+
+
+ City: ${city}, Street: ${street}
+
+
+
+
+ ${/CLONEME}
+
+ ';
+
+ $replacements = array(
+ array('city' => 'London', 'street' => 'Baker Street'),
+ array('city' => 'New York', 'street' => '5th Avenue'),
+ array('city' => 'Rome', 'street' => 'Via della Conciliazione'),
+ );
+ $templateProcessor = new TestableTemplateProcesor($mainPart);
+ $templateProcessor->cloneBlock('CLONEME', 0, true, false, $replacements);
+
+ $this->assertContains('City: London, Street: Baker Street', $templateProcessor->getMainPart());
+ $this->assertContains('City: New York, Street: 5th Avenue', $templateProcessor->getMainPart());
+ $this->assertContains('City: Rome, Street: Via della Conciliazione', $templateProcessor->getMainPart());
+ }
+
/**
* Template macros can be fixed.
*