PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.5.3
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.5.3
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 / XLSX / Manager / SharedStringsCaching / FileBasedStrategy.php

FileBasedStrategy.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.5.3, at vendor/openspout/openspout/src/Reader/XLSX/Manager/SharedStringsCaching/FileBasedStrategy.php

161 lines 6.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\XLSX\Manager\SharedStringsCaching;
4
5 use FluentCart\OpenSpout\Reader\Exception\SharedStringNotFoundException;
6 use FluentCart\OpenSpout\Reader\XLSX\Creator\HelperFactory;
7 /**
8 * This class implements the file-based caching strategy for shared strings.
9 * Shared strings are stored in small files (with a max number of strings per file).
10 * This strategy is slower than an in-memory strategy but is used to avoid out of memory crashes.
11 */
12 class FileBasedStrategy implements CachingStrategyInterface
13 {
14 /** Value to use to escape the line feed character ("\n") */
15 public const ESCAPED_LINE_FEED_CHARACTER = '_x000A_';
16 /** @var \OpenSpout\Common\Helper\GlobalFunctionsHelper Helper to work with global functions */
17 protected $globalFunctionsHelper;
18 /** @var \OpenSpout\Common\Helper\FileSystemHelper Helper to perform file system operations */
19 protected $fileSystemHelper;
20 /** @var string Temporary folder where the temporary files will be created */
21 protected $tempFolder;
22 /**
23 * @var int Maximum number of strings that can be stored in one temp file
24 *
25 * @see CachingStrategyFactory::MAX_NUM_STRINGS_PER_TEMP_FILE
26 */
27 protected $maxNumStringsPerTempFile;
28 /** @var null|resource Pointer to the last temp file a shared string was written to */
29 protected $tempFilePointer;
30 /**
31 * @var string Path of the temporary file whose contents is currently stored in memory
32 *
33 * @see CachingStrategyFactory::MAX_NUM_STRINGS_PER_TEMP_FILE
34 */
35 protected $inMemoryTempFilePath;
36 /**
37 * @var array Contents of the temporary file that was last read
38 *
39 * @see CachingStrategyFactory::MAX_NUM_STRINGS_PER_TEMP_FILE
40 */
41 protected $inMemoryTempFileContents;
42 /**
43 * @param string $tempFolder Temporary folder where the temporary files to store shared strings will be stored
44 * @param int $maxNumStringsPerTempFile Maximum number of strings that can be stored in one temp file
45 * @param HelperFactory $helperFactory Factory to create helpers
46 */
47 public function __construct($tempFolder, $maxNumStringsPerTempFile, $helperFactory)
48 {
49 $this->fileSystemHelper = $helperFactory->createFileSystemHelper($tempFolder);
50 $this->tempFolder = $this->fileSystemHelper->createFolder($tempFolder, \uniqid('sharedstrings'));
51 $this->maxNumStringsPerTempFile = $maxNumStringsPerTempFile;
52 $this->globalFunctionsHelper = $helperFactory->createGlobalFunctionsHelper();
53 $this->tempFilePointer = null;
54 }
55 /**
56 * Adds the given string to the cache.
57 *
58 * @param string $sharedString The string to be added to the cache
59 * @param int $sharedStringIndex Index of the shared string in the sharedStrings.xml file
60 */
61 public function addStringForIndex($sharedString, $sharedStringIndex)
62 {
63 $tempFilePath = $this->getSharedStringTempFilePath($sharedStringIndex);
64 if (!$this->globalFunctionsHelper->file_exists($tempFilePath)) {
65 if ($this->tempFilePointer) {
66 $this->globalFunctionsHelper->fclose($this->tempFilePointer);
67 }
68 $this->tempFilePointer = $this->globalFunctionsHelper->fopen($tempFilePath, 'w');
69 }
70 // The shared string retrieval logic expects each cell data to be on one line only
71 // Encoding the line feed character allows to preserve this assumption
72 $lineFeedEncodedSharedString = $this->escapeLineFeed($sharedString);
73 $this->globalFunctionsHelper->fwrite($this->tempFilePointer, $lineFeedEncodedSharedString . \PHP_EOL);
74 }
75 /**
76 * Closes the cache after the last shared string was added.
77 * This prevents any additional string from being added to the cache.
78 */
79 public function closeCache()
80 {
81 // close pointer to the last temp file that was written
82 if ($this->tempFilePointer) {
83 $this->globalFunctionsHelper->fclose($this->tempFilePointer);
84 }
85 }
86 /**
87 * Returns the string located at the given index from the cache.
88 *
89 * @param int $sharedStringIndex Index of the shared string in the sharedStrings.xml file
90 *
91 * @throws \OpenSpout\Reader\Exception\SharedStringNotFoundException If no shared string found for the given index
92 *
93 * @return string The shared string at the given index
94 */
95 public function getStringAtIndex($sharedStringIndex)
96 {
97 $tempFilePath = $this->getSharedStringTempFilePath($sharedStringIndex);
98 $indexInFile = $sharedStringIndex % $this->maxNumStringsPerTempFile;
99 if (!$this->globalFunctionsHelper->file_exists($tempFilePath)) {
100 throw new SharedStringNotFoundException("Shared string temp file not found: {$tempFilePath} ; for index: {$sharedStringIndex}");
101 }
102 if ($this->inMemoryTempFilePath !== $tempFilePath) {
103 $this->inMemoryTempFileContents = \explode(\PHP_EOL, $this->globalFunctionsHelper->file_get_contents($tempFilePath));
104 $this->inMemoryTempFilePath = $tempFilePath;
105 }
106 $sharedString = null;
107 // Using isset here because it is way faster than array_key_exists...
108 if (isset($this->inMemoryTempFileContents[$indexInFile])) {
109 $escapedSharedString = $this->inMemoryTempFileContents[$indexInFile];
110 $sharedString = $this->unescapeLineFeed($escapedSharedString);
111 }
112 if (null === $sharedString) {
113 throw new SharedStringNotFoundException("Shared string not found for index: {$sharedStringIndex}");
114 }
115 return \rtrim($sharedString, \PHP_EOL);
116 }
117 /**
118 * Destroys the cache, freeing memory and removing any created artifacts.
119 */
120 public function clearCache()
121 {
122 if ($this->tempFolder) {
123 $this->fileSystemHelper->deleteFolderRecursively($this->tempFolder);
124 }
125 }
126 /**
127 * Returns the path for the temp file that should contain the string for the given index.
128 *
129 * @param int $sharedStringIndex Index of the shared string in the sharedStrings.xml file
130 *
131 * @return string The temp file path for the given index
132 */
133 protected function getSharedStringTempFilePath($sharedStringIndex)
134 {
135 $numTempFile = (int) ($sharedStringIndex / $this->maxNumStringsPerTempFile);
136 return $this->tempFolder . '/sharedstrings' . $numTempFile;
137 }
138 /**
139 * Escapes the line feed characters (\n).
140 *
141 * @param string $unescapedString
142 *
143 * @return string
144 */
145 private function escapeLineFeed($unescapedString)
146 {
147 return \str_replace("\n", self::ESCAPED_LINE_FEED_CHARACTER, $unescapedString);
148 }
149 /**
150 * Unescapes the line feed characters (\n).
151 *
152 * @param string $escapedString
153 *
154 * @return string
155 */
156 private function unescapeLineFeed($escapedString)
157 {
158 return \str_replace(self::ESCAPED_LINE_FEED_CHARACTER, "\n", $escapedString);
159 }
160 }
161