Add element availability matrix and enable `addObject` in footnote and textrun

This commit is contained in:
Ivan Lanin 2014-04-02 09:01:44 +07:00
parent 6f7b97e3ab
commit 495930be9d
19 changed files with 330 additions and 280 deletions

View File

@ -19,11 +19,19 @@ This is the changelog between releases of PHPWord. Releases are listed in revers
- ListItem: Ability to add list item in header/footer - @ivanlanin GH-187
- CheckBox: Ability to add checkbox in header/footer - @ivanlanin GH-187
- Link: Ability to add link in header/footer - @ivanlanin GH-187
- Object: Ability to add object in textrun and footnote - @ivanlanin GH-187
### Bugfixes
- Footnote: Footnote content doesn't show footnote reference number - @ivanlanin GH-170
### Deprecated
- `createTextRun` replaced by `addTextRun`
- `createFootnote` replaced by `addFootnote`
- `createHeader` replaced by `addHeader`
- `createFooter` replaced by `addFooter`
### Miscellaneous
- Documentation: Simplify page level docblock - @ivanlanin GH-179

View File

@ -3,6 +3,51 @@
Elements
========
Below are the matrix of element availability in each container. The column shows
the containers while the rows lists the elements.
+-----+---------------+---------+--------+--------+------+----------+----------+
| Num | Element | Section | Header | Footer | Cell | Text Run | Footnote |
+=====+===============+=========+========+========+======+==========+==========+
| 1 | Text | v | v | v | v | v | v |
+-----+---------------+---------+--------+--------+------+----------+----------+
| 2 | Text Run | v | v | v | v | \- | \- |
+-----+---------------+---------+--------+--------+------+----------+----------+
| 3 | Link | v | v | v | v | v | v |
+-----+---------------+---------+--------+--------+------+----------+----------+
| 4 | Title | v | ? | ? | ? | ? | ? |
+-----+---------------+---------+--------+--------+------+----------+----------+
| 5 | Preserve Text | ? | v | v | v\* | ? | ? |
+-----+---------------+---------+--------+--------+------+----------+----------+
| 6 | Text Break | v | v | v | v | v | v |
+-----+---------------+---------+--------+--------+------+----------+----------+
| 7 | Page Break | v | \- | \- | \- | \- | \- |
+-----+---------------+---------+--------+--------+------+----------+----------+
| 8 | List | v | v | v | v | \- | \- |
+-----+---------------+---------+--------+--------+------+----------+----------+
| 9 | Table | v | v | v | ? | \- | \- |
+-----+---------------+---------+--------+--------+------+----------+----------+
| 10 | Image | v | v | v | v | v | v |
+-----+---------------+---------+--------+--------+------+----------+----------+
| 11 | Watermark | \- | v | \- | \- | \- | \- |
+-----+---------------+---------+--------+--------+------+----------+----------+
| 12 | Object | v | ? | ? | v | v | v |
+-----+---------------+---------+--------+--------+------+----------+----------+
| 13 | TOC | v | \- | \- | \- | \- | \- |
+-----+---------------+---------+--------+--------+------+----------+----------+
| 14 | Footnote | v | \- | \- | v\*\*| v\*\* | \- |
+-----+---------------+---------+--------+--------+------+----------+----------+
| 15 | CheckBox | v | v | v | v | ? | ? |
+-----+---------------+---------+--------+--------+------+----------+----------+
Legend:
- ``v`` Available
- ``v*`` Available only when inside header/footer
- ``v**`` Available only when inside section
- ``-`` Not available
- ``?`` Should be available
Texts
-----

View File

@ -29,6 +29,8 @@ $textrun->addText(' Sample Link: ');
$textrun->addLink('http://www.google.com', null, 'NLink');
$textrun->addText(' Sample Image: ');
$textrun->addImage('resources/_earth.jpg', array('width' => 18, 'height' => 18));
$textrun->addText(' Sample Object: ');
$textrun->addObject('resources/_sheet.xls');
$textrun->addText(' Here is some more text. ');
// Save file

View File

@ -27,8 +27,10 @@ $footnote->addTextBreak();
$footnote->addText('But you can insert a manual text break like above, ');
$footnote->addText('links like ');
$footnote->addLink('http://www.google.com', null, 'NLink');
$footnote->addText(', or image like ');
$footnote->addText(', image like ');
$footnote->addImage('resources/_earth.jpg', array('width' => 18, 'height' => 18));
$footnote->addText(', or object like ');
$footnote->addObject('resources/_sheet.xls');
$footnote->addText('But you can only put footnote in section, not in header or footer.');
$section->addText('You can also create the footnote directly from the section making it wrap in a paragraph like the footnote below this paragraph. But is is best used from within a textrun.');

View File

@ -37,21 +37,21 @@ use PhpOffice\PhpWord\Element\CheckBox;
abstract class Container
{
/**
* Container type section|header|footer
* Container type section|header|footer|cell|textrun|footnote
*
* @var string
*/
protected $containerType;
protected $container;
/**
* Section Id
*
* @var int
*/
protected $sectionId;
protected $containerId;
/**
* Footer Element Collection
* Elements collection
*
* @var int
*/
@ -62,11 +62,11 @@ abstract class Container
*
* Used by textrun and cell to determine where the element is located
* because it will affect the availability of other element, e.g. footnote
* will not be available when $docPartType is header or footer.
* will not be available when $docPart is header or footer.
*
* @var string
*/
protected $docPartType = null;
protected $docPart = null;
/**
* Document part Id
@ -92,9 +92,13 @@ abstract class Container
*/
public function addText($text, $fontStyle = null, $paragraphStyle = null)
{
if (in_array($this->containerType, array('footnote', 'textrun'))) {
$this->checkValidity('text');
// Reset paragraph style for footnote and textrun. They have their own
if (in_array($this->container, array('footnote', 'textrun'))) {
$paragraphStyle = null;
}
$text = String::toUTF8($text);
$element = new Text($text, $fontStyle, $paragraphStyle);
$this->elements[] = $element;
@ -102,20 +106,6 @@ abstract class Container
return $element;
}
/**
* Add text break element
*
* @param int $count
* @param mixed $fontStyle
* @param mixed $paragraphStyle
*/
public function addTextBreak($count = 1, $fontStyle = null, $paragraphStyle = null)
{
for ($i = 1; $i <= $count; $i++) {
$this->elements[] = new TextBreak($fontStyle, $paragraphStyle);
}
}
/**
* Add textrun element
*
@ -124,18 +114,17 @@ abstract class Container
*/
public function addTextRun($paragraphStyle = null)
{
if (!in_array($this->containerType, array('section', 'header', 'footer', 'cell'))) {
throw new \BadMethodCallException();
}
if ($this->containerType == 'cell') {
$docPartType = $this->docPartType;
$this->checkValidity('textrun');
if ($this->container == 'cell') {
$docPart = $this->docPart;
$docPartId = $this->docPartId;
} else {
$docPartType = $this->containerType;
$docPartId = $this->sectionId;
$docPart = $this->container;
$docPartId = $this->containerId;
}
$textRun = new TextRun($paragraphStyle, $docPartType, $docPartId);
$textRun = new TextRun($paragraphStyle, $docPart, $docPartId);
$this->elements[] = $textRun;
return $textRun;
@ -152,24 +141,30 @@ abstract class Container
*/
public function addLink($linkSrc, $linkName = null, $fontStyle = null, $paragraphStyle = null)
{
if (!is_null($this->docPartType)) {
$linkContainer = $this->docPartType;
$linkContainerId = $this->docPartId;
$this->checkValidity('link');
$inSection = true;
if (!is_null($this->docPart)) {
$container = $this->docPart;
$containerId = $this->docPartId;
} else {
$linkContainer = $this->containerType;
$linkContainerId = $this->sectionId;
$container = $this->container;
$containerId = $this->containerId;
}
if ($linkContainer == 'header' || $linkContainer == 'footer') {
$linkContainer .= $linkContainerId;
if ($container == 'header' || $container == 'footer') {
$container .= $containerId;
$inSection = false;
} elseif ($container == 'footnote') {
$inSection = false;
}
$linkSrc = String::toUTF8($linkSrc);
$linkName = String::toUTF8($linkName);
$link = new Link($linkSrc, $linkName, $fontStyle, $paragraphStyle);
if ($linkContainer == 'section') {
if ($inSection) {
$rID = Media::addSectionLinkElement($linkSrc);
} else {
$rID = Media::addMediaElement($linkContainer, 'hyperlink', $linkSrc);
$rID = Media::addMediaElement($container, 'hyperlink', $linkSrc);
}
$link->setRelationId($rID);
$this->elements[] = $link;
@ -183,13 +178,11 @@ abstract class Container
* @param string $text
* @param int $depth
* @return Title
* @todo Enable title element in header, footer, footnote, textrun
* @todo Enable title element in other containers
*/
public function addTitle($text, $depth = 1)
{
if (!in_array($this->containerType, array('section'))) {
throw new \BadMethodCallException();
}
$this->checkValidity('title');
$text = String::toUTF8($text);
$styles = Style::getStyles();
@ -219,12 +212,7 @@ abstract class Container
*/
public function addPreserveText($text, $fontStyle = null, $paragraphStyle = null)
{
if (!in_array($this->containerType, array('header', 'footer', 'cell'))) {
throw new \BadMethodCallException();
}
if ($this->containerType == 'cell' && $this->docPartType == 'section') {
throw new \BadMethodCallException();
}
$this->checkValidity('preservetext');
$text = String::toUTF8($text);
$ptext = new PreserveText($text, $fontStyle, $paragraphStyle);
@ -233,6 +221,22 @@ abstract class Container
return $ptext;
}
/**
* Add text break element
*
* @param int $count
* @param mixed $fontStyle
* @param mixed $paragraphStyle
*/
public function addTextBreak($count = 1, $fontStyle = null, $paragraphStyle = null)
{
$this->checkValidity('textbreak');
for ($i = 1; $i <= $count; $i++) {
$this->elements[] = new TextBreak($fontStyle, $paragraphStyle);
}
}
/**
* Add listitem element
*
@ -242,13 +246,10 @@ abstract class Container
* @param mixed $styleList
* @param mixed $paragraphStyle
* @return ListItem
* @todo Enable list item element in header and footer
*/
public function addListItem($text, $depth = 0, $fontStyle = null, $styleList = null, $paragraphStyle = null)
{
if (!in_array($this->containerType, array('section', 'header', 'footer', 'cell'))) {
throw new \BadMethodCallException();
}
$this->checkValidity('listitem');
$text = String::toUTF8($text);
$listItem = new ListItem($text, $depth, $fontStyle, $styleList, $paragraphStyle);
@ -265,11 +266,9 @@ abstract class Container
*/
public function addTable($style = null)
{
if (!in_array($this->containerType, array('section', 'header', 'footer'))) {
throw new \BadMethodCallException();
}
$this->checkValidity('table');
$table = new Table($this->containerType, $this->sectionId, $style);
$table = new Table($this->container, $this->containerId, $style);
$this->elements[] = $table;
return $table;
@ -285,30 +284,31 @@ abstract class Container
*/
public function addImage($src, $style = null, $isWatermark = false)
{
if ($this->containerType == 'cell') {
$imageContainerType = $this->docPartType;
$imageContainerId = $this->docPartId;
$this->checkValidity('image');
if ($this->container == 'cell' || $this->container == 'textrun') {
$container = $this->docPart;
$containerId = $this->docPartId;
} else {
$imageContainerType = $this->containerType;
$imageContainerId = $this->sectionId;
$container = $this->container;
$containerId = $this->containerId;
}
$image = new Image($src, $style, $isWatermark);
if (!is_null($image->getSource())) {
$rID = null;
switch ($imageContainerType) {
switch ($container) {
case 'textrun':
case 'section':
$rID = Media::addSectionMediaElement($src, 'image', $image);
break;
case 'header':
$rID = Media::addHeaderMediaElement($imageContainerId, $src, $image);
$rID = Media::addHeaderMediaElement($containerId, $src, $image);
break;
case 'footer':
$rID = Media::addFooterMediaElement($imageContainerId, $src, $image);
$rID = Media::addFooterMediaElement($containerId, $src, $image);
break;
case 'footnote':
$rID = Media::addMediaElement('footnotes', 'image', $src, $image);
$rID = Media::addMediaElement('footnote', 'image', $src, $image);
break;
}
$image->setRelationId($rID);
@ -331,11 +331,19 @@ abstract class Container
*/
public function addObject($src, $style = null)
{
if (!in_array($this->containerType, array('section', 'cell'))) {
throw new \BadMethodCallException();
$inSection = true;
if (!is_null($this->docPart)) {
$container = $this->docPart;
$containerId = $this->docPartId;
} else {
$container = $this->container;
$containerId = $this->containerId;
}
if ($this->containerType == 'cell' && $this->docPartType != 'section') {
throw new \BadMethodCallException();
if ($container == 'header' || $container == 'footer') {
$container .= $containerId;
$inSection = false;
} elseif ($container == 'footnote') {
$inSection = false;
}
$object = new Object($src, $style);
@ -345,9 +353,14 @@ abstract class Container
if (strlen($ext) == 4 && strtolower(substr($ext, -1)) == 'x') {
$ext = substr($ext, 0, -1);
}
$icon = __DIR__ . "/../_staticDocParts/_{$ext}.png";
$rIDimg = Media::addSectionMediaElement($icon, 'image', new Image($icon));
$data = Media::addSectionMediaElement($src, 'oleObject');
$icon = realpath(__DIR__ . "/../_staticDocParts/_{$ext}.png");
if ($inSection) {
$rIDimg = Media::addSectionMediaElement($icon, 'image', new Image($icon));
$data = Media::addSectionMediaElement($src, 'oleObject');
} else {
$rIDimg = Media::addMediaElement($container, 'image', $icon, new Image($icon));
$data = Media::addMediaElement($container, 'embeddings', $src);
}
$rID = $data[0];
$objectId = $data[1];
$object->setRelationId($rID);
@ -368,12 +381,7 @@ abstract class Container
*/
public function addFootnote($paragraphStyle = null)
{
if (!in_array($this->containerType, array('section', 'textrun', 'cell'))) {
throw new \BadMethodCallException();
}
if (!is_null($this->docPartType) && $this->docPartType != 'section') {
throw new \BadMethodCallException();
}
$this->checkValidity('footnote');
$footnote = new FootnoteElement($paragraphStyle);
$refID = FootnoteCollection::addFootnoteElement($footnote);
@ -391,16 +399,10 @@ abstract class Container
* @param mixed $fontStyle
* @param mixed $paragraphStyle
* @return CheckBox
* @todo Enable checkbox element in header and footer
*/
public function addCheckBox($name, $text, $fontStyle = null, $paragraphStyle = null)
{
if (!in_array($this->containerType, array('section', 'header', 'footer', 'cell'))) {
throw new \BadMethodCallException();
}
if ($this->containerType == 'cell' && $this->docPartType != 'section') {
throw new \BadMethodCallException();
}
$this->checkValidity('checkbox');
$name = String::toUTF8($name);
$text = String::toUTF8($text);
@ -416,7 +418,7 @@ abstract class Container
*/
public function getSectionId()
{
return $this->sectionId;
return $this->containerId;
}
/**
@ -436,10 +438,7 @@ abstract class Container
*/
public function getRelationId()
{
if (!in_array($this->containerType, array('header', 'footer'))) {
throw new \BadMethodCallException();
}
$this->checkValidity('relationid');
return $this->relationId;
}
@ -450,10 +449,7 @@ abstract class Container
*/
public function setRelationId($rId)
{
if (!in_array($this->containerType, array('header', 'footer'))) {
throw new \BadMethodCallException();
}
$this->checkValidity('relationid');
$this->relationId = $rId;
}
@ -490,4 +486,56 @@ abstract class Container
{
return $this->addFootnote($paragraphStyle);
}
/**
* Check if a method is allowed for the current container
*
* @param string $element
* @return boolean
*/
private function checkValidity($method)
{
$validContainers = array(
'text' => 'all',
'link' => 'all',
'textbreak' => 'all',
'image' => 'all',
'textrun' => array('section', 'header', 'footer', 'cell'),
'listitem' => array('section', 'header', 'footer', 'cell'),
'checkbox' => array('section', 'header', 'footer', 'cell'),
'table' => array('section', 'header', 'footer'),
'object' => array('section', 'textrun', 'cell', 'footnote'),
'footnote' => array('section', 'textrun', 'cell'),
'preservetext' => array('header', 'footer', 'cell'),
'relationid' => array('header', 'footer'),
'title' => array('section'),
);
$validContainerInContainers = array(
'preservetext' => array(array('cell'), array('header', 'footer')),
'object' => array(array('cell', 'textrun'), array('section')),
'footnote' => array(array('cell', 'textrun'), array('section')),
);
// Check if a method is valid for current container
if (array_key_exists($method, $validContainers)) {
if (is_array($validContainers[$method])) {
if (!in_array($this->container, $validContainers[$method])) {
throw new \BadMethodCallException();
}
}
}
// Check if a method is valid for current container, located in other container
if (array_key_exists($method, $validContainerInContainers)) {
$rules = $validContainerInContainers[$method];
$containers = $rules[0];
$allowedDocParts = $rules[1];
foreach ($containers as $container) {
if ($this->container == $container && !in_array($this->docPart, $allowedDocParts)) {
throw new \BadMethodCallException();
}
}
}
return true;
}
}

View File

@ -21,7 +21,7 @@ class Footer extends Container
*/
public function __construct($sectionId)
{
$this->containerType = 'footer';
$this->sectionId = $sectionId;
$this->container = 'footer';
$this->containerId = $sectionId;
}
}

View File

@ -40,8 +40,8 @@ class Header extends Container
*/
public function __construct($sectionId)
{
$this->containerType = 'header';
$this->sectionId = $sectionId;
$this->container = 'header';
$this->containerId = $sectionId;
}
/**

View File

@ -50,8 +50,8 @@ class Section extends Container
*/
public function __construct($sectionCount, $settings = null)
{
$this->containerType = 'section';
$this->sectionId = $sectionCount;
$this->container = 'section';
$this->containerId = $sectionCount;
$this->settings = new Settings();
$this->setSettings($settings);
}
@ -112,7 +112,7 @@ class Section extends Container
*/
public function addHeader()
{
$header = new Header($this->sectionId);
$header = new Header($this->containerId);
$this->headers[] = $header;
return $header;
}
@ -124,7 +124,7 @@ class Section extends Container
*/
public function addFooter()
{
$footer = new Footer($this->sectionId);
$footer = new Footer($this->containerId);
$this->footer = $footer;
return $footer;
}

View File

@ -38,7 +38,7 @@ class Footnote extends Container
*/
public function __construct($paragraphStyle = null)
{
$this->containerType = 'footnote';
$this->container = 'footnote';
// Set paragraph style
if (is_array($paragraphStyle)) {
$this->paragraphStyle = new Paragraph();

View File

@ -34,15 +34,15 @@ class Cell extends Container
/**
* Create new instance
*
* @param string $docPartType section|header|footer
* @param string $docPart section|header|footer
* @param int $docPartId
* @param int $width
* @param array|CellStyle $style
*/
public function __construct($docPartType, $docPartId, $width = null, $style = null)
public function __construct($docPart, $docPartId, $width = null, $style = null)
{
$this->containerType = 'cell';
$this->docPartType = $docPartType;
$this->container = 'cell';
$this->docPart = $docPart;
$this->docPartId = $docPartId;
$this->width = $width;
$this->cellStyle = new CellStyle();

View File

@ -31,10 +31,10 @@ class TextRun extends Container
* @param string $docPartType section|header|footer
* @param int $docPartId
*/
public function __construct($paragraphStyle = null, $docPartType = 'section', $docPartId = 1)
public function __construct($paragraphStyle = null, $docPart = 'section', $docPartId = 1)
{
$this->containerType = 'textrun';
$this->docPartType = $docPartType;
$this->container = 'textrun';
$this->docPart = $docPart;
$this->docPartId = $docPartId;
// Set paragraph style
if (is_array($paragraphStyle)) {

View File

@ -79,7 +79,7 @@ class Media
$isMemImage = false;
if (!is_null($image)) {
$isMemImage = $image->getIsMemImage();
$extension = $image->getImageExtension();
$ext = $image->getImageExtension();
}
if ($isMemImage) {
$media['isMemImage'] = true;
@ -87,10 +87,10 @@ class Media
$media['imagefunction'] = $image->getImageFunction();
}
$folder = 'media';
$file = $type . $cImg . '.' . strtolower($extension);
$file = $type . $cImg . '.' . strtolower($ext);
} elseif ($type === 'oleObject') {
$cObj++;
$folder = 'embedding';
$folder = 'embeddings';
$file = $type . $cObj . '.bin';
}
$media['source'] = $src;
@ -247,8 +247,8 @@ class Media
/**
* Add new media element
*
* @param string $container section|header|footer|footnotes
* @param string $mediaType image|embedding|hyperlink
* @param string $container section|headerx|footerx|footnote
* @param string $mediaType image|embeddings|hyperlink
* @param string $source
* @param Image $image
* @return int
@ -267,35 +267,49 @@ class Media
$mediaTypeCount = self::countMediaElements($container, $mediaType);
$mediaData = array();
$relId = $mediaCount + 1;
$target = null;
$mediaTypeCount++;
// Images
if ($mediaType == 'image') {
$isMemImage = false;
if (!is_null($image)) {
$isMemImage = $image->getIsMemImage();
$extension = $image->getImageExtension();
$ext = $image->getImageExtension();
$ext = strtolower($ext);
}
if ($isMemImage) {
$mediaData['isMemImage'] = true;
$mediaData['createfunction'] = $image->getImageCreateFunction();
$mediaData['imagefunction'] = $image->getImageFunction();
}
$file = 'image' . $mediaTypeCount . '.' . strtolower($extension);
if ($container != 'footnotes') {
$file = $container . '_' . $file;
}
$target = 'media/' . $file;
$target = "media/{$container}_image{$mediaTypeCount}.{$ext}";
// Objects
} elseif ($mediaType == 'embeddings') {
$file = "oleObject{$mediaTypeCount}.bin";
$target = "embeddings/{$container}_oleObject{$mediaTypeCount}.bin";
// Links
} elseif ($mediaType == 'hyperlink') {
$target = $source;
}
$mediaData['source'] = $source;
$mediaData['target'] = $target;
$mediaData['type'] = $mediaType;
$mediaData['rID'] = $relId;
self::$media[$container][$mediaId] = $mediaData;
return $relId;
if ($mediaType === 'embeddings') {
return array($relId, ++self::$objectId);
} else {
return $relId;
}
} else {
return self::$media[$container][$mediaId]['rID'];
if ($mediaType === 'embeddings') {
$relId = self::$media[$container][$mediaId]['rID'];
return array($relId, ++self::$objectId);
} else {
return self::$media[$container][$mediaId]['rID'];
}
}
}

View File

@ -121,7 +121,7 @@ class Word2007 extends Writer implements IWriter
$this->getWriterPart('documentrels')->writeHeaderFooterRels($hdrMedia)
);
foreach ($hdrMedia as $element) {
if ($element['type'] == 'image') {
if ($element['type'] != 'hyperlink') {
$this->addFileToPackage($objZip, $element);
}
}
@ -137,7 +137,7 @@ class Word2007 extends Writer implements IWriter
$this->getWriterPart('documentrels')->writeHeaderFooterRels($ftrMedia)
);
foreach ($ftrMedia as $element) {
if ($element['type'] == 'image') {
if ($element['type'] != 'hyperlink') {
$this->addFileToPackage($objZip, $element);
}
}
@ -155,10 +155,10 @@ class Word2007 extends Writer implements IWriter
foreach ($_headers as $index => &$_header) {
$_cHdrs++;
$_header->setRelationId(++$rID);
$hdrFile = 'header' . $_cHdrs . '.xml';
$hdrFile = "header{$_cHdrs}.xml";
$sectionElements[] = array('target' => $hdrFile, 'type' => 'header', 'rID' => $rID);
$objZip->addFromString(
'word/' . $hdrFile,
"word/{$hdrFile}",
$this->getWriterPart('header')->writeHeader($_header)
);
}
@ -167,10 +167,10 @@ class Word2007 extends Writer implements IWriter
if (!is_null($_footer)) {
$_footer->setRelationId(++$rID);
$_footerCount = $_footer->getSectionId();
$ftrFile = 'footer' . $_footerCount . '.xml';
$ftrFile = "footer{$_footerCount}.xml";
$sectionElements[] = array('target' => $ftrFile, 'type' => 'footer', 'rID' => $rID);
$objZip->addFromString(
'word/' . $ftrFile,
"word/{$ftrFile}",
$this->getWriterPart('footer')->writeFooter($_footer)
);
}
@ -181,24 +181,24 @@ class Word2007 extends Writer implements IWriter
// Push to document.xml.rels
$sectionElements[] = array('target' => 'footnotes.xml', 'type' => 'footnotes', 'rID' => ++$rID);
// Add footnote media to package
$footnotesMedia = Media::getMediaElements('footnotes');
if (!empty($footnotesMedia)) {
foreach ($footnotesMedia as $media) {
if ($media['type'] == 'image') {
$footnoteMedia = Media::getMediaElements('footnote');
if (!empty($footnoteMedia)) {
foreach ($footnoteMedia as $media) {
if ($media['type'] != 'hyperlink') {
$this->addFileToPackage($objZip, $media);
}
}
}
// Write footnotes.xml
$objZip->addFromString(
"word/footnotes.xml",
'word/footnotes.xml',
$this->getWriterPart('footnotes')->writeFootnotes(Footnote::getFootnoteElements())
);
// Write footnotes.xml.rels
if (!empty($footnotesMedia)) {
if (!empty($footnoteMedia)) {
$objZip->addFromString(
'word/_rels/footnotes.xml.rels',
$this->getWriterPart('footnotesrels')->writeFootnotesRels($footnotesMedia)
$this->getWriterPart('footnotesrels')->writeFootnotesRels($footnoteMedia)
);
}
}

View File

@ -44,11 +44,8 @@ class Base extends WriterPart
* @param Text $text
* @param boolean $withoutP
*/
protected function writeText(
XMLWriter $xmlWriter,
Text $text,
$withoutP = false
) {
protected function writeText(XMLWriter $xmlWriter, Text $text, $withoutP = false)
{
$styleFont = $text->getFontStyle();
$styleParagraph = $text->getParagraphStyle();
$strText = htmlspecialchars($text->getText());
@ -76,10 +73,8 @@ class Base extends WriterPart
* @param XMLWriter $xmlWriter
* @param TextRun $textrun
*/
protected function writeTextRun(
XMLWriter $xmlWriter,
TextRun $textrun
) {
protected function writeTextRun(XMLWriter $xmlWriter, TextRun $textrun)
{
$elements = $textrun->getElements();
$styleParagraph = $textrun->getParagraphStyle();
$xmlWriter->startElement('w:p');
@ -94,6 +89,8 @@ class Base extends WriterPart
$xmlWriter->writeElement('w:br');
} elseif ($element instanceof Image) {
$this->writeImage($xmlWriter, $element, true);
} elseif ($element instanceof Object) {
$this->writeObject($xmlWriter, $element, true);
} elseif ($element instanceof Footnote) {
$this->writeFootnote($xmlWriter, $element, true);
}
@ -109,11 +106,8 @@ class Base extends WriterPart
* @param Link $link
* @param boolean $withoutP
*/
protected function writeLink(
XMLWriter $xmlWriter,
Link $link,
$withoutP = false
) {
protected function writeLink(XMLWriter $xmlWriter, Link $link, $withoutP = false)
{
$rID = $link->getRelationId();
$linkName = $link->getLinkName();
if (is_null($linkName)) {
@ -196,10 +190,8 @@ class Base extends WriterPart
* @param XMLWriter $xmlWriter
* @param PreserveText $textrun
*/
protected function writePreserveText(
XMLWriter $xmlWriter,
PreserveText $textrun
) {
protected function writePreserveText(XMLWriter $xmlWriter, PreserveText $textrun)
{
$styleFont = $textrun->getFontStyle();
$styleParagraph = $textrun->getParagraphStyle();
@ -467,11 +459,8 @@ class Base extends WriterPart
* @param Image $image
* @param boolean $withoutP
*/
protected function writeImage(
XMLWriter $xmlWriter,
Image $image,
$withoutP = false
) {
protected function writeImage(XMLWriter $xmlWriter, Image $image, $withoutP = false)
{
$rId = $image->getRelationId();
$style = $image->getStyle();
@ -601,8 +590,9 @@ class Base extends WriterPart
*
* @param XMLWriter $xmlWriter
* @param Object $object
* @param boolean $withoutP
*/
protected function writeObject(XMLWriter $xmlWriter, Object $object)
protected function writeObject(XMLWriter $xmlWriter, Object $object, $withoutP = false)
{
$rIdObject = $object->getRelationId();
$rIdImage = $object->getImageRelationId();
@ -611,7 +601,9 @@ class Base extends WriterPart
$style = $object->getStyle();
$align = $style->getAlign();
$xmlWriter->startElement('w:p');
if (!$withoutP) {
$xmlWriter->startElement('w:p');
}
if (!is_null($align)) {
$xmlWriter->startElement('w:pPr');
$xmlWriter->startElement('w:jc');
@ -643,7 +635,9 @@ class Base extends WriterPart
$xmlWriter->endElement(); // o:OLEObject
$xmlWriter->endElement(); // w:object
$xmlWriter->endElement(); // w:r
$xmlWriter->endElement(); // w:p
if (!$withoutP) {
$xmlWriter->endElement(); // w:p
}
}
/**
@ -653,11 +647,8 @@ class Base extends WriterPart
* @param Footnote $footnote
* @param boolean $withoutP
*/
protected function writeFootnote(
XMLWriter $xmlWriter,
Footnote $footnote,
$withoutP = false
) {
protected function writeFootnote(XMLWriter $xmlWriter, Footnote $footnote, $withoutP = false)
{
if (!$withoutP) {
$xmlWriter->startElement('w:p');
}
@ -682,12 +673,8 @@ class Base extends WriterPart
* @param boolean $withoutP
* @param boolean $checkState
*/
protected function writeCheckBox(
XMLWriter $xmlWriter,
CheckBox $checkbox,
$withoutP = false,
$checkState = false
) {
protected function writeCheckBox(XMLWriter $xmlWriter, CheckBox $checkbox, $withoutP = false, $checkState = false)
{
$name = htmlspecialchars($checkbox->getName());
$name = String::controlCharacterPHP2OOXML($name);
$text = htmlspecialchars($checkbox->getText());
@ -758,11 +745,8 @@ class Base extends WriterPart
* @param Paragraph $style
* @param bool $withoutPPR
*/
protected function writeParagraphStyle(
XMLWriter $xmlWriter,
Paragraph $style,
$withoutPPR = false
) {
protected function writeParagraphStyle(XMLWriter $xmlWriter, Paragraph $style, $withoutPPR = false)
{
$align = $style->getAlign();
$spacing = $style->getSpacing();
@ -965,11 +949,8 @@ class Base extends WriterPart
* @param TableStyle $style
* @param boolean $isFullStyle
*/
protected function writeTableStyle(
XMLWriter $xmlWriter,
TableStyle $style,
$isFullStyle = true
) {
protected function writeTableStyle(XMLWriter $xmlWriter, TableStyle $style, $isFullStyle = true)
{
$bgColor = $style->getBgColor();
$brdCol = $style->getBorderColor();
@ -1094,11 +1075,8 @@ class Base extends WriterPart
* @param string $type
* @param TableStyle $style
*/
protected function writeRowStyle(
XMLWriter $xmlWriter,
$type,
TableStyle $style
) {
protected function writeRowStyle(XMLWriter $xmlWriter, $type, TableStyle $style)
{
$brdSz = $style->getBorderSize();
$brdCol = $style->getBorderColor();
$bgColor = $style->getBgColor();
@ -1265,6 +1243,26 @@ class Base extends WriterPart
}
}
/**
* Write media rels (image, embeddings, hyperlink)
*
* @param XMLWriter $xmlWriter
* @param array mediaRels
*/
protected function writeMediaRels(XMLWriter $xmlWriter, $mediaRels)
{
$rTypePrefix = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/';
foreach ($mediaRels as $mediaRel) {
$rId = $mediaRel['rID'];
$rType = $mediaRel['type'];
$rName = $mediaRel['target']; // file name
$targetMode = ($rType == 'hyperlink') ? 'External' : '';
$rType = $rTypePrefix . ($rType == 'embeddings' ? 'oleObject' : $rType);
$this->writeRel($xmlWriter, $rId, $rType, $rName, $targetMode);
}
}
/**
* Write individual rels entry
*
@ -1274,28 +1272,19 @@ class Base extends WriterPart
* @param string $pTarget Relationship target
* @param string $pTargetMode Relationship target mode
*/
protected function writeRelationship(
XMLWriter $xmlWriter,
$pId = 1,
$pType = '',
$pTarget = '',
$pTargetMode = ''
) {
protected function writeRel(XMLWriter $xmlWriter, $pId, $pType, $pTarget, $pTargetMode = '')
{
if ($pType != '' && $pTarget != '') {
if (strpos($pId, 'rId') === false) {
$pId = 'rId' . $pId;
}
// Write relationship
$xmlWriter->startElement('Relationship');
$xmlWriter->writeAttribute('Id', $pId);
$xmlWriter->writeAttribute('Type', $pType);
$xmlWriter->writeAttribute('Target', $pTarget);
if ($pTargetMode != '') {
$xmlWriter->writeAttribute('TargetMode', $pTargetMode);
}
$xmlWriter->endElement();
} else {
throw new Exception("Invalid parameters passed.");
@ -1309,11 +1298,8 @@ class Base extends WriterPart
* @param Paragraph|string $styleParagraph
* @param boolean $withoutPPR
*/
protected function writeInlineParagraphStyle(
XMLWriter $xmlWriter,
$styleParagraph = null,
$withoutPPR = false
) {
protected function writeInlineParagraphStyle(XMLWriter $xmlWriter, $styleParagraph = null, $withoutPPR = false)
{
if ($styleParagraph instanceof Paragraph) {
$this->writeParagraphStyle($xmlWriter, $styleParagraph, $withoutPPR);
} else {
@ -1337,10 +1323,8 @@ class Base extends WriterPart
* @param XMLWriter $xmlWriter
* @param Font|string $styleFont
*/
protected function writeInlineFontStyle(
XMLWriter $xmlWriter,
$styleFont = null
) {
protected function writeInlineFontStyle(XMLWriter $xmlWriter, $styleFont = null)
{
if ($styleFont instanceof Font) {
$this->writeFontStyle($xmlWriter, $styleFont);
} else {

View File

@ -151,7 +151,6 @@ class ContentTypes extends WriterPart
}
}
$xmlWriter->endElement();
// Return

View File

@ -35,7 +35,7 @@ class DocumentRels extends Base
$xmlWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
// Relationship word/document.xml
$this->writeRelationship(
$this->writeRel(
$xmlWriter,
1,
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles',
@ -43,7 +43,7 @@ class DocumentRels extends Base
);
// Relationship word/numbering.xml
$this->writeRelationship(
$this->writeRel(
$xmlWriter,
2,
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering',
@ -51,7 +51,7 @@ class DocumentRels extends Base
);
// Relationship word/settings.xml
$this->writeRelationship(
$this->writeRel(
$xmlWriter,
3,
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings',
@ -59,7 +59,7 @@ class DocumentRels extends Base
);
// Relationship word/settings.xml
$this->writeRelationship(
$this->writeRel(
$xmlWriter,
4,
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme',
@ -67,7 +67,7 @@ class DocumentRels extends Base
);
// Relationship word/settings.xml
$this->writeRelationship(
$this->writeRel(
$xmlWriter,
5,
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings',
@ -75,73 +75,34 @@ class DocumentRels extends Base
);
// Relationship word/settings.xml
$this->writeRelationship(
$this->writeRel(
$xmlWriter,
6,
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable',
'fontTable.xml'
);
// Relationships to Images / Embeddings / Headers / Footers
foreach ($_relsCollection as $relation) {
$relationType = $relation['type'];
$relationName = $relation['target'];
$relationId = $relation['rID'];
$targetMode = ($relationType == 'hyperlink') ? 'External' : '';
$this->writeRelationship(
$xmlWriter,
$relationId,
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/' . $relationType,
$relationName,
$targetMode
);
}
$xmlWriter->endElement();
$this->writeMediaRels($xmlWriter, $_relsCollection);
$xmlWriter->endElement(); // Relationships
// Return
return $xmlWriter->getData();
}
/**
* Write header footer rels
* Write header footer rels word/_rels/*.xml.rels
*
* @param array $_relsCollection
*/
public function writeHeaderFooterRels($_relsCollection)
{
// Create XML writer
$xmlWriter = $this->getXmlWriter();
// XML header
$xmlWriter->startDocument('1.0', 'UTF-8', 'yes');
// Relationships
$xmlWriter->startElement('Relationships');
$xmlWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
// Relationships to Images / Embeddings / Headers / Footers
foreach ($_relsCollection as $relation) {
$relationType = $relation['type'];
$relationName = $relation['target'];
$relationId = $relation['rID'];
$targetMode = ($relationType == 'hyperlink') ? 'External' : '';
$this->writeRelationship(
$xmlWriter,
$relationId,
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/' . $relationType,
$relationName,
$targetMode
);
}
$this->writeMediaRels($xmlWriter, $_relsCollection);
$xmlWriter->endElement();
// Return
return $xmlWriter->getData();
}
}

View File

@ -13,6 +13,7 @@ use PhpOffice\PhpWord\Element\Footnote;
use PhpOffice\PhpWord\Element\Text;
use PhpOffice\PhpWord\Element\Link;
use PhpOffice\PhpWord\Element\Image;
use PhpOffice\PhpWord\Element\Object;
use PhpOffice\PhpWord\Element\TextBreak;
use PhpOffice\PhpWord\Style\Paragraph;
use PhpOffice\PhpWord\Shared\XMLWriter;
@ -119,6 +120,8 @@ class Footnotes extends Base
$this->writeLink($xmlWriter, $element, true);
} elseif ($element instanceof Image) {
$this->writeImage($xmlWriter, $element, true);
} elseif ($element instanceof Object) {
$this->writeObject($xmlWriter, $element, true);
} elseif ($element instanceof TextBreak) {
$xmlWriter->writeElement('w:br');
}

View File

@ -24,29 +24,13 @@ class FootnotesRels extends Base
*/
public function writeFootnotesRels($_relsCollection)
{
// Create XML writer
$xmlWriter = $this->getXmlWriter();
// XML header
$xmlWriter->startDocument('1.0', 'UTF-8', 'yes');
// Relationships
$xmlWriter->startElement('Relationships');
$xmlWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
// Relationships to Links
foreach ($_relsCollection as $relation) {
$relationType = $relation['type'];
$relationName = $relation['target'];
$relationId = $relation['rID'];
$targetMode = ($relationType == 'hyperlink') ? 'External' : '';
$this->writeRelationship($xmlWriter, $relationId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/' . $relationType, $relationName, $targetMode);
}
$this->writeMediaRels($xmlWriter, $_relsCollection);
$xmlWriter->endElement();
// Return
return $xmlWriter->getData();
}
}

View File

@ -38,7 +38,7 @@ class Rels extends Base
$relationId = 1;
// Relationship word/document.xml
$this->writeRelationship(
$this->writeRel(
$xmlWriter,
$relationId,
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument',
@ -46,7 +46,7 @@ class Rels extends Base
);
// Relationship docProps/core.xml
$this->writeRelationship(
$this->writeRel(
$xmlWriter,
++$relationId,
'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties',
@ -54,7 +54,7 @@ class Rels extends Base
);
// Relationship docProps/app.xml
$this->writeRelationship(
$this->writeRel(
$xmlWriter,
++$relationId,
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties',