Skip to content

Commit

Permalink
PHPOffice#260 - A quick hack around
Browse files Browse the repository at this point in the history
A quick hack solution I came up with today. This isn't pretty in the
slightest and is my first pull request so apologise if I've done it
wrong. I normally work on BitBucket.

Example Usage
------------------

$templateProcessor = new
\PhpOffice\PhpWord\TemplateProcessor('C:\Users\Robert\Desktop\sample.docx');

$templateProcessor->cloneRow('rowValue', 10);
$templateProcessor->setValue('test#1', htmlspecialchars('Text goes
here'));
$templateProcessor->setImageValue('testPhoto#1', 'image3.png',
'my-other-image.jpg');
$templateProcessor->setValue('test#2', htmlspecialchars('Text2 goes
here'));
$templateProcessor->setImageValue('testPhoto#2', 'image4.png',
my-image.jpg');
  • Loading branch information
OAFCROB committed Jun 29, 2015
1 parent 3f13650 commit ca52b09
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/PhpWord/Reader/Word2007.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile,
* @param string $docFile
* @return array
*/
private function readRelationships($docFile)
public function readRelationships($docFile)
{
$relationships = array();

Expand Down
127 changes: 127 additions & 0 deletions src/PhpWord/TemplateProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Shared\String;
use PhpOffice\PhpWord\Shared\ZipArchive;
use PhpOffice\PhpWord\Reader\Word2007;

class TemplateProcessor
{
Expand Down Expand Up @@ -58,6 +59,13 @@ class TemplateProcessor
*/
private $temporaryDocumentFooters = array();

/**
* Contents of the images added to the template
*
* @var string[]
*/
private $imageData = array();

/**
* @since 0.12.0 Throws CreateTemporaryFileException and CopyFileException instead of Exception.
*
Expand Down Expand Up @@ -145,6 +153,35 @@ public function setValue($search, $replace, $limit = -1)
}
}

/**
* Set a new image
*
* @param string $search
* @param string $replace
*/
public function setImageValue($search, $img, $imgSource)
{
// Sanity check
if (!file_exists($imgSource)) {
return;
}

// Delete current image
$this->zipClass->deleteName('word/media/' . $img);

// Add a new one
$this->zipClass->addFile($imgSource, 'word/media/' . $img);

$id = 1000;
if (strpos($search, "#")) {
$id = ($id + (int) substr($search, strpos($search, "#") + 1));
}

$this->imageData['rId'.$id] = ['type' => 'image', 'target' => 'word/media/'.$img, 'docPart' => 'media/'.$img];

$this->setValue($search, $this->getImgTag($id, $img));
}

/**
* Returns array of all variables in template.
*
Expand Down Expand Up @@ -175,6 +212,7 @@ public function getVariables()
*/
public function cloneRow($search, $numberOfClones)
{

if (substr($search, 0, 2) !== '${' && substr($search, -1) !== '}') {
$search = '${' . $search . '}';
}
Expand Down Expand Up @@ -307,6 +345,40 @@ public function save()

$this->zipClass->addFromString('word/document.xml', $this->temporaryDocumentMainPart);

$word = new Word2007();
$read = $word->readRelationships($this->zipClass->filename);

if (count($this->imageData)) {
$read['document'] = array_merge($read['document'], $this->imageData);
$xml = new \XMLWriter();
$xml->openMemory();
$xml->setIndent(true);
$xml->startDocument('1.0', 'UTF-8');
$xml->startElement('Relationships');
$xml->startAttribute('xmlns');
$xml->text('http:https://schemas.openxmlformats.org/package/2006/relationships');
$xml->endAttribute();
foreach ($read['document'] as $key => $data) {
$xml->startElement('Relationship');
$xml->startAttribute('Id');
$xml->text($key);
$xml->endAttribute();
$xml->startAttribute('Type');
$xml->text(
'http:https://schemas.openxmlformats.org/officeDocument/2006/relationships/'.$data['type']
);
$xml->endAttribute();
$xml->startAttribute('Target');
$xml->text($data['type'] === 'image' ? $data['docPart'] : $data['docPart'].'.xml');
$xml->endAttribute();
$xml->endElement();
}
$xml->endElement();
$xml->endDocument();
}

$this->zipClass->addFromString('word/_rels/document.xml.rels', $xml->outputMemory(true));

foreach ($this->temporaryDocumentFooters as $index => $headerXML) {
$this->zipClass->addFromString($this->getFooterName($index), $this->temporaryDocumentFooters[$index]);
}
Expand Down Expand Up @@ -383,6 +455,61 @@ protected function getVariablesForPart($documentPartXML)
return $matches[1];
}

protected function getImgTag($id, $imgName)
{
return '<w:p w:rsidR="00CC1A5D" w:rsidRDefault="00CC1A5D" w:rsidP="003D6476">'.
'<w:bookmarkStart w:id="0" w:name="_GoBack"/>'.
'<w:r>'.
'<w:rPr>'.
'<w:noProof/>'.
'<w:lang w:eastAsia="en-GB"/>'.
'</w:rPr>'.
'<w:drawing>'.
'<wp:inline distT="0" distB="0" distL="0" distR="0">'.
'<wp:extent cx="2857143" cy="1142857"/>'.
'<wp:effectExtent l="0" t="0" r="635" b="0"/>'.
'<wp:docPr id="2" name="Picture 2"/>'.
'<wp:cNvGraphicFramePr>'.
'<a:graphicFrameLocks xmlns:a="http:https://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1"/>'.
'</wp:cNvGraphicFramePr>'.
'<a:graphic xmlns:a="http:https://schemas.openxmlformats.org/drawingml/2006/main">'.
'<a:graphicData uri="http:https://schemas.openxmlformats.org/drawingml/2006/picture">'.
'<pic:pic xmlns:pic="http:https://schemas.openxmlformats.org/drawingml/2006/picture">'.
'<pic:nvPicPr>'.
'<pic:cNvPr id="'.$id.'" name="'.$imgName.'"/>'.
'<pic:cNvPicPr/>'.
'</pic:nvPicPr>'.
'<pic:blipFill>'.
'<a:blip r:embed="rId'.$id.'">'.
'<a:extLst>'.
'<a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}">'.
'<a14:useLocalDpi xmlns:a14="http:https://schemas.microsoft.com/office/drawing/2010/main" val="0"/>'.
'</a:ext>'.
'</a:extLst>'.
'</a:blip>'.
'<a:stretch>'.
'<a:fillRect/>'.
'</a:stretch>'.
'</pic:blipFill>'.
'<pic:spPr>'.
'<a:xfrm>'.
'<a:off x="0" y="0"/>'.
'<a:ext cx="2857143" cy="1142857"/>'.
'</a:xfrm>'.
'<a:prstGeom prst="rect">'.
'<a:avLst/>'.
'</a:prstGeom>'.
'</pic:spPr>'.
'</pic:pic>'.
'</a:graphicData>'.
'</a:graphic>'.
'</wp:inline>'.
'</w:drawing>'.
'</w:r>'.
'<w:bookmarkEnd w:id="0"/>'.
'</w:p>';
}

/**
* Get the name of the footer file for $index.
*
Expand Down

3 comments on commit ca52b09

@tartarsaucemedia
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't work. I get corrupt docx and cannot open.

@Salman456
Copy link

@Salman456 Salman456 commented on ca52b09 Jul 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OAFCROB Can you please add the code you used in the template.docx

@OAFCROB
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issues I've had with a corrupt document have been related to word spell checking the words. If you rename the file to a .zip then look at the components see if your tags are still intact, this is a massive problem with PHP Word that I've found.

Please sign in to comment.