PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.1
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.1
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 trunk All 48 releases
fluent-cart / vendor / openspout / openspout / src / Writer / ODS / Helper / FileSystemHelper.php

FileSystemHelper.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.1, at vendor/openspout/openspout/src/Writer/ODS/Helper/FileSystemHelper.php

251 lines 11.3 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\Writer\ODS\Helper;
4
5 use FluentCart\OpenSpout\Writer\Common\Entity\Worksheet;
6 use FluentCart\OpenSpout\Writer\Common\Helper\FileSystemWithRootFolderHelperInterface;
7 use FluentCart\OpenSpout\Writer\Common\Helper\ZipHelper;
8 use FluentCart\OpenSpout\Writer\ODS\Manager\Style\StyleManager;
9 use FluentCart\OpenSpout\Writer\ODS\Manager\WorksheetManager;
10 /**
11 * This class provides helper functions to help with the file system operations
12 * like files/folders creation & deletion for ODS files.
13 */
14 class FileSystemHelper extends \FluentCart\OpenSpout\Common\Helper\FileSystemHelper implements FileSystemWithRootFolderHelperInterface
15 {
16 public const APP_NAME = 'Spout';
17 public const MIMETYPE = 'application/vnd.oasis.opendocument.spreadsheet';
18 public const META_INF_FOLDER_NAME = 'META-INF';
19 public const SHEETS_CONTENT_TEMP_FOLDER_NAME = 'worksheets-temp';
20 public const MANIFEST_XML_FILE_NAME = 'manifest.xml';
21 public const CONTENT_XML_FILE_NAME = 'content.xml';
22 public const META_XML_FILE_NAME = 'meta.xml';
23 public const MIMETYPE_FILE_NAME = 'mimetype';
24 public const STYLES_XML_FILE_NAME = 'styles.xml';
25 /** @var string Path to the root folder inside the temp folder where the files to create the ODS will be stored */
26 protected $rootFolder;
27 /** @var string Path to the "META-INF" folder inside the root folder */
28 protected $metaInfFolder;
29 /** @var string Path to the temp folder, inside the root folder, where specific sheets content will be written to */
30 protected $sheetsContentTempFolder;
31 /** @var ZipHelper Helper to perform tasks with Zip archive */
32 private $zipHelper;
33 /**
34 * @param string $baseFolderPath The path of the base folder where all the I/O can occur
35 * @param ZipHelper $zipHelper Helper to perform tasks with Zip archive
36 */
37 public function __construct($baseFolderPath, $zipHelper)
38 {
39 parent::__construct($baseFolderPath);
40 $this->zipHelper = $zipHelper;
41 }
42 /**
43 * @return string
44 */
45 public function getRootFolder()
46 {
47 return $this->rootFolder;
48 }
49 /**
50 * @return string
51 */
52 public function getSheetsContentTempFolder()
53 {
54 return $this->sheetsContentTempFolder;
55 }
56 /**
57 * Creates all the folders needed to create a ODS file, as well as the files that won't change.
58 *
59 * @throws \OpenSpout\Common\Exception\IOException If unable to create at least one of the base folders
60 */
61 public function createBaseFilesAndFolders()
62 {
63 $this->createRootFolder()->createMetaInfoFolderAndFile()->createSheetsContentTempFolder()->createMetaFile()->createMimetypeFile();
64 }
65 /**
66 * Creates the "content.xml" file under the root folder.
67 *
68 * @param WorksheetManager $worksheetManager
69 * @param StyleManager $styleManager
70 * @param Worksheet[] $worksheets
71 *
72 * @return FileSystemHelper
73 */
74 public function createContentFile($worksheetManager, $styleManager, $worksheets)
75 {
76 $contentXmlFileContents = <<<'EOD'
77 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
78 <office:document-content office:version="1.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:msoxl="http://schemas.microsoft.com/office/excel/formula" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xlink="http://www.w3.org/1999/xlink">
79 EOD;
80 $contentXmlFileContents .= $styleManager->getContentXmlFontFaceSectionContent();
81 $contentXmlFileContents .= $styleManager->getContentXmlAutomaticStylesSectionContent($worksheets);
82 $contentXmlFileContents .= '<office:body><office:spreadsheet>';
83 $this->createFileWithContents($this->rootFolder, self::CONTENT_XML_FILE_NAME, $contentXmlFileContents);
84 // Append sheets content to "content.xml"
85 $contentXmlFilePath = $this->rootFolder . '/' . self::CONTENT_XML_FILE_NAME;
86 $contentXmlHandle = \fopen($contentXmlFilePath, 'a');
87 foreach ($worksheets as $worksheet) {
88 // write the "<table:table>" node, with the final sheet's name
89 \fwrite($contentXmlHandle, $worksheetManager->getTableElementStartAsString($worksheet));
90 $worksheetFilePath = $worksheet->getFilePath();
91 $this->copyFileContentsToTarget($worksheetFilePath, $contentXmlHandle);
92 \fwrite($contentXmlHandle, '</table:table>');
93 }
94 $contentXmlFileContents = '</office:spreadsheet></office:body></office:document-content>';
95 \fwrite($contentXmlHandle, $contentXmlFileContents);
96 \fclose($contentXmlHandle);
97 return $this;
98 }
99 /**
100 * Deletes the temporary folder where sheets content was stored.
101 *
102 * @return FileSystemHelper
103 */
104 public function deleteWorksheetTempFolder()
105 {
106 $this->deleteFolderRecursively($this->sheetsContentTempFolder);
107 return $this;
108 }
109 /**
110 * Creates the "styles.xml" file under the root folder.
111 *
112 * @param StyleManager $styleManager
113 * @param int $numWorksheets Number of created worksheets
114 *
115 * @return FileSystemHelper
116 */
117 public function createStylesFile($styleManager, $numWorksheets)
118 {
119 $stylesXmlFileContents = $styleManager->getStylesXMLFileContent($numWorksheets);
120 $this->createFileWithContents($this->rootFolder, self::STYLES_XML_FILE_NAME, $stylesXmlFileContents);
121 return $this;
122 }
123 /**
124 * Zips the root folder and streams the contents of the zip into the given stream.
125 *
126 * @param resource $streamPointer Pointer to the stream to copy the zip
127 */
128 public function zipRootFolderAndCopyToStream($streamPointer)
129 {
130 $zip = $this->zipHelper->createZip($this->rootFolder);
131 $zipFilePath = $this->zipHelper->getZipFilePath($zip);
132 // In order to have the file's mime type detected properly, files need to be added
133 // to the zip file in a particular order.
134 // @see http://www.jejik.com/articles/2010/03/how_to_correctly_create_odf_documents_using_zip/
135 $this->zipHelper->addUncompressedFileToArchive($zip, $this->rootFolder, self::MIMETYPE_FILE_NAME);
136 $this->zipHelper->addFolderToArchive($zip, $this->rootFolder, ZipHelper::EXISTING_FILES_SKIP);
137 $this->zipHelper->closeArchiveAndCopyToStream($zip, $streamPointer);
138 // once the zip is copied, remove it
139 $this->deleteFile($zipFilePath);
140 }
141 /**
142 * Creates the folder that will be used as root.
143 *
144 * @throws \OpenSpout\Common\Exception\IOException If unable to create the folder
145 *
146 * @return FileSystemHelper
147 */
148 protected function createRootFolder()
149 {
150 $this->rootFolder = $this->createFolder($this->baseFolderRealPath, \uniqid('ods'));
151 return $this;
152 }
153 /**
154 * Creates the "META-INF" folder under the root folder as well as the "manifest.xml" file in it.
155 *
156 * @throws \OpenSpout\Common\Exception\IOException If unable to create the folder or the "manifest.xml" file
157 *
158 * @return FileSystemHelper
159 */
160 protected function createMetaInfoFolderAndFile()
161 {
162 $this->metaInfFolder = $this->createFolder($this->rootFolder, self::META_INF_FOLDER_NAME);
163 $this->createManifestFile();
164 return $this;
165 }
166 /**
167 * Creates the "manifest.xml" file under the "META-INF" folder (under root).
168 *
169 * @throws \OpenSpout\Common\Exception\IOException If unable to create the file
170 *
171 * @return FileSystemHelper
172 */
173 protected function createManifestFile()
174 {
175 $manifestXmlFileContents = <<<'EOD'
176 <?xml version="1.0" encoding="UTF-8"?>
177 <manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">
178 <manifest:file-entry manifest:full-path="/" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>
179 <manifest:file-entry manifest:full-path="styles.xml" manifest:media-type="text/xml"/>
180 <manifest:file-entry manifest:full-path="content.xml" manifest:media-type="text/xml"/>
181 <manifest:file-entry manifest:full-path="meta.xml" manifest:media-type="text/xml"/>
182 </manifest:manifest>
183 EOD;
184 $this->createFileWithContents($this->metaInfFolder, self::MANIFEST_XML_FILE_NAME, $manifestXmlFileContents);
185 return $this;
186 }
187 /**
188 * Creates the temp folder where specific sheets content will be written to.
189 * This folder is not part of the final ODS file and is only used to be able to jump between sheets.
190 *
191 * @throws \OpenSpout\Common\Exception\IOException If unable to create the folder
192 *
193 * @return FileSystemHelper
194 */
195 protected function createSheetsContentTempFolder()
196 {
197 $this->sheetsContentTempFolder = $this->createFolder($this->rootFolder, self::SHEETS_CONTENT_TEMP_FOLDER_NAME);
198 return $this;
199 }
200 /**
201 * Creates the "meta.xml" file under the root folder.
202 *
203 * @throws \OpenSpout\Common\Exception\IOException If unable to create the file
204 *
205 * @return FileSystemHelper
206 */
207 protected function createMetaFile()
208 {
209 $appName = self::APP_NAME;
210 $createdDate = (new \DateTime())->format(\DateTime::W3C);
211 $metaXmlFileContents = <<<EOD
212 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
213 <office:document-meta office:version="1.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink">
214 <office:meta>
215 <dc:creator>{$appName}</dc:creator>
216 <meta:creation-date>{$createdDate}</meta:creation-date>
217 <dc:date>{$createdDate}</dc:date>
218 </office:meta>
219 </office:document-meta>
220 EOD;
221 $this->createFileWithContents($this->rootFolder, self::META_XML_FILE_NAME, $metaXmlFileContents);
222 return $this;
223 }
224 /**
225 * Creates the "mimetype" file under the root folder.
226 *
227 * @throws \OpenSpout\Common\Exception\IOException If unable to create the file
228 *
229 * @return FileSystemHelper
230 */
231 protected function createMimetypeFile()
232 {
233 $this->createFileWithContents($this->rootFolder, self::MIMETYPE_FILE_NAME, self::MIMETYPE);
234 return $this;
235 }
236 /**
237 * Streams the content of the file at the given path into the target resource.
238 * Depending on which mode the target resource was created with, it will truncate then copy
239 * or append the content to the target file.
240 *
241 * @param string $sourceFilePath Path of the file whose content will be copied
242 * @param resource $targetResource Target resource that will receive the content
243 */
244 protected function copyFileContentsToTarget($sourceFilePath, $targetResource)
245 {
246 $sourceHandle = \fopen($sourceFilePath, 'r');
247 \stream_copy_to_stream($sourceHandle, $targetResource);
248 \fclose($sourceHandle);
249 }
250 }
251