See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401]
1 <?php 2 3 namespace Box\Spout\Reader\XLSX\Manager; 4 5 use Box\Spout\Common\Exception\IOException; 6 use Box\Spout\Reader\Wrapper\XMLReader; 7 use Box\Spout\Reader\XLSX\Creator\InternalEntityFactory; 8 9 /** 10 * Class WorkbookRelationshipsManager 11 * This class manages the workbook relationships defined in the associated XML file 12 */ 13 class WorkbookRelationshipsManager 14 { 15 const BASE_PATH = 'xl/'; 16 17 /** Path of workbook relationships XML file inside the XLSX file */ 18 const WORKBOOK_RELS_XML_FILE_PATH = 'xl/_rels/workbook.xml.rels'; 19 20 /** Relationships types */ 21 const RELATIONSHIP_TYPE_SHARED_STRINGS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings'; 22 const RELATIONSHIP_TYPE_STYLES = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles'; 23 const RELATIONSHIP_TYPE_WORKSHEET = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet'; 24 25 /** Nodes and attributes used to find relevant information in the workbook relationships XML file */ 26 const XML_NODE_RELATIONSHIP = 'Relationship'; 27 const XML_ATTRIBUTE_TYPE = 'Type'; 28 const XML_ATTRIBUTE_TARGET = 'Target'; 29 30 /** @var string Path of the XLSX file being read */ 31 private $filePath; 32 33 /** @var InternalEntityFactory Factory to create entities */ 34 private $entityFactory; 35 36 /** @var array Cache of the already read workbook relationships: [TYPE] => [FILE_NAME] */ 37 private $cachedWorkbookRelationships; 38 39 /** 40 * @param string $filePath Path of the XLSX file being read 41 * @param InternalEntityFactory $entityFactory Factory to create entities 42 */ 43 public function __construct($filePath, $entityFactory) 44 { 45 $this->filePath = $filePath; 46 $this->entityFactory = $entityFactory; 47 } 48 49 /** 50 * @return string The path of the shared string XML file 51 */ 52 public function getSharedStringsXMLFilePath() 53 { 54 $workbookRelationships = $this->getWorkbookRelationships(); 55 $sharedStringsXMLFilePath = $workbookRelationships[self::RELATIONSHIP_TYPE_SHARED_STRINGS]; 56 57 // the file path can be relative (e.g. "styles.xml") or absolute (e.g. "/xl/styles.xml") 58 $doesContainBasePath = (strpos($sharedStringsXMLFilePath, self::BASE_PATH) !== false); 59 if (!$doesContainBasePath) { 60 // make sure we return an absolute file path 61 $sharedStringsXMLFilePath = self::BASE_PATH . $sharedStringsXMLFilePath; 62 } 63 64 return $sharedStringsXMLFilePath; 65 } 66 67 /** 68 * @return bool Whether the XLSX file contains a shared string XML file 69 */ 70 public function hasSharedStringsXMLFile() 71 { 72 $workbookRelationships = $this->getWorkbookRelationships(); 73 74 return isset($workbookRelationships[self::RELATIONSHIP_TYPE_SHARED_STRINGS]); 75 } 76 77 /** 78 * @return string|null The path of the styles XML file 79 */ 80 public function getStylesXMLFilePath() 81 { 82 $workbookRelationships = $this->getWorkbookRelationships(); 83 $stylesXMLFilePath = $workbookRelationships[self::RELATIONSHIP_TYPE_STYLES]; 84 85 // the file path can be relative (e.g. "styles.xml") or absolute (e.g. "/xl/styles.xml") 86 $doesContainBasePath = (strpos($stylesXMLFilePath, self::BASE_PATH) !== false); 87 if (!$doesContainBasePath) { 88 // make sure we return a full path 89 $stylesXMLFilePath = self::BASE_PATH . $stylesXMLFilePath; 90 } 91 92 return $stylesXMLFilePath; 93 } 94 95 /** 96 * Reads the workbook.xml.rels and extracts the filename associated to the different types. 97 * It caches the result so that the file is read only once. 98 * 99 * @throws \Box\Spout\Common\Exception\IOException If workbook.xml.rels can't be read 100 * @return array 101 */ 102 private function getWorkbookRelationships() 103 { 104 if (!isset($this->cachedWorkbookRelationships)) { 105 $xmlReader = $this->entityFactory->createXMLReader(); 106 107 if ($xmlReader->openFileInZip($this->filePath, self::WORKBOOK_RELS_XML_FILE_PATH) === false) { 108 throw new IOException('Could not open "' . self::WORKBOOK_RELS_XML_FILE_PATH . '".'); 109 } 110 111 $this->cachedWorkbookRelationships = []; 112 113 while ($xmlReader->readUntilNodeFound(self::XML_NODE_RELATIONSHIP)) { 114 $this->processWorkbookRelationship($xmlReader); 115 } 116 } 117 118 return $this->cachedWorkbookRelationships; 119 } 120 121 /** 122 * Extracts and store the data of the current workbook relationship. 123 * 124 * @param XMLReader $xmlReader 125 * @return void 126 */ 127 private function processWorkbookRelationship($xmlReader) 128 { 129 $type = $xmlReader->getAttribute(self::XML_ATTRIBUTE_TYPE); 130 $target = $xmlReader->getAttribute(self::XML_ATTRIBUTE_TARGET); 131 132 // @NOTE: if a type is defined more than once, we overwrite the previous value 133 // To be changed if we want to get the file paths of sheet XML files for instance. 134 $this->cachedWorkbookRelationships[$type] = $target; 135 } 136 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body