暂无描述

AbstractElement.php 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. <?php
  2. /**
  3. * This file is part of PHPWord - A pure PHP library for reading and writing
  4. * word processing documents.
  5. *
  6. * PHPWord is free software distributed under the terms of the GNU Lesser
  7. * General Public License version 3 as published by the Free Software Foundation.
  8. *
  9. * For the full copyright and license information, please read the LICENSE
  10. * file that was distributed with this source code. For the full list of
  11. * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
  12. *
  13. * @link https://github.com/PHPOffice/PHPWord
  14. * @copyright 2010-2014 PHPWord contributors
  15. * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
  16. */
  17. namespace PhpOffice\PhpWord\Element;
  18. use PhpOffice\PhpWord\Media;
  19. use PhpOffice\PhpWord\PhpWord;
  20. use PhpOffice\PhpWord\Style;
  21. /**
  22. * Element abstract class
  23. *
  24. * @since 0.10.0
  25. */
  26. abstract class AbstractElement
  27. {
  28. /**
  29. * PhpWord object
  30. *
  31. * @var \PhpOffice\PhpWord\PhpWord
  32. */
  33. protected $phpWord;
  34. /**
  35. * Section Id
  36. *
  37. * @var int
  38. */
  39. protected $sectionId;
  40. /**
  41. * Document part type: Section|Header|Footer|Footnote|Endnote
  42. *
  43. * Used by textrun and cell container to determine where the element is
  44. * located because it will affect the availability of other element,
  45. * e.g. footnote will not be available when $docPart is header or footer.
  46. *
  47. * @var string
  48. */
  49. protected $docPart = 'Section';
  50. /**
  51. * Document part Id
  52. *
  53. * For header and footer, this will be = ($sectionId - 1) * 3 + $index
  54. * because the max number of header/footer in every page is 3, i.e.
  55. * AUTO, FIRST, and EVEN (AUTO = ODD)
  56. *
  57. * @var int
  58. */
  59. protected $docPartId = 1;
  60. /**
  61. * Index of element in the elements collection (start with 1)
  62. *
  63. * @var int
  64. */
  65. protected $elementIndex = 1;
  66. /**
  67. * Unique Id for element
  68. *
  69. * @var int
  70. */
  71. protected $elementId;
  72. /**
  73. * Relation Id
  74. *
  75. * @var int
  76. */
  77. protected $relationId;
  78. /**
  79. * Depth of table container nested level; Primarily used for RTF writer/reader
  80. *
  81. * 0 = Not in a table; 1 = in a table; 2 = in a table inside another table, etc.
  82. *
  83. * @var int
  84. */
  85. private $nestedLevel = 0;
  86. /**
  87. * Parent container type
  88. *
  89. * @var string
  90. */
  91. private $parentContainer;
  92. /**
  93. * Has media relation flag; true for Link, Image, and Object
  94. *
  95. * @var bool
  96. */
  97. protected $mediaRelation = false;
  98. /**
  99. * Is part of collection; true for Title, Footnote, Endnote, and Chart
  100. *
  101. * @var bool
  102. */
  103. protected $collectionRelation = false;
  104. /**
  105. * Get PhpWord
  106. *
  107. * @return \PhpOffice\PhpWord\PhpWord
  108. */
  109. public function getPhpWord()
  110. {
  111. return $this->phpWord;
  112. }
  113. /**
  114. * Set PhpWord as reference.
  115. *
  116. * @param \PhpOffice\PhpWord\PhpWord $phpWord
  117. * @return void
  118. */
  119. public function setPhpWord(PhpWord $phpWord = null)
  120. {
  121. $this->phpWord = $phpWord;
  122. }
  123. /**
  124. * Get section number
  125. *
  126. * @return int
  127. */
  128. public function getSectionId()
  129. {
  130. return $this->sectionId;
  131. }
  132. /**
  133. * Set doc part.
  134. *
  135. * @param string $docPart
  136. * @param int $docPartId
  137. * @return void
  138. */
  139. public function setDocPart($docPart, $docPartId = 1)
  140. {
  141. $this->docPart = $docPart;
  142. $this->docPartId = $docPartId;
  143. }
  144. /**
  145. * Get doc part
  146. *
  147. * @return string
  148. */
  149. public function getDocPart()
  150. {
  151. return $this->docPart;
  152. }
  153. /**
  154. * Get doc part Id
  155. *
  156. * @return int
  157. */
  158. public function getDocPartId()
  159. {
  160. return $this->docPartId;
  161. }
  162. /**
  163. * Return media element (image, object, link) container name
  164. *
  165. * @return string section|headerx|footerx|footnote|endnote
  166. */
  167. private function getMediaPart()
  168. {
  169. $mediaPart = $this->docPart;
  170. if ($mediaPart == 'Header' || $mediaPart == 'Footer') {
  171. $mediaPart .= $this->docPartId;
  172. }
  173. return strtolower($mediaPart);
  174. }
  175. /**
  176. * Get element index
  177. *
  178. * @return int
  179. */
  180. public function getElementIndex()
  181. {
  182. return $this->elementIndex;
  183. }
  184. /**
  185. * Set element index.
  186. *
  187. * @param int $value
  188. * @return void
  189. */
  190. public function setElementIndex($value)
  191. {
  192. $this->elementIndex = $value;
  193. }
  194. /**
  195. * Get element unique ID
  196. *
  197. * @return string
  198. */
  199. public function getElementId()
  200. {
  201. return $this->elementId;
  202. }
  203. /**
  204. * Set element unique ID from 6 first digit of md5.
  205. *
  206. * @return void
  207. */
  208. public function setElementId()
  209. {
  210. $this->elementId = substr(md5(rand()), 0, 6);
  211. }
  212. /**
  213. * Get relation Id
  214. *
  215. * @return int
  216. */
  217. public function getRelationId()
  218. {
  219. return $this->relationId;
  220. }
  221. /**
  222. * Set relation Id.
  223. *
  224. * @param int $value
  225. * @return void
  226. */
  227. public function setRelationId($value)
  228. {
  229. $this->relationId = $value;
  230. }
  231. /**
  232. * Get nested level
  233. *
  234. * @return int
  235. */
  236. public function getNestedLevel()
  237. {
  238. return $this->nestedLevel;
  239. }
  240. /**
  241. * Set parent container
  242. *
  243. * Passed parameter should be a container, except for Table (contain Row) and Row (contain Cell)
  244. *
  245. * @param \PhpOffice\PhpWord\Element\AbstractElement $container
  246. * @return void
  247. */
  248. public function setParentContainer(AbstractElement $container)
  249. {
  250. $this->parentContainer = substr(get_class($container), strrpos(get_class($container), '\\') + 1);
  251. // Set nested level
  252. $this->nestedLevel = $container->getNestedLevel();
  253. if ($this->parentContainer == 'Cell') {
  254. $this->nestedLevel++;
  255. }
  256. // Set phpword
  257. $this->setPhpWord($container->getPhpWord());
  258. // Set doc part
  259. if (!$this instanceof Footnote) {
  260. $this->setDocPart($container->getDocPart(), $container->getDocPartId());
  261. }
  262. $this->setMediaRelation();
  263. $this->setCollectionRelation();
  264. }
  265. /**
  266. * Set relation Id for media elements (link, image, object; legacy of OOXML)
  267. *
  268. * - Image element needs to be passed to Media object
  269. * - Icon needs to be set for Object element
  270. *
  271. * @return void
  272. */
  273. private function setMediaRelation()
  274. {
  275. if (!$this instanceof Link && !$this instanceof Image && !$this instanceof Object) {
  276. return;
  277. }
  278. $elementName = substr(get_class($this), strrpos(get_class($this), '\\') + 1);
  279. $mediaPart = $this->getMediaPart();
  280. $source = $this->getSource();
  281. $image = null;
  282. if ($this instanceof Image) {
  283. $image = $this;
  284. }
  285. $rId = Media::addElement($mediaPart, strtolower($elementName), $source, $image);
  286. $this->setRelationId($rId);
  287. if ($this instanceof Object) {
  288. $icon = $this->getIcon();
  289. $rId = Media::addElement($mediaPart, 'image', $icon, new Image($icon));
  290. $this->setImageRelationId($rId);
  291. }
  292. }
  293. /**
  294. * Set relation Id for elements that will be registered in the Collection subnamespaces.
  295. *
  296. * @return void
  297. */
  298. private function setCollectionRelation()
  299. {
  300. if ($this->collectionRelation === true && $this->phpWord instanceof PhpWord) {
  301. $elementName = substr(get_class($this), strrpos(get_class($this), '\\') + 1);
  302. $addMethod = "add{$elementName}";
  303. $rId = $this->phpWord->$addMethod($this);
  304. $this->setRelationId($rId);
  305. }
  306. }
  307. /**
  308. * Check if element is located in Section doc part (as opposed to Header/Footer)
  309. *
  310. * @return bool
  311. */
  312. public function isInSection()
  313. {
  314. return ($this->docPart == 'Section');
  315. }
  316. /**
  317. * Set new style value
  318. *
  319. * @param mixed $styleObject Style object
  320. * @param mixed $styleValue Style value
  321. * @param bool $returnObject Always return object
  322. * @return mixed
  323. */
  324. protected function setNewStyle($styleObject, $styleValue = null, $returnObject = false)
  325. {
  326. if (!is_null($styleValue) && is_array($styleValue)) {
  327. $styleObject->setStyleByArray($styleValue);
  328. $style = $styleObject;
  329. } else {
  330. $style = $returnObject ? $styleObject : $styleValue;
  331. }
  332. return $style;
  333. }
  334. /**
  335. * Set enum value
  336. *
  337. * @param mixed $value
  338. * @param array $enum
  339. * @param mixed $default
  340. * @return mixed
  341. * @throws \InvalidArgumentException
  342. * @todo Merge with the same method in AbstractStyle
  343. */
  344. protected function setEnumVal($value = null, $enum = array(), $default = null)
  345. {
  346. if ($value != null && trim($value) != '' && !empty($enum) && !in_array($value, $enum)) {
  347. throw new \InvalidArgumentException("Invalid style value: {$value}");
  348. } elseif ($value === null || trim($value) == '') {
  349. $value = $default;
  350. }
  351. return $value;
  352. }
  353. }