Skip to content

Commit a450f66

Browse files
author
d-damien
committed
Bugfix PHPOffice#548: variables edited in word get messed with invisible XML
1 parent 5781f65 commit a450f66

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

src/PhpWord/TemplateProcessor.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,43 @@ public function applyXslStyleSheet($xslDOMDocument, $xslOptions = array(), $xslO
135135
$this->tempDocumentMainPart = $xmlTransformed;
136136
}
137137

138+
/**
139+
* Clean all template parts of hidden XML within variables/placeholders.
140+
*
141+
* @return void
142+
*/
143+
public function fixBrokenVariables()
144+
{
145+
$this->tempDocumentMainPart = $this->fixBrokenVariablesForPart($this->tempDocumentMainPart);
146+
147+
foreach ($this->tempDocumentHeaders as &$headerXML) {
148+
$headerXML = $this->fixBrokenVariablesForPart($headerXML);
149+
}
150+
151+
foreach ($this->tempDocumentFooters as &$footerXML) {
152+
$headerXML = $this->fixBrokenVariablesForPart($footerXML);
153+
}
154+
}
155+
156+
/**
157+
* Fix dirty hidden XML within variables in document part.
158+
*
159+
* @param string $documentPartXML said document part
160+
*
161+
* @return string
162+
*/
163+
protected function fixBrokenVariablesForPart(string $documentPartXML)
164+
{
165+
return
166+
preg_replace_callback(
167+
'|\$([^{]*)(\{.*})|U',
168+
function ($match) {
169+
return '$'.strip_tags($match[2]);
170+
},
171+
$documentPartXML
172+
);
173+
}
174+
138175
/**
139176
* @param mixed $macro
140177
* @param mixed $replace

tests/PhpWord/TemplateProcessorTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,30 @@ final public function testXslStyleSheetCanNotBeAppliedOnFailureOfLoadingXmlFromT
141141
@$templateProcessor->applyXslStyleSheet($xslDOMDocument);
142142
}
143143

144+
/**
145+
* @covers ::fixBrokenVariablesForPart
146+
* @test
147+
*/
148+
public function testFixBrokenVariablesForPart()
149+
{
150+
// accessing protected method via closure binding
151+
$template = new TemplateProcessor();
152+
$closure = function ($arg) {
153+
return $this->fixBrokenVariablesForPart($arg);
154+
};
155+
$method = $closure->bindTo($template, $template);
156+
157+
// example XML found in actual word document
158+
$actualDirtyXml = ''
159+
.'<w:szCs w:val="18"/>${</w:rPr>sps_telephone}<w:t>'
160+
.'$</w:t></w:r><w:r w:rsidR="00 C3064E" w:rsidRPr="00C3064E"><w:rPr><w:rFonts w:ascii="Arial" w:hAnsi="Arial" w:cs="Arial"/><w:noProof/><w:sz w:val="20"/><w:szCs w:val="18"/></w:rPr><w:t>'
161+
.'{sps</w:t></w:r><w:r w:rsidR="00243 BDA"><w:rPr><w:rFonts w:ascii="Arial" w:hAnsi="Arial" w:cs="Arial"/><w:noProof/><w:sz w:val="20"/><w:szCs w:val="18"/></w:rPr><w:t>'
162+
.'_</w:t></w:r><w:r w:rsidR="00C3064E" w:rsidRPr="00C3064E"><w:rPr><w:rFonts w:ascii="Arial" w:hAnsi="Arial" w:cs="Arial"/><w:noProof/><w:sz w:val="20"/><w:szCs w:val="18"/></w:rPr><w:t>nom}'.'${sps_mail}';
163+
164+
$expectedCleanXml = '<w:szCs w:val="18"/>${sps_telephone}<w:t>${sps_nom}${sps_mail}';
165+
$this->assertEquals($method($actualDirtyXml), $expectedCleanXml);
166+
}
167+
144168
/**
145169
* @civers ::setValue
146170
* @covers ::cloneRow

0 commit comments

Comments
 (0)