PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.3.28
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.3.28
1.6.6 1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 All 49 releases
fluent-cart / vendor / openspout / openspout / src / Reader / ODS / SheetIterator.php

SheetIterator.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.3.28, at vendor/openspout/openspout/src/Reader/ODS/SheetIterator.php

193 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\OpenSpout\Reader\ODS;
4
5 use FluentCart\OpenSpout\Common\Exception\IOException;
6 use FluentCart\OpenSpout\Reader\Exception\XMLProcessingException;
7 use FluentCart\OpenSpout\Reader\IteratorInterface;
8 use FluentCart\OpenSpout\Reader\ODS\Creator\InternalEntityFactory;
9 use FluentCart\OpenSpout\Reader\ODS\Helper\SettingsHelper;
10 use FluentCart\OpenSpout\Reader\Wrapper\XMLReader;
11 /**
12 * Iterate over ODS sheet.
13 */
14 class SheetIterator implements IteratorInterface
15 {
16 public const CONTENT_XML_FILE_PATH = 'content.xml';
17 public const XML_STYLE_NAMESPACE = 'urn:oasis:names:tc:opendocument:xmlns:style:1.0';
18 /** Definition of XML nodes name and attribute used to parse sheet data */
19 public const XML_NODE_AUTOMATIC_STYLES = 'office:automatic-styles';
20 public const XML_NODE_STYLE_TABLE_PROPERTIES = 'table-properties';
21 public const XML_NODE_TABLE = 'table:table';
22 public const XML_ATTRIBUTE_STYLE_NAME = 'style:name';
23 public const XML_ATTRIBUTE_TABLE_NAME = 'table:name';
24 public const XML_ATTRIBUTE_TABLE_STYLE_NAME = 'table:style-name';
25 public const XML_ATTRIBUTE_TABLE_DISPLAY = 'table:display';
26 /** @var string Path of the file to be read */
27 protected $filePath;
28 /** @var \OpenSpout\Common\Manager\OptionsManagerInterface Reader's options manager */
29 protected $optionsManager;
30 /** @var InternalEntityFactory Factory to create entities */
31 protected $entityFactory;
32 /** @var XMLReader The XMLReader object that will help read sheet's XML data */
33 protected $xmlReader;
34 /** @var \OpenSpout\Common\Helper\Escaper\ODS Used to unescape XML data */
35 protected $escaper;
36 /** @var bool Whether there are still at least a sheet to be read */
37 protected $hasFoundSheet;
38 /** @var int The index of the sheet being read (zero-based) */
39 protected $currentSheetIndex;
40 /** @var string The name of the sheet that was defined as active */
41 protected $activeSheetName;
42 /** @var array Associative array [STYLE_NAME] => [IS_SHEET_VISIBLE] */
43 protected $sheetsVisibility;
44 /**
45 * @param string $filePath Path of the file to be read
46 * @param \OpenSpout\Common\Manager\OptionsManagerInterface $optionsManager
47 * @param \OpenSpout\Common\Helper\Escaper\ODS $escaper Used to unescape XML data
48 * @param SettingsHelper $settingsHelper Helper to get data from "settings.xml"
49 * @param InternalEntityFactory $entityFactory Factory to create entities
50 */
51 public function __construct($filePath, $optionsManager, $escaper, $settingsHelper, $entityFactory)
52 {
53 $this->filePath = $filePath;
54 $this->optionsManager = $optionsManager;
55 $this->entityFactory = $entityFactory;
56 $this->xmlReader = $entityFactory->createXMLReader();
57 $this->escaper = $escaper;
58 $this->activeSheetName = $settingsHelper->getActiveSheetName($filePath);
59 }
60 /**
61 * Rewind the Iterator to the first element.
62 *
63 * @see http://php.net/manual/en/iterator.rewind.php
64 *
65 * @throws \OpenSpout\Common\Exception\IOException If unable to open the XML file containing sheets' data
66 */
67 #[\ReturnTypeWillChange]
68 public function rewind()
69 {
70 $this->xmlReader->close();
71 if (\false === $this->xmlReader->openFileInZip($this->filePath, self::CONTENT_XML_FILE_PATH)) {
72 $contentXmlFilePath = $this->filePath . '#' . self::CONTENT_XML_FILE_PATH;
73 throw new IOException("Could not open \"{$contentXmlFilePath}\".");
74 }
75 try {
76 $this->sheetsVisibility = $this->readSheetsVisibility();
77 $this->hasFoundSheet = $this->xmlReader->readUntilNodeFound(self::XML_NODE_TABLE);
78 } catch (XMLProcessingException $exception) {
79 throw new IOException("The content.xml file is invalid and cannot be read. [{$exception->getMessage()}]");
80 }
81 $this->currentSheetIndex = 0;
82 }
83 /**
84 * Checks if current position is valid.
85 *
86 * @see http://php.net/manual/en/iterator.valid.php
87 *
88 * @return bool
89 */
90 #[\ReturnTypeWillChange]
91 public function valid()
92 {
93 return $this->hasFoundSheet;
94 }
95 /**
96 * Move forward to next element.
97 *
98 * @see http://php.net/manual/en/iterator.next.php
99 */
100 #[\ReturnTypeWillChange]
101 public function next()
102 {
103 $this->hasFoundSheet = $this->xmlReader->readUntilNodeFound(self::XML_NODE_TABLE);
104 if ($this->hasFoundSheet) {
105 ++$this->currentSheetIndex;
106 }
107 }
108 /**
109 * Return the current element.
110 *
111 * @see http://php.net/manual/en/iterator.current.php
112 *
113 * @return \OpenSpout\Reader\ODS\Sheet
114 */
115 #[\ReturnTypeWillChange]
116 public function current()
117 {
118 $escapedSheetName = $this->xmlReader->getAttribute(self::XML_ATTRIBUTE_TABLE_NAME);
119 $sheetName = $this->escaper->unescape($escapedSheetName);
120 $isSheetActive = $this->isSheetActive($sheetName, $this->currentSheetIndex, $this->activeSheetName);
121 $sheetStyleName = $this->xmlReader->getAttribute(self::XML_ATTRIBUTE_TABLE_STYLE_NAME);
122 $isSheetVisible = $this->isSheetVisible($sheetStyleName);
123 return $this->entityFactory->createSheet($this->xmlReader, $this->currentSheetIndex, $sheetName, $isSheetActive, $isSheetVisible, $this->optionsManager);
124 }
125 /**
126 * Return the key of the current element.
127 *
128 * @see http://php.net/manual/en/iterator.key.php
129 *
130 * @return int
131 */
132 #[\ReturnTypeWillChange]
133 public function key()
134 {
135 return $this->currentSheetIndex + 1;
136 }
137 /**
138 * Cleans up what was created to iterate over the object.
139 */
140 #[\ReturnTypeWillChange]
141 public function end()
142 {
143 $this->xmlReader->close();
144 }
145 /**
146 * Extracts the visibility of the sheets.
147 *
148 * @return array Associative array [STYLE_NAME] => [IS_SHEET_VISIBLE]
149 */
150 private function readSheetsVisibility()
151 {
152 $sheetsVisibility = [];
153 $this->xmlReader->readUntilNodeFound(self::XML_NODE_AUTOMATIC_STYLES);
154 /** @var \DOMElement $automaticStylesNode */
155 $automaticStylesNode = $this->xmlReader->expand();
156 $tableStyleNodes = $automaticStylesNode->getElementsByTagNameNS(self::XML_STYLE_NAMESPACE, self::XML_NODE_STYLE_TABLE_PROPERTIES);
157 /** @var \DOMElement $tableStyleNode */
158 foreach ($tableStyleNodes as $tableStyleNode) {
159 $isSheetVisible = 'false' !== $tableStyleNode->getAttribute(self::XML_ATTRIBUTE_TABLE_DISPLAY);
160 $parentStyleNode = $tableStyleNode->parentNode;
161 $styleName = $parentStyleNode->getAttribute(self::XML_ATTRIBUTE_STYLE_NAME);
162 $sheetsVisibility[$styleName] = $isSheetVisible;
163 }
164 return $sheetsVisibility;
165 }
166 /**
167 * Returns whether the current sheet was defined as the active one.
168 *
169 * @param string $sheetName Name of the current sheet
170 * @param int $sheetIndex Index of the current sheet
171 * @param null|string $activeSheetName Name of the sheet that was defined as active or NULL if none defined
172 *
173 * @return bool Whether the current sheet was defined as the active one
174 */
175 private function isSheetActive($sheetName, $sheetIndex, $activeSheetName)
176 {
177 // The given sheet is active if its name matches the defined active sheet's name
178 // or if no information about the active sheet was found, it defaults to the first sheet.
179 return null === $activeSheetName && 0 === $sheetIndex || $activeSheetName === $sheetName;
180 }
181 /**
182 * Returns whether the current sheet is visible.
183 *
184 * @param string $sheetStyleName Name of the sheet style
185 *
186 * @return bool Whether the current sheet is visible
187 */
188 private function isSheetVisible($sheetStyleName)
189 {
190 return $this->sheetsVisibility[$sheetStyleName] ?? \true;
191 }
192 }
193