diff --git a/Classes/PHPWord/Template.php b/Classes/PHPWord/Template.php index eb6e42d2..a1b26714 100755 --- a/Classes/PHPWord/Template.php +++ b/Classes/PHPWord/Template.php @@ -64,7 +64,7 @@ class PHPWord_Template if ($this->_tempFileName !== false) { // Copy the source File to the temp File if (!copy($strFilename, $this->_tempFileName)) { - throw new PHPWord_Exception('Could not copy the template from ' . $strFilename . ' to ' . $this->_tempFileName . '.'); + throw new PHPWord_Exception("Could not copy the template from {$strFilename} to {$this->_tempFileName}."); } $this->_objZip = new ZipArchive(); @@ -75,6 +75,36 @@ class PHPWord_Template throw new PHPWord_Exception('Could not create temporary file with unique name in the default temporary directory.'); } } + + /** + * Applies XSL style sheet to template's parts + * + * @param DOMDocument &$xslDOMDocument + * @param array $xslOptions = array() + * @param string $xslOptionsURI = '' + */ + public function applyXslStyleSheet(&$xslDOMDocument, $xslOptions = array(), $xslOptionsURI = '') + { + $processor = new \XSLTProcessor(); + + $processor->importStylesheet($xslDOMDocument); + + if ($processor->setParameter($xslOptionsURI, $xslOptions) === false) { + throw new \Exception('Could not set values for the given XSL style sheet parameters.'); + } + + $xmlDOMDocument = new \DOMDocument(); + if ($xmlDOMDocument->loadXML($this->_documentXML) === false) { + throw new \Exception('Could not load XML from the given template.'); + } + + $xmlTransformed = $processor->transformToXml($xmlDOMDocument); + if ($xmlTransformed === false) { + throw new \Exception('Could not transform the given XML document.'); + } + + $this->_documentXML = $xmlTransformed; + } /** * Set a Template value diff --git a/Tests/PHPWord/TemplateTest.php b/Tests/PHPWord/TemplateTest.php new file mode 100644 index 00000000..1cc30639 --- /dev/null +++ b/Tests/PHPWord/TemplateTest.php @@ -0,0 +1,118 @@ +load( + \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'xsl', 'remove_tables_by_needle.xsl') + ) + ); + + foreach (array('${employee.', '${scoreboard.') as $needle) { + $template->applyXslStyleSheet($xslDOMDocument, array('needle' => $needle)); + } + + $actualDocument = $template->save(); + $expectedDocument = \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'documents', 'without_table_macros.docx') + ); + + $actualZip = new \ZipArchive(); + $actualZip->open($actualDocument); + $actualXml = $actualZip->getFromName('word/document.xml'); + if ($actualZip->close() === false) { + throw new \Exception('Could not close zip file "' . $actualDocument . '".'); + } + + $expectedZip = new \ZipArchive(); + $expectedZip->open($expectedDocument); + $expectedXml = $expectedZip->getFromName('word/document.xml'); + if ($expectedZip->close() === false) { + throw new \Exception('Could not close zip file "' . $expectedDocument . '".'); + } + + $this->assertXmlStringEqualsXmlString($expectedXml, $actualXml); + } + + /** + * @covers ::applyXslStyleSheet + * @expectedException Exception + * @expectedExceptionMessage Could not set values for the given XSL style sheet parameters. + * @test + */ + final public function testXslStyleSheetCanNotBeAppliedOnFailureOfSettingParameterValue() + { + $template = new PHPWord_Template( + \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'templates', 'blank.docx') + ) + ); + + $xslDOMDocument = new \DOMDocument(); + $xslDOMDocument->load( + \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'xsl', 'passthrough.xsl') + ) + ); + + /* + * We have to use error control below, because XSLTProcessor::setParameter omits warning on failure. + * This warning fails the test. + */ + @$template->applyXslStyleSheet($xslDOMDocument, array(1 => 'somevalue')); + } + + /** + * @covers ::applyXslStyleSheet + * @expectedException Exception + * @expectedExceptionMessage Could not load XML from the given template. + * @test + */ + final public function testXslStyleSheetCanNotBeAppliedOnFailureOfLoadingXmlFromTemplate() + { + $template = new PHPWord_Template( + \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'templates', 'corrupted_main_document_part.docx') + ) + ); + + $xslDOMDocument = new \DOMDocument(); + $xslDOMDocument->load( + \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'xsl', 'passthrough.xsl') + ) + ); + + /* + * We have to use error control below, because DOMDocument::loadXML omits warning on failure. + * This warning fails the test. + */ + @$template->applyXslStyleSheet($xslDOMDocument); + } +} \ No newline at end of file diff --git a/Tests/_files/documents/without_table_macros.docx b/Tests/_files/documents/without_table_macros.docx new file mode 100644 index 00000000..e4e9767f Binary files /dev/null and b/Tests/_files/documents/without_table_macros.docx differ diff --git a/Tests/_files/templates/blank.docx b/Tests/_files/templates/blank.docx new file mode 100644 index 00000000..071b7f35 Binary files /dev/null and b/Tests/_files/templates/blank.docx differ diff --git a/Tests/_files/templates/corrupted_main_document_part.docx b/Tests/_files/templates/corrupted_main_document_part.docx new file mode 100644 index 00000000..69712525 Binary files /dev/null and b/Tests/_files/templates/corrupted_main_document_part.docx differ diff --git a/Tests/_files/templates/with_table_macros.docx b/Tests/_files/templates/with_table_macros.docx new file mode 100644 index 00000000..cd5ed6ce Binary files /dev/null and b/Tests/_files/templates/with_table_macros.docx differ diff --git a/Tests/_files/xsl/passthrough.xsl b/Tests/_files/xsl/passthrough.xsl new file mode 100644 index 00000000..4ab21dd7 --- /dev/null +++ b/Tests/_files/xsl/passthrough.xsl @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Tests/_files/xsl/remove_tables_by_needle.xsl b/Tests/_files/xsl/remove_tables_by_needle.xsl new file mode 100644 index 00000000..1a7b1369 --- /dev/null +++ b/Tests/_files/xsl/remove_tables_by_needle.xsl @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/changelog.txt b/changelog.txt index 3edb75a8..b421fab6 100755 --- a/changelog.txt +++ b/changelog.txt @@ -37,6 +37,7 @@ Changes in branch for release 0.7.1 : - Feature: (ivanlanin) GH-48 GH-86 - Font: Superscript and subscript - Feature: (ivanlanin) GH-48 GH-86 - Paragraph: Hanging paragraph - Feature: (ivanlanin) GH-48 GH-86 - Section: Multicolumn and section break +- Feature: (RomanSyroeshko) GH-46 GH-47 GH-83 - Template : Ability to apply XSL style sheet to Template - QA: (Progi1984) - UnitTests - Feature: (ivanlanin) - General: PHPWord_Shared_Font::pointSizeToTwips() converter - Feature: (ivanlanin) - Paragraph: Ability to define normal paragraph style with PHPWord::setNormalStyle()