This commit is contained in:
parent
1c5bb3a911
commit
d57973693d
|
|
@ -12,6 +12,7 @@ Place announcement text here.
|
||||||
- Introduced the `\PhpOffice\PhpWord\SimpleType\JcTable` simple type. - @RomanSyroeshko
|
- Introduced the `\PhpOffice\PhpWord\SimpleType\JcTable` simple type. - @RomanSyroeshko
|
||||||
- Introduced writer for the "Paragraph Alignment" element (see `\PhpOffice\PhpWord\Writer\Word2007\Element\ParagraphAlignment`). - @RomanSyroeshko
|
- Introduced writer for the "Paragraph Alignment" element (see `\PhpOffice\PhpWord\Writer\Word2007\Element\ParagraphAlignment`). - @RomanSyroeshko
|
||||||
- Introduced writer for the "Table Alignment" element (see `\PhpOffice\PhpWord\Writer\Word2007\Element\TableAlignment`). - @RomanSyroeshko
|
- Introduced writer for the "Table Alignment" element (see `\PhpOffice\PhpWord\Writer\Word2007\Element\TableAlignment`). - @RomanSyroeshko
|
||||||
|
- Supported indexed arrays in arguments of `TemplateProcessor::setValue()`. - @RomanSyroeshko #618
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Improved error message for the case when `autoload.php` is not found. - @RomanSyroeshko #371
|
- Improved error message for the case when `autoload.php` is not found. - @RomanSyroeshko #371
|
||||||
|
|
@ -39,7 +40,7 @@ so installation via ZIP-archive download is not an option anymore. To install PH
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- `Undefined property` error while reading MS-DOC documents. - @jaberu #610
|
- `Undefined property` error while reading MS-DOC documents. - @jaberu #610
|
||||||
- Corrupted OOXML template issue in case when its macro is broken immediately after `$` sign.
|
- Corrupted OOXML template issue in case when its names is broken immediately after `$` sign.
|
||||||
That case wasn't taken into account in implementation of `TemplateProcessor::fixBrokenMacros()`. - @RomanSyroeshko @d-damien #548
|
That case wasn't taken into account in implementation of `TemplateProcessor::fixBrokenMacros()`. - @RomanSyroeshko @d-damien #548
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.3",
|
"php": ">=5.3.3",
|
||||||
"ext-xml": "*",
|
"ext-xml": "*",
|
||||||
"zendframework/zend-validator": "2.5.*",
|
|
||||||
"zendframework/zend-stdlib": "~2.5",
|
"zendframework/zend-stdlib": "~2.5",
|
||||||
|
"zendframework/zend-validator": "2.5.*",
|
||||||
"phpoffice/common": "0.2.*"
|
"phpoffice/common": "0.2.*"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
|
@ -47,8 +47,8 @@
|
||||||
"dompdf/dompdf":"0.6.*",
|
"dompdf/dompdf":"0.6.*",
|
||||||
"tecnickcom/tcpdf": "6.*",
|
"tecnickcom/tcpdf": "6.*",
|
||||||
"mpdf/mpdf": "5.*",
|
"mpdf/mpdf": "5.*",
|
||||||
"zendframework/zend-validator": "2.5.*",
|
|
||||||
"zendframework/zend-stdlib": "~2.5",
|
"zendframework/zend-stdlib": "~2.5",
|
||||||
|
"zendframework/zend-validator": "2.5.*",
|
||||||
"phpoffice/common": "0.2.*"
|
"phpoffice/common": "0.2.*"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Templates processing
|
Templates processing
|
||||||
====================
|
====================
|
||||||
|
|
||||||
You can create a .docx document template with included search-patterns which can be replaced by any value you wish. Only single-line values can be replaced.
|
You can create an OOXML document template with included search-patterns (macros) which can be replaced by any value you wish. Only single-line values can be replaced.
|
||||||
|
|
||||||
To deal with a template file, use ``new TemplateProcessor`` statement. After TemplateProcessor instance creation the document template is copied into the temporary directory. Then you can use ``TemplateProcessor::setValue`` method to change the value of a search pattern. The search-pattern model is: ``${search-pattern}``.
|
To deal with a template file, use ``new TemplateProcessor`` statement. After TemplateProcessor instance creation the document template is copied into the temporary directory. Then you can use ``TemplateProcessor::setValue`` method to change the value of a search pattern. The search-pattern model is: ``${search-pattern}``.
|
||||||
|
|
||||||
|
|
@ -12,8 +12,8 @@ Example:
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
$templateProcessor = new TemplateProcessor('Template.docx');
|
$templateProcessor = new TemplateProcessor('Template.docx');
|
||||||
$templateProcessor->setValue('Name', 'Somebody someone');
|
$templateProcessor->setValue('Name', 'John Doe');
|
||||||
$templateProcessor->setValue('Street', 'Coming-Undone-Street 32');
|
$templateProcessor->setValue(array('City', 'Street'), array('Detroit', '12th Street'));
|
||||||
|
|
||||||
It is not possible to directly add new OOXML elements to the template file being processed, but it is possible to transform main document part of the template using XSLT (see ``TemplateProcessor::applyXslStyleSheet``).
|
It is not possible to directly add new OOXML elements to the template file being processed, but it is possible to transform main document part of the template using XSLT (see ``TemplateProcessor::applyXslStyleSheet``).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of PHPWord - A pure PHP library for reading and writing
|
||||||
|
* word processing documents.
|
||||||
|
*
|
||||||
|
* PHPWord is free software distributed under the terms of the GNU Lesser
|
||||||
|
* General Public License version 3 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the LICENSE
|
||||||
|
* file that was distributed with this source code. For the full list of
|
||||||
|
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
|
||||||
|
*
|
||||||
|
* @link https://github.com/PHPOffice/PHPWord
|
||||||
|
* @copyright 2010-2016 PHPWord contributors
|
||||||
|
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpWord\Escaper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.13.0
|
||||||
|
*/
|
||||||
|
interface EscaperInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param mixed $subject
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function escape($subject);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of PHPWord - A pure PHP library for reading and writing
|
||||||
|
* word processing documents.
|
||||||
|
*
|
||||||
|
* PHPWord is free software distributed under the terms of the GNU Lesser
|
||||||
|
* General Public License version 3 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the LICENSE
|
||||||
|
* file that was distributed with this source code. For the full list of
|
||||||
|
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
|
||||||
|
*
|
||||||
|
* @link https://github.com/PHPOffice/PHPWord
|
||||||
|
* @copyright 2010-2016 PHPWord contributors
|
||||||
|
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpWord\Escaper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.13.0
|
||||||
|
*/
|
||||||
|
class RegExp implements EscaperInterface
|
||||||
|
{
|
||||||
|
const REG_EXP_DELIMITER = '/';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $subject
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected static function escapeSingleItem($subject)
|
||||||
|
{
|
||||||
|
return self::REG_EXP_DELIMITER . preg_quote($subject, self::REG_EXP_DELIMITER) . self::REG_EXP_DELIMITER . 'u';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function escape($subject)
|
||||||
|
{
|
||||||
|
if (is_array($subject)) {
|
||||||
|
foreach ($subject as &$item) {
|
||||||
|
$item = self::escapeSingleItem($item);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$subject = self::escapeSingleItem($subject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $subject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpWord;
|
namespace PhpOffice\PhpWord;
|
||||||
|
|
||||||
|
use PhpOffice\PhpWord\Escaper\RegExp;
|
||||||
use PhpOffice\PhpWord\Exception\CopyFileException;
|
use PhpOffice\PhpWord\Exception\CopyFileException;
|
||||||
use PhpOffice\PhpWord\Exception\CreateTemporaryFileException;
|
use PhpOffice\PhpWord\Exception\CreateTemporaryFileException;
|
||||||
use PhpOffice\PhpWord\Exception\Exception;
|
use PhpOffice\PhpWord\Exception\Exception;
|
||||||
|
|
@ -136,31 +137,61 @@ class TemplateProcessor
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $macro
|
* @param string $macro
|
||||||
* @param mixed $replace
|
|
||||||
* @param integer $limit
|
|
||||||
*
|
*
|
||||||
* @return void
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function setValue($macro, $replace, $limit = self::MAXIMUM_REPLACEMENTS_DEFAULT)
|
protected static function ensureMacroCompleted($macro)
|
||||||
{
|
{
|
||||||
if (substr($macro, 0, 2) !== '${' && substr($macro, -1) !== '}') {
|
if (substr($macro, 0, 2) !== '${' && substr($macro, -1) !== '}') {
|
||||||
$macro = '${' . $macro . '}';
|
$macro = '${' . $macro . '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!StringUtils::isValidUtf8($replace)) {
|
return $macro;
|
||||||
$replace = utf8_encode($replace);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->tempDocumentHeaders as $index => $headerXML) {
|
/**
|
||||||
$this->tempDocumentHeaders[$index] = $this->setValueForPart($this->tempDocumentHeaders[$index], $macro, $replace, $limit);
|
* @param string $subject
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected static function ensureUtf8Encoded($subject)
|
||||||
|
{
|
||||||
|
if (!StringUtils::isValidUtf8($subject)) {
|
||||||
|
$subject = utf8_encode($subject);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->tempDocumentMainPart = $this->setValueForPart($this->tempDocumentMainPart, $macro, $replace, $limit);
|
return $subject;
|
||||||
|
|
||||||
foreach ($this->tempDocumentFooters as $index => $headerXML) {
|
|
||||||
$this->tempDocumentFooters[$index] = $this->setValueForPart($this->tempDocumentFooters[$index], $macro, $replace, $limit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $search
|
||||||
|
* @param mixed $replace
|
||||||
|
* @param integer $limit
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setValue($search, $replace, $limit = self::MAXIMUM_REPLACEMENTS_DEFAULT)
|
||||||
|
{
|
||||||
|
if (is_array($search)) {
|
||||||
|
foreach ($search as &$item) {
|
||||||
|
$item = self::ensureMacroCompleted($item);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$search = self::ensureMacroCompleted($search);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($replace)) {
|
||||||
|
foreach ($replace as &$item) {
|
||||||
|
$item = self::ensureUtf8Encoded($item);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$replace = self::ensureUtf8Encoded($replace);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->tempDocumentHeaders = $this->setValueForPart($search, $replace, $this->tempDocumentHeaders, $limit);
|
||||||
|
$this->tempDocumentMainPart = $this->setValueForPart($search, $replace, $this->tempDocumentMainPart, $limit);
|
||||||
|
$this->tempDocumentFooters = $this->setValueForPart($search, $replace, $this->tempDocumentFooters, $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -398,22 +429,20 @@ class TemplateProcessor
|
||||||
/**
|
/**
|
||||||
* Find and replace macros in the given XML section.
|
* Find and replace macros in the given XML section.
|
||||||
*
|
*
|
||||||
|
* @param mixed $search
|
||||||
|
* @param mixed $replace
|
||||||
* @param string $documentPartXML
|
* @param string $documentPartXML
|
||||||
* @param string $search
|
|
||||||
* @param string $replace
|
|
||||||
* @param integer $limit
|
* @param integer $limit
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function setValueForPart($documentPartXML, $search, $replace, $limit)
|
protected function setValueForPart($search, $replace, $documentPartXML, $limit)
|
||||||
{
|
{
|
||||||
// Note: we can't use the same function for both cases here, because of performance considerations.
|
// Note: we can't use the same function for both cases here, because of performance considerations.
|
||||||
if (self::MAXIMUM_REPLACEMENTS_DEFAULT === $limit) {
|
if (self::MAXIMUM_REPLACEMENTS_DEFAULT === $limit) {
|
||||||
return str_replace($search, $replace, $documentPartXML);
|
return str_replace($search, $replace, $documentPartXML);
|
||||||
} else {
|
} else {
|
||||||
$regExpDelim = '/';
|
return preg_replace(RegExp::escape($search), $replace, $documentPartXML, $limit);
|
||||||
$escapedSearch = preg_quote($search, $regExpDelim);
|
|
||||||
return preg_replace("{$regExpDelim}{$escapedSearch}{$regExpDelim}u", $replace, $documentPartXML, $limit);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -175,15 +175,17 @@ final class TemplateProcessorTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx');
|
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx');
|
||||||
|
|
||||||
$this->assertEquals(
|
$this->assertEquals(array('documentContent', 'headerValue', 'footerValue'), $templateProcessor->getVariables());
|
||||||
array('documentContent', 'headerValue', 'footerValue'),
|
|
||||||
$templateProcessor->getVariables()
|
$macroNames = array('headerValue', 'documentContent', 'footerValue');
|
||||||
|
$macroValues = array(
|
||||||
|
htmlspecialchars('Header Value', ENT_COMPAT, 'UTF-8'),
|
||||||
|
htmlspecialchars('Document text.', ENT_COMPAT, 'UTF-8'),
|
||||||
|
htmlspecialchars('Footer Value', ENT_COMPAT, 'UTF-8')
|
||||||
);
|
);
|
||||||
|
$templateProcessor->setValue($macroNames, $macroValues);
|
||||||
|
|
||||||
$docName = 'header-footer-test-result.docx';
|
$docName = 'header-footer-test-result.docx';
|
||||||
$templateProcessor->setValue('headerValue', htmlspecialchars('Header Value', ENT_COMPAT, 'UTF-8'));
|
|
||||||
$templateProcessor->setValue('documentContent', htmlspecialchars('Document text.', ENT_COMPAT, 'UTF-8'));
|
|
||||||
$templateProcessor->setValue('footerValue', htmlspecialchars('Footer Value', ENT_COMPAT, 'UTF-8'));
|
|
||||||
$templateProcessor->saveAs($docName);
|
$templateProcessor->saveAs($docName);
|
||||||
$docFound = file_exists($docName);
|
$docFound = file_exists($docName);
|
||||||
unlink($docName);
|
unlink($docName);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue