Skip to content

Commit

Permalink
Update cloneBlock and replaceBlock
Browse files Browse the repository at this point in the history
Implements the fonction gave by brad-jones on the issue :
#341 (comment)
  • Loading branch information
chervaliery committed Jun 1, 2015
1 parent 3f13650 commit 8a8dbd0
Showing 1 changed file with 128 additions and 24 deletions.
152 changes: 128 additions & 24 deletions src/PhpWord/TemplateProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -233,22 +233,25 @@ public function cloneRow($search, $numberOfClones)
public function cloneBlock($blockname, $clones = 1, $replace = true)
{
$xmlBlock = null;
preg_match(
'/(<\?xml.*)(<w:p.*>\${' . $blockname . '}<\/w:.*?p>)(.*)(<w:p.*\${\/' . $blockname . '}<\/w:.*?p>)/is',
$this->temporaryDocumentMainPart,
$matches
);

$matches = $this->findBlock($blockname);

if (isset($matches[1]))
{
$xmlBlock = $matches[1];

if (isset($matches[3])) {
$xmlBlock = $matches[3];
$cloned = array();
for ($i = 1; $i <= $clones; $i++) {
$cloned[] = $xmlBlock;

for ($i = 1; $i <= $clones; $i++)
{
$cloned[] = preg_replace('/\${(.*?)}/','${$1_'.$i.'}', $xmlBlock);
}

if ($replace) {
$this->temporaryDocumentMainPart = str_replace(
$matches[2] . $matches[3] . $matches[4],
if ($replace)
{
$this->temporaryDocumentMainPart = str_replace
(
$matches[0],
implode('', $cloned),
$this->temporaryDocumentMainPart
);
Expand All @@ -267,18 +270,16 @@ public function cloneBlock($blockname, $clones = 1, $replace = true)
*/
public function replaceBlock($blockname, $replacement)
{
preg_match(
'/(<\?xml.*)(<w:p.*>\${' . $blockname . '}<\/w:.*?p>)(.*)(<w:p.*\${\/' . $blockname . '}<\/w:.*?p>)/is',
$this->temporaryDocumentMainPart,
$matches
);

if (isset($matches[3])) {
$this->temporaryDocumentMainPart = str_replace(
$matches[2] . $matches[3] . $matches[4],
$replacement,
$this->temporaryDocumentMainPart
);
$matches = $this->findBlock($blockname);

if (isset($matches[1]))
{
$this->temporaryDocumentMainPart = str_replace
(
$matches[0],
$replacement,
$this->temporaryDocumentMainPart
);
}
}

Expand Down Expand Up @@ -452,4 +453,107 @@ private function getSlice($startPosition, $endPosition = 0)

return substr($this->temporaryDocumentMainPart, $startPosition, ($endPosition - $startPosition));
}

private function findBlock($blockname)
{
// Parse the XML
$xml = new \SimpleXMLElement($this->temporaryDocumentMainPart);

// Find the starting and ending tags
$startNode = false; $endNode = false;
foreach ($xml->xpath('//w:t') as $node)
{
if (strpos($node, '${'.$blockname.'}') !== false)
{
$startNode = $node;
continue;
}

if (strpos($node, '${/'.$blockname.'}') !== false)
{
$endNode = $node;
break;
}
}

// Make sure we found the tags
if ($startNode === false || $endNode === false)
{
return null;
}

// Find the parent <w:p> node for the start tag
$node = $startNode; $startNode = null;
while (is_null($startNode))
{
$node = $node->xpath('..')[0];

if ($node->getName() == 'p')
{
$startNode = $node;
}
}

// Find the parent <w:p> node for the end tag
$node = $endNode; $endNode = null;
while (is_null($endNode))
{
$node = $node->xpath('..')[0];

if ($node->getName() == 'p')
{
$endNode = $node;
}
}

/*
* NOTE: Because SimpleXML reduces empty tags to "self-closing" tags.
* We need to replace the original XML with the version of XML as
* SimpleXML sees it. The following example should show the issue
* we are facing.
*
* This is the XML that my document contained orginally.
*
* ```xml
* <w:p>
* <w:pPr>
* <w:pStyle w:val="TextBody"/>
* <w:rPr></w:rPr>
* </w:pPr>
* <w:r>
* <w:rPr></w:rPr>
* <w:t>${CLONEME}</w:t>
* </w:r>
* </w:p>
* ```
*
* This is the XML that SimpleXML returns from asXml().
*
* ```xml
* <w:p>
* <w:pPr>
* <w:pStyle w:val="TextBody"/>
* <w:rPr/>
* </w:pPr>
* <w:r>
* <w:rPr/>
* <w:t>${CLONEME}</w:t>
* </w:r>
* </w:p>
* ```
*/

$this->temporaryDocumentMainPart = $xml->asXml();

// Find the xml in between the tags
$xmlBlock = null;
preg_match
(
'/'.preg_quote($startNode->asXml(), '/').'(.*?)'.preg_quote($endNode->asXml(), '/').'/is',
$this->temporaryDocumentMainPart,
$matches
);

return $matches;
}
}

0 comments on commit 8a8dbd0

Please sign in to comment.