PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 4.0.8
Visualizer – Tables & Charts Manager with Built-in AI Generator v4.0.8
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 All 149 releases
visualizer / vendor / openspout / openspout / src / Reader / Wrapper / XMLReader.php

XMLReader.php in Visualizer – Tables & Charts Manager with Built-in AI Generator 4.0.8, at vendor/openspout/openspout/src/Reader/Wrapper/XMLReader.php

193 lines 5.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace OpenSpout\Reader\Wrapper;
4
5 /**
6 * Wrapper around the built-in XMLReader.
7 *
8 * @see \XMLReader
9 */
10 class XMLReader extends \XMLReader
11 {
12 use XMLInternalErrorsHelper;
13
14 public const ZIP_WRAPPER = 'zip://';
15
16 /**
17 * Opens the XML Reader to read a file located inside a ZIP file.
18 *
19 * @param string $zipFilePath Path to the ZIP file
20 * @param string $fileInsideZipPath Relative or absolute path of the file inside the zip
21 *
22 * @return bool TRUE on success or FALSE on failure
23 */
24 public function openFileInZip($zipFilePath, $fileInsideZipPath)
25 {
26 $wasOpenSuccessful = false;
27 $realPathURI = $this->getRealPathURIForFileInZip($zipFilePath, $fileInsideZipPath);
28
29 // We need to check first that the file we are trying to read really exist because:
30 // - PHP emits a warning when trying to open a file that does not exist.
31 // - HHVM does not check if file exists within zip file (@link https://github.com/facebook/hhvm/issues/5779)
32 if ($this->fileExistsWithinZip($realPathURI)) {
33 $wasOpenSuccessful = $this->open($realPathURI, null, LIBXML_NONET);
34 }
35
36 return $wasOpenSuccessful;
37 }
38
39 /**
40 * Returns the real path for the given path components.
41 * This is useful to avoid issues on some Windows setup.
42 *
43 * @param string $zipFilePath Path to the ZIP file
44 * @param string $fileInsideZipPath Relative or absolute path of the file inside the zip
45 *
46 * @return string The real path URI
47 */
48 public function getRealPathURIForFileInZip($zipFilePath, $fileInsideZipPath)
49 {
50 // The file path should not start with a '/', otherwise it won't be found
51 $fileInsideZipPathWithoutLeadingSlash = ltrim($fileInsideZipPath, '/');
52
53 return self::ZIP_WRAPPER.realpath($zipFilePath).'#'.$fileInsideZipPathWithoutLeadingSlash;
54 }
55
56 /**
57 * Move to next node in document.
58 *
59 * @see \XMLReader::read
60 *
61 * @throws \OpenSpout\Reader\Exception\XMLProcessingException If an error/warning occurred
62 *
63 * @return bool TRUE on success or FALSE on failure
64 */
65 #[\ReturnTypeWillChange]
66 public function read()
67 {
68 $this->useXMLInternalErrors();
69
70 $wasReadSuccessful = parent::read();
71
72 $this->resetXMLInternalErrorsSettingAndThrowIfXMLErrorOccured();
73
74 return $wasReadSuccessful;
75 }
76
77 /**
78 * Read until the element with the given name is found, or the end of the file.
79 *
80 * @param string $nodeName Name of the node to find
81 *
82 * @throws \OpenSpout\Reader\Exception\XMLProcessingException If an error/warning occurred
83 *
84 * @return bool TRUE on success or FALSE on failure
85 */
86 public function readUntilNodeFound($nodeName)
87 {
88 do {
89 $wasReadSuccessful = $this->read();
90 $isNotPositionedOnStartingNode = !$this->isPositionedOnStartingNode($nodeName);
91 } while ($wasReadSuccessful && $isNotPositionedOnStartingNode);
92
93 return $wasReadSuccessful;
94 }
95
96 /**
97 * Move cursor to next node skipping all subtrees.
98 *
99 * @see \XMLReader::next
100 *
101 * @param null|string $localName The name of the next node to move to
102 *
103 * @throws \OpenSpout\Reader\Exception\XMLProcessingException If an error/warning occurred
104 *
105 * @return bool TRUE on success or FALSE on failure
106 */
107 #[\ReturnTypeWillChange]
108 public function next($localName = null)
109 {
110 $this->useXMLInternalErrors();
111
112 $wasNextSuccessful = parent::next($localName);
113
114 $this->resetXMLInternalErrorsSettingAndThrowIfXMLErrorOccured();
115
116 return $wasNextSuccessful;
117 }
118
119 /**
120 * @param string $nodeName
121 *
122 * @return bool Whether the XML Reader is currently positioned on the starting node with given name
123 */
124 public function isPositionedOnStartingNode($nodeName)
125 {
126 return $this->isPositionedOnNode($nodeName, self::ELEMENT);
127 }
128
129 /**
130 * @param string $nodeName
131 *
132 * @return bool Whether the XML Reader is currently positioned on the ending node with given name
133 */
134 public function isPositionedOnEndingNode($nodeName)
135 {
136 return $this->isPositionedOnNode($nodeName, self::END_ELEMENT);
137 }
138
139 /**
140 * @return string The name of the current node, un-prefixed
141 */
142 public function getCurrentNodeName()
143 {
144 return $this->localName;
145 }
146
147 /**
148 * Returns whether the file at the given location exists.
149 *
150 * @param string $zipStreamURI URI of a zip stream, e.g. "zip://file.zip#path/inside.xml"
151 *
152 * @return bool TRUE if the file exists, FALSE otherwise
153 */
154 protected function fileExistsWithinZip($zipStreamURI)
155 {
156 $doesFileExists = false;
157
158 $pattern = '/zip:\/\/([^#]+)#(.*)/';
159 if (preg_match($pattern, $zipStreamURI, $matches)) {
160 $zipFilePath = $matches[1];
161 $innerFilePath = $matches[2];
162
163 $zip = new \ZipArchive();
164 if (true === $zip->open($zipFilePath)) {
165 $doesFileExists = (false !== $zip->locateName($innerFilePath));
166 $zip->close();
167 }
168 }
169
170 return $doesFileExists;
171 }
172
173 /**
174 * @param string $nodeName
175 * @param int $nodeType
176 *
177 * @return bool Whether the XML Reader is currently positioned on the node with given name and type
178 */
179 private function isPositionedOnNode($nodeName, $nodeType)
180 {
181 /**
182 * In some cases, the node has a prefix (for instance, "<sheet>" can also be "<x:sheet>").
183 * So if the given node name does not have a prefix, we need to look at the unprefixed name ("localName").
184 *
185 * @see https://github.com/box/spout/issues/233
186 */
187 $hasPrefix = (false !== strpos($nodeName, ':'));
188 $currentNodeName = ($hasPrefix) ? $this->name : $this->localName;
189
190 return $this->nodeType === $nodeType && $currentNodeName === $nodeName;
191 }
192 }
193