PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 3.6.64
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v3.6.64
6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 3.6.65 All 196 releases
fluentform / app / Services / Spout / Writer / ODS / Helper / FileSystemHelper.php

FileSystemHelper.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 3.6.64, at app/Services/Spout/Writer/ODS/Helper/FileSystemHelper.php

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