Update Template processor setValue() improvements #614

This commit is contained in:
kazi Tanvir Ahsan 2015-09-10 23:46:48 +10:00
parent a123ce41e5
commit 873d41a872

View File

@ -1,4 +1,5 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
@ -68,8 +69,8 @@ class TemplateProcessor
* @throws \PhpOffice\PhpWord\Exception\CreateTemporaryFileException
* @throws \PhpOffice\PhpWord\Exception\CopyFileException
*/
public function __construct($documentTemplate)
{
public function __construct($documentTemplate) {
// Temporary document filename initialization
$this->tempDocumentFilename = tempnam(Settings::getTempDir(), 'PhpWord');
if (false === $this->tempDocumentFilename) {
@ -86,16 +87,12 @@ class TemplateProcessor
$this->zipClass->open($this->tempDocumentFilename);
$index = 1;
while (false !== $this->zipClass->locateName($this->getHeaderName($index))) {
$this->tempDocumentHeaders[$index] = $this->fixBrokenMacros(
$this->zipClass->getFromName($this->getHeaderName($index))
);
$this->tempDocumentHeaders[$index] = $this->fixBrokenMacros($this->zipClass->getFromName($this->getHeaderName($index)));
$index++;
}
$index = 1;
while (false !== $this->zipClass->locateName($this->getFooterName($index))) {
$this->tempDocumentFooters[$index] = $this->fixBrokenMacros(
$this->zipClass->getFromName($this->getFooterName($index))
);
$this->tempDocumentFooters[$index] = $this->fixBrokenMacros($this->zipClass->getFromName($this->getFooterName($index)));
$index++;
}
$this->tempDocumentMainPart = $this->fixBrokenMacros($this->zipClass->getFromName('word/document.xml'));
@ -112,8 +109,7 @@ class TemplateProcessor
*
* @throws \PhpOffice\PhpWord\Exception\Exception
*/
public function applyXslStyleSheet($xslDOMDocument, $xslOptions = array(), $xslOptionsURI = '')
{
public function applyXslStyleSheet($xslDOMDocument, $xslOptions = array(), $xslOptionsURI = '') {
$xsltProcessor = new \XSLTProcessor();
$xsltProcessor->importStylesheet($xslDOMDocument);
@ -142,12 +138,15 @@ class TemplateProcessor
*
* @return void
*/
public function setValue($macro, $replace, $limit = self::MAXIMUM_REPLACEMENTS_DEFAULT)
{
public function setValue($macro, $replace, $limit = self::MAXIMUM_REPLACEMENTS_DEFAULT) {
if (substr($macro, 0, 2) !== '${' && substr($macro, -1) !== '}') {
$macro = '${' . $macro . '}';
}
if (!String::isUTF8($replace)) {
$replace = utf8_encode($replace);
}
foreach ($this->tempDocumentHeaders as $index => $headerXML) {
$this->tempDocumentHeaders[$index] = $this->setValueForPart($this->tempDocumentHeaders[$index], $macro, $replace, $limit);
}
@ -164,8 +163,7 @@ class TemplateProcessor
*
* @return string[]
*/
public function getVariables()
{
public function getVariables() {
$variables = $this->getVariablesForPart($this->tempDocumentMainPart);
foreach ($this->tempDocumentHeaders as $headerXML) {
@ -189,8 +187,7 @@ class TemplateProcessor
*
* @throws \PhpOffice\PhpWord\Exception\Exception
*/
public function cloneRow($search, $numberOfClones)
{
public function cloneRow($search, $numberOfClones) {
if ('${' !== substr($search, 0, 2) && '}' !== substr($search, -1)) {
$search = '${' . $search . '}';
}
@ -206,6 +203,7 @@ class TemplateProcessor
// Check if there's a cell spanning multiple rows.
if (preg_match('#<w:vMerge w:val="restart"/>#', $xmlRow)) {
// $extraRowStart = $rowEnd;
$extraRowEnd = $rowEnd;
while (true) {
@ -219,10 +217,10 @@ class TemplateProcessor
// If tmpXmlRow doesn't contain continue, this row is no longer part of the spanned row.
$tmpXmlRow = $this->getSlice($extraRowStart, $extraRowEnd);
if (!preg_match('#<w:vMerge/>#', $tmpXmlRow) &&
!preg_match('#<w:vMerge w:val="continue" />#', $tmpXmlRow)) {
if (!preg_match('#<w:vMerge/>#', $tmpXmlRow) && !preg_match('#<w:vMerge w:val="continue" />#', $tmpXmlRow)) {
break;
}
// This row was a spanned row, update $rowEnd and search for the next row.
$rowEnd = $extraRowEnd;
}
@ -247,14 +245,9 @@ class TemplateProcessor
*
* @return string|null
*/
public function cloneBlock($blockname, $clones = 1, $replace = true)
{
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->tempDocumentMainPart,
$matches
);
preg_match('/(<\?xml.*)(<w:p.*>\${' . $blockname . '}<\/w:.*?p>)(.*)(<w:p.*\${\/' . $blockname . '}<\/w:.*?p>)/is', $this->tempDocumentMainPart, $matches);
if (isset($matches[3])) {
$xmlBlock = $matches[3];
@ -264,11 +257,7 @@ class TemplateProcessor
}
if ($replace) {
$this->tempDocumentMainPart = str_replace(
$matches[2] . $matches[3] . $matches[4],
implode('', $cloned),
$this->tempDocumentMainPart
);
$this->tempDocumentMainPart = str_replace($matches[2] . $matches[3] . $matches[4], implode('', $cloned), $this->tempDocumentMainPart);
}
}
@ -283,20 +272,11 @@ class TemplateProcessor
*
* @return void
*/
public function replaceBlock($blockname, $replacement)
{
preg_match(
'/(<\?xml.*)(<w:p.*>\${' . $blockname . '}<\/w:.*?p>)(.*)(<w:p.*\${\/' . $blockname . '}<\/w:.*?p>)/is',
$this->tempDocumentMainPart,
$matches
);
public function replaceBlock($blockname, $replacement) {
preg_match('/(<\?xml.*)(<w:p.*>\${' . $blockname . '}<\/w:.*?p>)(.*)(<w:p.*\${\/' . $blockname . '}<\/w:.*?p>)/is', $this->tempDocumentMainPart, $matches);
if (isset($matches[3])) {
$this->tempDocumentMainPart = str_replace(
$matches[2] . $matches[3] . $matches[4],
$replacement,
$this->tempDocumentMainPart
);
$this->tempDocumentMainPart = str_replace($matches[2] . $matches[3] . $matches[4], $replacement, $this->tempDocumentMainPart);
}
}
@ -307,8 +287,7 @@ class TemplateProcessor
*
* @return void
*/
public function deleteBlock($blockname)
{
public function deleteBlock($blockname) {
$this->replaceBlock($blockname, '');
}
@ -319,8 +298,7 @@ class TemplateProcessor
*
* @throws \PhpOffice\PhpWord\Exception\Exception
*/
public function save()
{
public function save() {
foreach ($this->tempDocumentHeaders as $index => $headerXML) {
$this->zipClass->addFromString($this->getHeaderName($index), $this->tempDocumentHeaders[$index]);
}
@ -348,8 +326,7 @@ class TemplateProcessor
*
* @return void
*/
public function saveAs($fileName)
{
public function saveAs($fileName) {
$tempFileName = $this->save();
if (file_exists($fileName)) {
@ -376,17 +353,12 @@ class TemplateProcessor
*
* @return string
*/
protected function fixBrokenMacros($documentPart)
{
protected function fixBrokenMacros($documentPart) {
$fixedDocumentPart = $documentPart;
$fixedDocumentPart = preg_replace_callback(
'|\$\{([^\}]+)\}|U',
function ($match) {
$fixedDocumentPart = preg_replace_callback('|\$\{([^\}]+)\}|U', function ($match) {
return strip_tags($match[0]);
},
$fixedDocumentPart
);
}, $fixedDocumentPart);
return $fixedDocumentPart;
}
@ -395,23 +367,19 @@ class TemplateProcessor
* Find and replace macros in the given XML section.
*
* @param string $documentPartXML
* @param string $search
* @param string $searchP
* @param string $replace
* @param integer $limit
*
* @return string
*/
protected function setValueForPart($documentPartXML, $search, $replace, $limit)
{
if (!String::isUTF8($replace)) {
$replace = utf8_encode($replace);
}
protected function setValueForPart($documentPartXML, $search, $replace, $limit) {
// Note: we can't use the same function for both cases here, because of performance considerations.
if (self::MAXIMUM_REPLACEMENTS_DEFAULT === $limit) {
return str_replace($search, $replace, $documentPartXML);
} else {
}
else {
$regExpDelim = '/';
$escapedSearch = preg_quote($search, $regExpDelim);
return preg_replace("{$regExpDelim}{$escapedSearch}{$regExpDelim}u", $replace, $documentPartXML, $limit);
@ -425,8 +393,7 @@ class TemplateProcessor
*
* @return string[]
*/
protected function getVariablesForPart($documentPartXML)
{
protected function getVariablesForPart($documentPartXML) {
preg_match_all('/\$\{(.*?)}/i', $documentPartXML, $matches);
return $matches[1];
@ -439,8 +406,7 @@ class TemplateProcessor
*
* @return string
*/
protected function getFooterName($index)
{
protected function getFooterName($index) {
return sprintf('word/footer%d.xml', $index);
}
@ -451,8 +417,7 @@ class TemplateProcessor
*
* @return string
*/
protected function getHeaderName($index)
{
protected function getHeaderName($index) {
return sprintf('word/header%d.xml', $index);
}
@ -465,8 +430,7 @@ class TemplateProcessor
*
* @throws \PhpOffice\PhpWord\Exception\Exception
*/
protected function findRowStart($offset)
{
protected function findRowStart($offset) {
$rowStart = strrpos($this->tempDocumentMainPart, '<w:tr ', ((strlen($this->tempDocumentMainPart) - $offset) * -1));
if (!$rowStart) {
@ -486,8 +450,7 @@ class TemplateProcessor
*
* @return integer
*/
protected function findRowEnd($offset)
{
protected function findRowEnd($offset) {
return strpos($this->tempDocumentMainPart, '</w:tr>', $offset) + 7;
}
@ -499,8 +462,7 @@ class TemplateProcessor
*
* @return string
*/
protected function getSlice($startPosition, $endPosition = 0)
{
protected function getSlice($startPosition, $endPosition = 0) {
if (!$endPosition) {
$endPosition = strlen($this->tempDocumentMainPart);
}