Template Processor: Replace all occurrences in setImageValue when no limit is given
This commit is contained in:
1 parent
3984f68e11
commit
d54e8c7e16
3 files changed
+75
-8
No files matched your search
@@ -33,6 +33,7 @@
|
|||||||
- Reader Word2007: Read the size, position and wrapping of an image, from VML and DrawingML, instead of giving it the size of its pixels by [@dkulyk](https://github.com/dkulyk) in [#2947](https://github.com/PHPOffice/PHPWord/pull/2947)
|
- Reader Word2007: Read the size, position and wrapping of an image, from VML and DrawingML, instead of giving it the size of its pixels by [@dkulyk](https://github.com/dkulyk) in [#2947](https://github.com/PHPOffice/PHPWord/pull/2947)
|
||||||
- Writer ODText: Write the language of a text run, which was dropped, take any BCP 47 tag with its script, and use en-US for a document without a language as the Word2007 writer does, instead of fr-FR, zh-CN and hi-IN by [@dkulyk](https://github.com/dkulyk) in [#2944](https://github.com/PHPOffice/PHPWord/pull/2944)
|
- Writer ODText: Write the language of a text run, which was dropped, take any BCP 47 tag with its script, and use en-US for a document without a language as the Word2007 writer does, instead of fr-FR, zh-CN and hi-IN by [@dkulyk](https://github.com/dkulyk) in [#2944](https://github.com/PHPOffice/PHPWord/pull/2944)
|
||||||
- Writer Word2007: Point the page number of a table of contents entry at the bookmark of its title (`PAGEREF _Toc…`), and write the text of a title made of a text run by [@dkulyk](https://github.com/dkulyk) in [#2952](https://github.com/PHPOffice/PHPWord/pull/2952)
|
- Writer Word2007: Point the page number of a table of contents entry at the bookmark of its title (`PAGEREF _Toc…`), and write the text of a title made of a text run by [@dkulyk](https://github.com/dkulyk) in [#2952](https://github.com/PHPOffice/PHPWord/pull/2952)
|
||||||
|
- Template Processor: Replace every occurrence of an image variable in `setImageValue` when no limit is given, without adding unused image relations, by [@dualfroz](https://github.com/dualfroz) fixing [#2832](https://github.com/PHPOffice/PHPWord/issues/2832)
|
||||||
|
|
||||||
### Miscellaneous
|
### Miscellaneous
|
||||||
|
|
||||||
|
|||||||
@@ -698,6 +698,11 @@ class TemplateProcessor
|
|||||||
$preparedImageAttrs = $this->prepareImageAttrs($replaceImage, $varInlineArgs);
|
$preparedImageAttrs = $this->prepareImageAttrs($replaceImage, $varInlineArgs);
|
||||||
$imgPath = $preparedImageAttrs['src'];
|
$imgPath = $preparedImageAttrs['src'];
|
||||||
|
|
||||||
|
// replace variable
|
||||||
|
$varNameWithArgsFixed = static::ensureMacroCompleted($varNameWithArgs);
|
||||||
|
$matches = [];
|
||||||
|
// the occurrence may already be gone, replaced together with an identical one
|
||||||
|
if (preg_match('/(<[^<]+>)([^<]*)(' . preg_quote($varNameWithArgsFixed, '/') . ')([^>]*)(<[^>]+>)/Uu', $partContent, $matches)) {
|
||||||
// get image index
|
// get image index
|
||||||
$imgIndex = $this->getNextRelationsIndex($partFileName);
|
$imgIndex = $this->getNextRelationsIndex($partFileName);
|
||||||
$rid = 'rId' . $imgIndex;
|
$rid = 'rId' . $imgIndex;
|
||||||
@@ -706,10 +711,6 @@ class TemplateProcessor
|
|||||||
$this->addImageToRelations($partFileName, $rid, $imgPath, $preparedImageAttrs['mime']);
|
$this->addImageToRelations($partFileName, $rid, $imgPath, $preparedImageAttrs['mime']);
|
||||||
$xmlImage = str_replace(['{RID}', '{WIDTH}', '{HEIGHT}'], [$rid, $preparedImageAttrs['width'], $preparedImageAttrs['height']], $imgTpl);
|
$xmlImage = str_replace(['{RID}', '{WIDTH}', '{HEIGHT}'], [$rid, $preparedImageAttrs['width'], $preparedImageAttrs['height']], $imgTpl);
|
||||||
|
|
||||||
// replace variable
|
|
||||||
$varNameWithArgsFixed = static::ensureMacroCompleted($varNameWithArgs);
|
|
||||||
$matches = [];
|
|
||||||
if (preg_match('/(<[^<]+>)([^<]*)(' . preg_quote($varNameWithArgsFixed, '/') . ')([^>]*)(<[^>]+>)/Uu', $partContent, $matches)) {
|
|
||||||
$wholeTag = $matches[0];
|
$wholeTag = $matches[0];
|
||||||
array_shift($matches);
|
array_shift($matches);
|
||||||
[$openTag, $prefix, , $postfix, $closeTag] = $matches;
|
[$openTag, $prefix, , $postfix, $closeTag] = $matches;
|
||||||
@@ -718,7 +719,7 @@ class TemplateProcessor
|
|||||||
$partContent = $this->setValueForPart($wholeTag, $replaceXml, $partContent, $limit);
|
$partContent = $this->setValueForPart($wholeTag, $replaceXml, $partContent, $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++$i >= $limit) {
|
if (self::MAXIMUM_REPLACEMENTS_DEFAULT !== $limit && ++$i >= $limit) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1004,12 +1004,77 @@ final class TemplateProcessorTest extends \PHPUnit\Framework\TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Template processor of a document containing the variable ${Image}.
|
* @covers ::setImageValue
|
||||||
*/
|
*/
|
||||||
private function getImageTemplateProcessor(): TemplateProcessor
|
public function testSetImageValueReplacesAllOccurrencesByDefault(): void
|
||||||
|
{
|
||||||
|
$templateProcessor = $this->getImageTemplateProcessor(['${Image}', '${Image}', 'Signed: ${Image}']);
|
||||||
|
$templateProcessor->setImageValue('Image', __DIR__ . '/_files/images/earth.jpg');
|
||||||
|
|
||||||
|
[$mainPartXml, $relationsXml] = $this->saveAndReadMainPart($templateProcessor);
|
||||||
|
|
||||||
|
self::assertStringNotContainsString('${Image}', $mainPartXml);
|
||||||
|
self::assertStringContainsString('Signed: ', $mainPartXml);
|
||||||
|
self::assertSame(3, substr_count($mainPartXml, '<v:imagedata '));
|
||||||
|
self::assertImageRelationsMatchImages($mainPartXml, $relationsXml);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::setImageValue
|
||||||
|
*/
|
||||||
|
public function testSetImageValueWithLimit(): void
|
||||||
|
{
|
||||||
|
$templateProcessor = $this->getImageTemplateProcessor(['${Image}', '${Image}', 'Signed: ${Image}']);
|
||||||
|
$templateProcessor->setImageValue('Image', __DIR__ . '/_files/images/earth.jpg', 1);
|
||||||
|
|
||||||
|
[$mainPartXml, $relationsXml] = $this->saveAndReadMainPart($templateProcessor);
|
||||||
|
|
||||||
|
self::assertSame(2, substr_count($mainPartXml, '${Image}'));
|
||||||
|
self::assertSame(1, substr_count($mainPartXml, '<v:imagedata '));
|
||||||
|
self::assertImageRelationsMatchImages($mainPartXml, $relationsXml);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{string, string}
|
||||||
|
*/
|
||||||
|
private function saveAndReadMainPart(TemplateProcessor $templateProcessor): array
|
||||||
|
{
|
||||||
|
$resultFileName = (string) tempnam(Settings::getTempDir(), 'PHPWordResult');
|
||||||
|
$templateProcessor->saveAs($resultFileName);
|
||||||
|
|
||||||
|
$resultZip = new ZipArchive();
|
||||||
|
$resultZip->open($resultFileName);
|
||||||
|
$mainPartXml = (string) $resultZip->getFromName('word/document.xml');
|
||||||
|
$relationsXml = (string) $resultZip->getFromName('word/_rels/document.xml.rels');
|
||||||
|
$resultZip->close();
|
||||||
|
unlink($resultFileName);
|
||||||
|
|
||||||
|
return [$mainPartXml, $relationsXml];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Every image relation declared for the main part is used by an image, and every image uses a declared relation.
|
||||||
|
*/
|
||||||
|
private static function assertImageRelationsMatchImages(string $mainPartXml, string $relationsXml): void
|
||||||
|
{
|
||||||
|
preg_match_all('#<v:imagedata r:id="([^"]+)"#', $mainPartXml, $usedIds);
|
||||||
|
preg_match_all('#<Relationship Id="([^"]+)" Type="[^"]+/image"#', $relationsXml, $declaredIds);
|
||||||
|
|
||||||
|
self::assertEqualsCanonicalizing(array_values(array_unique($usedIds[1])), $declaredIds[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template processor of a document with a paragraph for each text, by default the variable ${Image}.
|
||||||
|
*
|
||||||
|
* @param string[] $texts
|
||||||
|
*/
|
||||||
|
private function getImageTemplateProcessor(array $texts = ['${Image}']): TemplateProcessor
|
||||||
{
|
{
|
||||||
$phpWord = new PhpWord();
|
$phpWord = new PhpWord();
|
||||||
$phpWord->addSection()->addText('${Image}');
|
$section = $phpWord->addSection();
|
||||||
|
foreach ($texts as $text) {
|
||||||
|
$section->addText($text);
|
||||||
|
}
|
||||||
$testFileName = (string) tempnam(Settings::getTempDir(), 'PHPWordTemplate');
|
$testFileName = (string) tempnam(Settings::getTempDir(), 'PHPWordTemplate');
|
||||||
IOFactory::createWriter($phpWord, 'Word2007')->save($testFileName);
|
IOFactory::createWriter($phpWord, 'Word2007')->save($testFileName);
|
||||||
$templateProcessor = new TemplateProcessor($testFileName);
|
$templateProcessor = new TemplateProcessor($testFileName);
|
||||||
|
|||||||
Reference in new issue
Block a user