Document.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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\Reader\Word2007;
  18. use PhpOffice\PhpWord\Element\Section;
  19. use PhpOffice\PhpWord\PhpWord;
  20. use PhpOffice\PhpWord\Shared\XMLReader;
  21. /**
  22. * Document reader
  23. *
  24. * @since 0.10.0
  25. * @SuppressWarnings(PHPMD.UnusedPrivateMethod) For readWPNode
  26. */
  27. class Document extends AbstractPart
  28. {
  29. /**
  30. * PhpWord object
  31. *
  32. * @var \PhpOffice\PhpWord\PhpWord
  33. */
  34. private $phpWord;
  35. /**
  36. * Read document.xml.
  37. *
  38. * @param \PhpOffice\PhpWord\PhpWord $phpWord
  39. * @return void
  40. */
  41. public function read(PhpWord $phpWord)
  42. {
  43. $this->phpWord = $phpWord;
  44. $xmlReader = new XMLReader();
  45. $xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
  46. $readMethods = array('w:p' => 'readWPNode', 'w:tbl' => 'readTable', 'w:sectPr' => 'readWSectPrNode');
  47. $nodes = $xmlReader->getElements('w:body/*');
  48. if ($nodes->length > 0) {
  49. $section = $this->phpWord->addSection();
  50. foreach ($nodes as $node) {
  51. if (isset($readMethods[$node->nodeName])) {
  52. $readMethod = $readMethods[$node->nodeName];
  53. $this->$readMethod($xmlReader, $node, $section);
  54. }
  55. }
  56. }
  57. }
  58. /**
  59. * Read header footer.
  60. *
  61. * @param array $settings
  62. * @param \PhpOffice\PhpWord\Element\Section &$section
  63. * @return void
  64. */
  65. private function readHeaderFooter($settings, Section &$section)
  66. {
  67. $readMethods = array('w:p' => 'readParagraph', 'w:tbl' => 'readTable');
  68. if (is_array($settings) && isset($settings['hf'])) {
  69. foreach ($settings['hf'] as $rID => $hfSetting) {
  70. if (isset($this->rels['document'][$rID])) {
  71. list($hfType, $xmlFile, $docPart) = array_values($this->rels['document'][$rID]);
  72. $addMethod = "add{$hfType}";
  73. $hfObject = $section->$addMethod($hfSetting['type']);
  74. // Read header/footer content
  75. $xmlReader = new XMLReader();
  76. $xmlReader->getDomFromZip($this->docFile, $xmlFile);
  77. $nodes = $xmlReader->getElements('*');
  78. if ($nodes->length > 0) {
  79. foreach ($nodes as $node) {
  80. if (isset($readMethods[$node->nodeName])) {
  81. $readMethod = $readMethods[$node->nodeName];
  82. $this->$readMethod($xmlReader, $node, $hfObject, $docPart);
  83. }
  84. }
  85. }
  86. }
  87. }
  88. }
  89. }
  90. /**
  91. * Read w:sectPr
  92. *
  93. * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
  94. * @param \DOMElement $domNode
  95. * @ignoreScrutinizerPatch
  96. * @return array
  97. */
  98. private function readSectionStyle(XMLReader $xmlReader, \DOMElement $domNode)
  99. {
  100. $styleDefs = array(
  101. 'breakType' => array(self::READ_VALUE, 'w:type'),
  102. 'pageSizeW' => array(self::READ_VALUE, 'w:pgSz', 'w:w'),
  103. 'pageSizeH' => array(self::READ_VALUE, 'w:pgSz', 'w:h'),
  104. 'orientation' => array(self::READ_VALUE, 'w:pgSz', 'w:orient'),
  105. 'colsNum' => array(self::READ_VALUE, 'w:cols', 'w:num'),
  106. 'colsSpace' => array(self::READ_VALUE, 'w:cols', 'w:space'),
  107. 'topMargin' => array(self::READ_VALUE, 'w:pgMar', 'w:top'),
  108. 'leftMargin' => array(self::READ_VALUE, 'w:pgMar', 'w:left'),
  109. 'bottomMargin' => array(self::READ_VALUE, 'w:pgMar', 'w:bottom'),
  110. 'rightMargin' => array(self::READ_VALUE, 'w:pgMar', 'w:right'),
  111. 'headerHeight' => array(self::READ_VALUE, 'w:pgMar', 'w:header'),
  112. 'footerHeight' => array(self::READ_VALUE, 'w:pgMar', 'w:footer'),
  113. 'gutter' => array(self::READ_VALUE, 'w:pgMar', 'w:gutter'),
  114. );
  115. $styles = $this->readStyleDefs($xmlReader, $domNode, $styleDefs);
  116. // Header and footer
  117. // @todo Cleanup this part
  118. $nodes = $xmlReader->getElements('*', $domNode);
  119. foreach ($nodes as $node) {
  120. if ($node->nodeName == 'w:headerReference' || $node->nodeName == 'w:footerReference') {
  121. $id = $xmlReader->getAttribute('r:id', $node);
  122. $styles['hf'][$id] = array(
  123. 'method' => str_replace('w:', '', str_replace('Reference', '', $node->nodeName)),
  124. 'type' => $xmlReader->getAttribute('w:type', $node),
  125. );
  126. }
  127. }
  128. return $styles;
  129. }
  130. /**
  131. * Read w:p node.
  132. *
  133. * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
  134. * @param \DOMElement $node
  135. * @param \PhpOffice\PhpWord\Element\Section &$section
  136. * @return void
  137. *
  138. * @todo <w:lastRenderedPageBreak>
  139. */
  140. private function readWPNode(XMLReader $xmlReader, \DOMElement $node, Section &$section)
  141. {
  142. // Page break
  143. if ($xmlReader->getAttribute('w:type', $node, 'w:r/w:br') == 'page') {
  144. $section->addPageBreak(); // PageBreak
  145. }
  146. // Paragraph
  147. $this->readParagraph($xmlReader, $node, $section);
  148. // Section properties
  149. if ($xmlReader->elementExists('w:pPr/w:sectPr', $node)) {
  150. $sectPrNode = $xmlReader->getElement('w:pPr/w:sectPr', $node);
  151. if ($sectPrNode !== null) {
  152. $this->readWSectPrNode($xmlReader, $sectPrNode, $section);
  153. }
  154. $section = $this->phpWord->addSection();
  155. }
  156. }
  157. /**
  158. * Read w:sectPr node.
  159. *
  160. * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
  161. * @param \DOMElement $node
  162. * @param \PhpOffice\PhpWord\Element\Section &$section
  163. * @return void
  164. */
  165. private function readWSectPrNode(XMLReader $xmlReader, \DOMElement $node, Section &$section)
  166. {
  167. $style = $this->readSectionStyle($xmlReader, $node);
  168. $section->setStyle($style);
  169. $this->readHeaderFooter($style, $section);
  170. }
  171. }