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; return $element; } /** * Add textrun element * * @param mixed $paragraphStyle * @return TextRun */ public function addTextRun($paragraphStyle = null) { $this->checkValidity('textrun'); if ($this->container == 'cell') { $docPart = $this->docPart; $docPartId = $this->docPartId; } else { $docPart = $this->container; $docPartId = $this->containerId; } $textRun = new TextRun($paragraphStyle, $docPart, $docPartId); $this->elements[] = $textRun; return $textRun; } /** * Add link element * * @param string $linkSrc * @param string $linkName * @param mixed $fontStyle * @param mixed $paragraphStyle * @return Link */ public function addLink($linkSrc, $linkName = null, $fontStyle = null, $paragraphStyle = null) { $this->checkValidity('link'); $inSection = true; if (!is_null($this->docPart)) { $container = $this->docPart; $containerId = $this->docPartId; } else { $container = $this->container; $containerId = $this->containerId; } 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 ($inSection) { $rID = Media::addSectionLinkElement($linkSrc); } else { $rID = Media::addMediaElement($container, 'hyperlink', $linkSrc); } $link->setRelationId($rID); $this->elements[] = $link; return $link; } /** * Add a Title Element * * @param string $text * @param int $depth * @return Title * @todo Enable title element in other containers */ public function addTitle($text, $depth = 1) { $this->checkValidity('title'); $text = String::toUTF8($text); $styles = Style::getStyles(); if (array_key_exists('Heading_' . $depth, $styles)) { $style = 'Heading' . $depth; } else { $style = null; } $title = new Title($text, $depth, $style); $data = TOC::addTitle($text, $depth); $anchor = $data[0]; $bookmarkId = $data[1]; $title->setAnchor($anchor); $title->setBookmarkId($bookmarkId); $this->elements[] = $title; return $title; } /** * Add preserve text element * * @param string $text * @param mixed $fontStyle * @param mixed $paragraphStyle * @return PreserveText */ public function addPreserveText($text, $fontStyle = null, $paragraphStyle = null) { $this->checkValidity('preservetext'); $text = String::toUTF8($text); $ptext = new PreserveText($text, $fontStyle, $paragraphStyle); $this->elements[] = $ptext; 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 * * @param string $text * @param int $depth * @param mixed $fontStyle * @param mixed $styleList * @param mixed $paragraphStyle * @return ListItem */ public function addListItem($text, $depth = 0, $fontStyle = null, $styleList = null, $paragraphStyle = null) { $this->checkValidity('listitem'); $text = String::toUTF8($text); $listItem = new ListItem($text, $depth, $fontStyle, $styleList, $paragraphStyle); $this->elements[] = $listItem; return $listItem; } /** * Add table element * * @param mixed $style * @return Table */ public function addTable($style = null) { $this->checkValidity('table'); $table = new Table($this->container, $this->containerId, $style); $this->elements[] = $table; return $table; } /** * Add image element * * @param string $src * @param mixed $style Image style * @param boolean $isWatermark * @return Image */ public function addImage($src, $style = null, $isWatermark = false) { $this->checkValidity('image'); if ($this->container == 'cell' || $this->container == 'textrun') { $container = $this->docPart; $containerId = $this->docPartId; } else { $container = $this->container; $containerId = $this->containerId; } $image = new Image($src, $style, $isWatermark); if (!is_null($image->getSource())) { $rID = null; switch ($container) { case 'textrun': case 'section': $rID = Media::addSectionMediaElement($src, 'image', $image); break; case 'header': $rID = Media::addHeaderMediaElement($containerId, $src, $image); break; case 'footer': $rID = Media::addFooterMediaElement($containerId, $src, $image); break; case 'footnote': $rID = Media::addMediaElement('footnote', 'image', $src, $image); break; } if (is_int($rID)) { $image->setRelationId($rID); } $this->elements[] = $image; return $image; } else { throw new InvalidImageException; } } /** * Add OLE-object element * * All exceptions should be handled by PhpOffice\PhpWord\Element\Object * * @param string $src * @param mixed $style * @return Object * @todo Enable OLE object element in header and footer */ public function addObject($src, $style = null) { $inSection = true; if (!is_null($this->docPart)) { $container = $this->docPart; $containerId = $this->docPartId; } else { $container = $this->container; $containerId = $this->containerId; } if ($container == 'header' || $container == 'footer') { $container .= $containerId; $inSection = false; } elseif ($container == 'footnote') { $inSection = false; } $object = new Object($src, $style); if (!is_null($object->getSource())) { $inf = pathinfo($src); $ext = $inf['extension']; if (strlen($ext) == 4 && strtolower(substr($ext, -1)) == 'x') { $ext = substr($ext, 0, -1); } $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); $object->setObjectId($objectId); if (is_int($rIDimg)) { $object->setImageRelationId($rIDimg); } $this->elements[] = $object; return $object; } else { throw new InvalidObjectException(); } } /** * Add footnote element * * @param mixed $paragraphStyle * @return FootnoteElement */ public function addFootnote($paragraphStyle = null) { $this->checkValidity('footnote'); $footnote = new FootnoteElement($paragraphStyle); $refID = FootnoteCollection::addFootnoteElement($footnote); $footnote->setRelationId($refID); $this->elements[] = $footnote; return $footnote; } /** * Add a CheckBox Element * * @param string $name * @param string $text * @param mixed $fontStyle * @param mixed $paragraphStyle * @return CheckBox */ public function addCheckBox($name, $text, $fontStyle = null, $paragraphStyle = null) { $this->checkValidity('checkbox'); $name = String::toUTF8($name); $text = String::toUTF8($text); $element = new CheckBox($name, $text, $fontStyle, $paragraphStyle); $this->elements[] = $element; return $element; } /** * Get section number * getFooterCount */ public function getSectionId() { return $this->containerId; } /** * Get all elements * * @return array */ public function getElements() { return $this->elements; } /** * Get relation Id * * @return int */ public function getRelationId() { $this->checkValidity('relationid'); return $this->relationId; } /** * Set relation Id * * @param int $rId */ public function setRelationId($rId) { $this->checkValidity('relationid'); $this->relationId = $rId; } /** * Add memory image element * * @param string $src * @param mixed $style * @deprecated 0.9.0 * @codeCoverageIgnore */ public function addMemoryImage($src, $style = null) { return $this->addImage($src, $style); } /** * Create textrun element * * @param mixed $paragraphStyle * @deprecated 0.9.2 * @codeCoverageIgnore */ public function createTextRun($paragraphStyle = null) { return $this->addTextRun($paragraphStyle); } /** * Create footnote element * * @param mixed $paragraphStyle * @deprecated 0.9.2 * @codeCoverageIgnore */ public function createFootnote($paragraphStyle = null) { return $this->addFootnote($paragraphStyle); } /** * Check if a method is allowed for the current container * * @param string $method * @return boolean */ private function checkValidity($method) { // Empty array means the element can be accepted by all containers $validContainers = array( 'text' => array(), 'link' => array(), 'textbreak' => array(), 'image' => array(), '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', 'footnote'), 'title' => array('section'), ); // Special condition, e.g. preservetext can only exists in cell when // the cell is located in header or footer $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 (!empty($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; } }