Aucune description

Word2007.php 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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;
  18. use PhpOffice\PhpWord\PhpWord;
  19. use PhpOffice\PhpWord\Shared\XMLReader;
  20. use PhpOffice\PhpWord\Shared\ZipArchive;
  21. /**
  22. * Reader for Word2007
  23. *
  24. * @since 0.8.0
  25. * @todo watermark, checkbox, toc
  26. * @todo Partly done: image, object
  27. */
  28. class Word2007 extends AbstractReader implements ReaderInterface
  29. {
  30. /**
  31. * Loads PhpWord from file
  32. *
  33. * @param string $docFile
  34. * @return \PhpOffice\PhpWord\PhpWord
  35. */
  36. public function load($docFile)
  37. {
  38. $phpWord = new PhpWord();
  39. $relationships = $this->readRelationships($docFile);
  40. $steps = array(
  41. array('stepPart' => 'document', 'stepItems' => array(
  42. 'styles' => 'Styles',
  43. 'numbering' => 'Numbering',
  44. )),
  45. array('stepPart' => 'main', 'stepItems' => array(
  46. 'officeDocument' => 'Document',
  47. 'core-properties' => 'DocPropsCore',
  48. 'extended-properties' => 'DocPropsApp',
  49. 'custom-properties' => 'DocPropsCustom',
  50. )),
  51. array('stepPart' => 'document', 'stepItems' => array(
  52. 'endnotes' => 'Endnotes',
  53. 'footnotes' => 'Footnotes',
  54. )),
  55. );
  56. foreach ($steps as $step) {
  57. $stepPart = $step['stepPart'];
  58. $stepItems = $step['stepItems'];
  59. foreach ($relationships[$stepPart] as $relItem) {
  60. $relType = $relItem['type'];
  61. if (isset($stepItems[$relType])) {
  62. $partName = $stepItems[$relType];
  63. $xmlFile = $relItem['target'];
  64. $this->readPart($phpWord, $relationships, $partName, $docFile, $xmlFile);
  65. }
  66. }
  67. }
  68. return $phpWord;
  69. }
  70. /**
  71. * Read document part.
  72. *
  73. * @param \PhpOffice\PhpWord\PhpWord $phpWord
  74. * @param array $relationships
  75. * @param string $partName
  76. * @param string $docFile
  77. * @param string $xmlFile
  78. * @return void
  79. */
  80. private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile, $xmlFile)
  81. {
  82. $partClass = "PhpOffice\\PhpWord\\Reader\\Word2007\\{$partName}";
  83. if (class_exists($partClass)) {
  84. /** @var \PhpOffice\PhpWord\Reader\Word2007\AbstractPart $part Type hint */
  85. $part = new $partClass($docFile, $xmlFile);
  86. $part->setRels($relationships);
  87. $part->read($phpWord);
  88. }
  89. }
  90. /**
  91. * Read all relationship files
  92. *
  93. * @param string $docFile
  94. * @return array
  95. */
  96. private function readRelationships($docFile)
  97. {
  98. $relationships = array();
  99. // _rels/.rels
  100. $relationships['main'] = $this->getRels($docFile, '_rels/.rels');
  101. // word/_rels/*.xml.rels
  102. $wordRelsPath = 'word/_rels/';
  103. $zip = new ZipArchive();
  104. if ($zip->open($docFile) === true) {
  105. for ($i = 0; $i < $zip->numFiles; $i++) {
  106. $xmlFile = $zip->getNameIndex($i);
  107. if ((substr($xmlFile, 0, strlen($wordRelsPath))) == $wordRelsPath && (substr($xmlFile, -1)) != '/') {
  108. $docPart = str_replace('.xml.rels', '', str_replace($wordRelsPath, '', $xmlFile));
  109. $relationships[$docPart] = $this->getRels($docFile, $xmlFile, 'word/');
  110. }
  111. }
  112. $zip->close();
  113. }
  114. return $relationships;
  115. }
  116. /**
  117. * Get relationship array
  118. *
  119. * @param string $docFile
  120. * @param string $xmlFile
  121. * @param string $targetPrefix
  122. * @return array
  123. */
  124. private function getRels($docFile, $xmlFile, $targetPrefix = '')
  125. {
  126. $metaPrefix = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/';
  127. $officePrefix = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/';
  128. $rels = array();
  129. $xmlReader = new XMLReader();
  130. $xmlReader->getDomFromZip($docFile, $xmlFile);
  131. $nodes = $xmlReader->getElements('*');
  132. foreach ($nodes as $node) {
  133. $rId = $xmlReader->getAttribute('Id', $node);
  134. $type = $xmlReader->getAttribute('Type', $node);
  135. $target = $xmlReader->getAttribute('Target', $node);
  136. // Remove URL prefixes from $type to make it easier to read
  137. $type = str_replace($metaPrefix, '', $type);
  138. $type = str_replace($officePrefix, '', $type);
  139. $docPart = str_replace('.xml', '', $target);
  140. // Do not add prefix to link source
  141. if (!in_array($type, array('hyperlink'))) {
  142. $target = $targetPrefix . $target;
  143. }
  144. // Push to return array
  145. $rels[$rId] = array('type' => $type, 'target' => $target, 'docPart' => $docPart);
  146. }
  147. ksort($rels);
  148. return $rels;
  149. }
  150. }