123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- <?php
- /**
- * This file is part of PHPWord - A pure PHP library for reading and writing
- * word processing documents.
- *
- * PHPWord is free software distributed under the terms of the GNU Lesser
- * General Public License version 3 as published by the Free Software Foundation.
- *
- * For the full copyright and license information, please read the LICENSE
- * file that was distributed with this source code. For the full list of
- * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
- *
- * @see https://github.com/PHPOffice/PHPWord
- *
- * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
- */
- namespace PhpOffice\PhpWord\Element;
- use DateTime;
- use InvalidArgumentException;
- use PhpOffice\PhpWord\Media;
- use PhpOffice\PhpWord\PhpWord;
- /**
- * Element abstract class.
- *
- * @since 0.10.0
- */
- abstract class AbstractElement
- {
- /**
- * PhpWord object.
- *
- * @var \PhpOffice\PhpWord\PhpWord
- */
- protected $phpWord;
- /**
- * Section Id.
- *
- * @var int
- */
- protected $sectionId;
- /**
- * Document part type: Section|Header|Footer|Footnote|Endnote.
- *
- * Used by textrun and cell container to determine where the element is
- * located because it will affect the availability of other element,
- * e.g. footnote will not be available when $docPart is header or footer.
- *
- * @var string
- */
- protected $docPart = 'Section';
- /**
- * Document part Id.
- *
- * For header and footer, this will be = ($sectionId - 1) * 3 + $index
- * because the max number of header/footer in every page is 3, i.e.
- * AUTO, FIRST, and EVEN (AUTO = ODD)
- *
- * @var int
- */
- protected $docPartId = 1;
- /**
- * Index of element in the elements collection (start with 1).
- *
- * @var int
- */
- protected $elementIndex = 1;
- /**
- * Unique Id for element.
- *
- * @var string
- */
- protected $elementId;
- /**
- * Relation Id.
- *
- * @var int
- */
- protected $relationId;
- /**
- * Depth of table container nested level; Primarily used for RTF writer/reader.
- *
- * 0 = Not in a table; 1 = in a table; 2 = in a table inside another table, etc.
- *
- * @var int
- */
- private $nestedLevel = 0;
- /**
- * A reference to the parent.
- *
- * @var null|AbstractElement
- */
- private $parent;
- /**
- * changed element info.
- *
- * @var TrackChange
- */
- private $trackChange;
- /**
- * Parent container type.
- *
- * @var string
- */
- private $parentContainer;
- /**
- * Has media relation flag; true for Link, Image, and Object.
- *
- * @var bool
- */
- protected $mediaRelation = false;
- /**
- * Is part of collection; true for Title, Footnote, Endnote, Chart, and Comment.
- *
- * @var bool
- */
- protected $collectionRelation = false;
- /**
- * The start position for the linked comment.
- *
- * @var Comment
- */
- protected $commentRangeStart;
- /**
- * The end position for the linked comment.
- *
- * @var Comment
- */
- protected $commentRangeEnd;
- /**
- * Get PhpWord.
- *
- * @return \PhpOffice\PhpWord\PhpWord
- */
- public function getPhpWord()
- {
- return $this->phpWord;
- }
- /**
- * Set PhpWord as reference.
- *
- * @param \PhpOffice\PhpWord\PhpWord $phpWord
- */
- public function setPhpWord(?PhpWord $phpWord = null): void
- {
- $this->phpWord = $phpWord;
- }
- /**
- * Get section number.
- *
- * @return int
- */
- public function getSectionId()
- {
- return $this->sectionId;
- }
- /**
- * Set doc part.
- *
- * @param string $docPart
- * @param int $docPartId
- */
- public function setDocPart($docPart, $docPartId = 1): void
- {
- $this->docPart = $docPart;
- $this->docPartId = $docPartId;
- }
- /**
- * Get doc part.
- *
- * @return string
- */
- public function getDocPart()
- {
- return $this->docPart;
- }
- /**
- * Get doc part Id.
- *
- * @return int
- */
- public function getDocPartId()
- {
- return $this->docPartId;
- }
- /**
- * Return media element (image, object, link) container name.
- *
- * @return string section|headerx|footerx|footnote|endnote
- */
- private function getMediaPart()
- {
- $mediaPart = $this->docPart;
- if ($mediaPart == 'Header' || $mediaPart == 'Footer') {
- $mediaPart .= $this->docPartId;
- }
- return strtolower($mediaPart);
- }
- /**
- * Get element index.
- *
- * @return int
- */
- public function getElementIndex()
- {
- return $this->elementIndex;
- }
- /**
- * Set element index.
- *
- * @param int $value
- */
- public function setElementIndex($value): void
- {
- $this->elementIndex = $value;
- }
- /**
- * Get element unique ID.
- *
- * @return string
- */
- public function getElementId()
- {
- return $this->elementId;
- }
- /**
- * Set element unique ID from 6 first digit of md5.
- */
- public function setElementId(): void
- {
- $this->elementId = substr(md5(mt_rand()), 0, 6);
- }
- /**
- * Get relation Id.
- *
- * @return int
- */
- public function getRelationId()
- {
- return $this->relationId;
- }
- /**
- * Set relation Id.
- *
- * @param int $value
- */
- public function setRelationId($value): void
- {
- $this->relationId = $value;
- }
- /**
- * Get nested level.
- *
- * @return int
- */
- public function getNestedLevel()
- {
- return $this->nestedLevel;
- }
- /**
- * Get comment start.
- *
- * @return Comment
- */
- public function getCommentRangeStart()
- {
- return $this->commentRangeStart;
- }
- /**
- * Set comment start.
- */
- public function setCommentRangeStart(Comment $value): void
- {
- if ($this instanceof Comment) {
- throw new InvalidArgumentException('Cannot set a Comment on a Comment');
- }
- $this->commentRangeStart = $value;
- $this->commentRangeStart->setStartElement($this);
- }
- /**
- * Get comment end.
- *
- * @return Comment
- */
- public function getCommentRangeEnd()
- {
- return $this->commentRangeEnd;
- }
- /**
- * Set comment end.
- */
- public function setCommentRangeEnd(Comment $value): void
- {
- if ($this instanceof Comment) {
- throw new InvalidArgumentException('Cannot set a Comment on a Comment');
- }
- $this->commentRangeEnd = $value;
- $this->commentRangeEnd->setEndElement($this);
- }
- /**
- * Get parent element.
- *
- * @return null|AbstractElement
- */
- public function getParent()
- {
- return $this->parent;
- }
- /**
- * Set parent container.
- *
- * Passed parameter should be a container, except for Table (contain Row) and Row (contain Cell)
- *
- * @param \PhpOffice\PhpWord\Element\AbstractElement $container
- */
- public function setParentContainer(self $container): void
- {
- $this->parentContainer = substr(get_class($container), strrpos(get_class($container), '\\') + 1);
- $this->parent = $container;
- // Set nested level
- $this->nestedLevel = $container->getNestedLevel();
- if ($this->parentContainer == 'Cell') {
- ++$this->nestedLevel;
- }
- // Set phpword
- $this->setPhpWord($container->getPhpWord());
- // Set doc part
- if (!$this instanceof Footnote) {
- $this->setDocPart($container->getDocPart(), $container->getDocPartId());
- }
- $this->setMediaRelation();
- $this->setCollectionRelation();
- }
- /**
- * Set relation Id for media elements (link, image, object; legacy of OOXML).
- *
- * - Image element needs to be passed to Media object
- * - Icon needs to be set for Object element
- */
- private function setMediaRelation(): void
- {
- if (!$this instanceof Link && !$this instanceof Image && !$this instanceof OLEObject) {
- return;
- }
- $elementName = substr(static::class, strrpos(static::class, '\\') + 1);
- if ($elementName == 'OLEObject') {
- $elementName = 'Object';
- }
- $mediaPart = $this->getMediaPart();
- $source = $this->getSource();
- $image = null;
- if ($this instanceof Image) {
- $image = $this;
- }
- $rId = Media::addElement($mediaPart, strtolower($elementName), $source, $image);
- $this->setRelationId($rId);
- if ($this instanceof OLEObject) {
- $icon = $this->getIcon();
- $rId = Media::addElement($mediaPart, 'image', $icon, new Image($icon));
- $this->setImageRelationId($rId);
- }
- }
- /**
- * Set relation Id for elements that will be registered in the Collection subnamespaces.
- */
- private function setCollectionRelation(): void
- {
- if ($this->collectionRelation === true && $this->phpWord instanceof PhpWord) {
- $elementName = substr(static::class, strrpos(static::class, '\\') + 1);
- $addMethod = "add{$elementName}";
- $rId = $this->phpWord->$addMethod($this);
- $this->setRelationId($rId);
- }
- }
- /**
- * Check if element is located in Section doc part (as opposed to Header/Footer).
- *
- * @return bool
- */
- public function isInSection()
- {
- return $this->docPart == 'Section';
- }
- /**
- * Set new style value.
- *
- * @param mixed $styleObject Style object
- * @param mixed $styleValue Style value
- * @param bool $returnObject Always return object
- *
- * @return mixed
- */
- protected function setNewStyle($styleObject, $styleValue = null, $returnObject = false)
- {
- if (null !== $styleValue && is_array($styleValue)) {
- $styleObject->setStyleByArray($styleValue);
- $style = $styleObject;
- } else {
- $style = $returnObject ? $styleObject : $styleValue;
- }
- return $style;
- }
- /**
- * Sets the trackChange information.
- */
- public function setTrackChange(TrackChange $trackChange): void
- {
- $this->trackChange = $trackChange;
- }
- /**
- * Gets the trackChange information.
- *
- * @return TrackChange
- */
- public function getTrackChange()
- {
- return $this->trackChange;
- }
- /**
- * Set changed.
- *
- * @param string $type INSERTED|DELETED
- * @param string $author
- * @param null|DateTime|int $date allways in UTC
- */
- public function setChangeInfo($type, $author, $date = null): void
- {
- $this->trackChange = new TrackChange($type, $author, $date);
- }
- /**
- * Set enum value.
- *
- * @param null|string $value
- * @param string[] $enum
- * @param null|string $default
- *
- * @return null|string
- *
- * @todo Merge with the same method in AbstractStyle
- */
- protected function setEnumVal($value = null, $enum = [], $default = null)
- {
- if ($value !== null && trim($value) != '' && !empty($enum) && !in_array($value, $enum)) {
- throw new InvalidArgumentException("Invalid style value: {$value}");
- } elseif ($value === null || trim($value) == '') {
- $value = $default;
- }
- return $value;
- }
- }
|