Skip to content

Instantly share code, notes, and snippets.

@japicoder
Last active March 28, 2023 05:34
Show Gist options
  • Save japicoder/722e6d2435a9b2dfcd057730898d4a24 to your computer and use it in GitHub Desktop.
Save japicoder/722e6d2435a9b2dfcd057730898d4a24 to your computer and use it in GitHub Desktop.
ExtendedTemplateProcessor class for PHPOffice/PHPWord that updates the relationships for links.
<?php
namespace App\Utils;
use PhpOffice\PhpWord\Element\Link;
use PhpOffice\PhpWord\Exception\Exception as PhpWordException;
use PhpOffice\PhpWord\TemplateProcessor;
class ExtendedTemplateProcessor extends TemplateProcessor
{
/**
* Add a reference for a new link into the template.
*
* @param Link $link
* @return Link
*/
public function addLinkValue(Link $link)
{
// This is not tested, but I think there might not be an entry in the
// relationships file for internal links.
if ($link->isInternal()) {
return $link;
}
// Update the link with a correct relation ID.
$rid = $this->getNextLinkRelationId();
$link->setRelationId($rid);
// Generate the XML content
$xmlRelation = $this->writeLinkRelationshipXML($link);
// Add link as relationship in XML relationships.
$mainPartName = $this->getMainPartName();
$this->tempDocumentRelations[$mainPartName] = str_replace('</Relationships>', $xmlRelation, $this->tempDocumentRelations[$mainPartName]) . '</Relationships>';
// The library adds 6 to the rId because it assumes we are starting
// from a blank document that has the 6 default rIds in it.
// We need to compensate for this.
if ($link->isInSection()) {
$link->setRelationId($rid - 6);
}
return $link;
}
/**
* Calculate what will be the next link relation Id.
* @return int
*/
public function getNextLinkRelationId()
{
// Set the relationship id number for the link.
$mainPartName = $this->getMainPartName();
return $this->getNextRelationsIndex($mainPartName);
}
/**
* Generate a relationship entry for a Link element.
* @param Link $link
* @return string
*/
private function writeLinkRelationshipXML(Link $link)
{
return $this->writeRelationshipXMLDefinition(
$link->getRelationId(),
'hyperlink',
$link->getSource(),
'External'
);
}
/**
* Write individual relationship entry.
*
* Format:
* <Relationship Id="rId..." Type="http://..." Target="....xml" TargetMode="..." />
*
* @param int $relId Relationship ID
* @param string $type Relationship type
* @param string $target Relationship target
* @param string $targetMode Relationship target mode
* @return string
*/
private function writeRelationshipXMLDefinition($relId, $type, $target, $targetMode = '')
{
$relId = 'rId' . $relId;
if ($targetMode != '') {
$targetMode = 'TargetMode="' . $targetMode . '"';
}
return strtr('<Relationship Id="%rid%" Type="%type%" Target="%target%" %targetMode% />', [
'%rid%' => $relId,
'%type%' => 'http://schemas.openxmlformats.org/' . $type,
'%target%' => $target,
'%targetMode%' => $targetMode,
]);
}
}
@alexisQuiroz
Copy link

puedes darme un ejemplo de uso?

@npth
Copy link

npth commented Mar 28, 2023

good solution, thanks.

usage example:

use PhpOffice\PhpWord\Element\TextRun;

$templateProcessor = new ExtendedTemplateProcessor('path/for_template.docx');
.......
$references = new TextRun();
$link = $references->addLink(hmlspecialchars('https://www.google.ru/search?q=test&newwindow=1'), 'Google', ['color' => '0000FF', 'underline' => 'single']);
$templateProcessor->addLinkValue($link);

$templateProcessor->setComplexValue('refs', $references);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment