‪TYPO3CMS  9.5
SimpleFileBackend.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
26 
32 {
33  const ‪SEPARATOR = '^';
34  const ‪EXPIRYTIME_FORMAT = 'YmdHis';
36  const ‪DATASIZE_DIGITS = 10;
42  protected ‪$cacheDirectory = '';
43 
52  protected ‪$temporaryCacheDirectory = '';
53 
59  protected ‪$cacheEntryFileExtension = '';
60 
64  protected ‪$cacheEntryIdentifiers = [];
65 
69  protected ‪$frozen = false;
70 
79  {
80  parent::setCache(‪$cache);
81  if (empty($this->temporaryCacheDirectory)) {
82  // If no cache directory was given with cacheDirectory
83  // configuration option, set it to a path below var/ folder
85  } else {
87  }
88  $codeOrData = ‪$cache instanceof ‪PhpFrontend ? 'code' : 'data';
89  $finalCacheDirectory = ‪$temporaryCacheDirectory . 'cache/' . $codeOrData . '/' . $this->cacheIdentifier . '/';
90  if (!is_dir($finalCacheDirectory)) {
91  $this->‪createFinalCacheDirectory($finalCacheDirectory);
92  }
93  unset($this->temporaryCacheDirectory);
94  $this->cacheDirectory = $finalCacheDirectory;
95  $this->cacheEntryFileExtension = ‪$cache instanceof ‪PhpFrontend ? '.php' : '';
96  if (strlen($this->cacheDirectory) + 23 > PHP_MAXPATHLEN) {
97  throw new ‪Exception('The length of the temporary cache file path "' . $this->cacheDirectory . '" exceeds the ' . 'maximum path length of ' . (PHP_MAXPATHLEN - 23) . '. Please consider ' . 'setting the temporaryDirectoryBase option to a shorter path.', 1248710426);
98  }
99  }
100 
115  {
116  // Skip handling if directory is a stream ressource
117  // This is used by unit tests with vfs:// directories
118  if (strpos(‪$cacheDirectory, '://')) {
119  $this->temporaryCacheDirectory = ‪$cacheDirectory;
120  return;
121  }
122  $documentRoot = ‪Environment::getProjectPath() . '/';
123  if ($open_basedir = ini_get('open_basedir')) {
125  $delimiter = ';';
126  ‪$cacheDirectory = str_replace('\\', '/', ‪$cacheDirectory);
127  if (!preg_match('/[A-Z]:/', substr(‪$cacheDirectory, 0, 2))) {
129  }
130  } else {
131  $delimiter = ':';
132  if (‪$cacheDirectory[0] !== '/') {
133  // relative path to cache directory.
135  }
136  }
137  $basedirs = explode($delimiter, $open_basedir);
138  $cacheDirectoryInBaseDir = false;
139  foreach ($basedirs as $basedir) {
141  $basedir = str_replace('\\', '/', $basedir);
142  }
143  if ($basedir[strlen($basedir) - 1] !== '/') {
144  $basedir .= '/';
145  }
146  if (GeneralUtility::isFirstPartOfStr(‪$cacheDirectory, $basedir)) {
147  $documentRoot = $basedir;
148  ‪$cacheDirectory = str_replace($basedir, '', ‪$cacheDirectory);
149  $cacheDirectoryInBaseDir = true;
150  break;
151  }
152  }
153  if (!$cacheDirectoryInBaseDir) {
154  throw new Exception(
155  'Open_basedir restriction in effect. The directory "' . ‪$cacheDirectory . '" is not in an allowed path.',
156  1476045417
157  );
158  }
159  } else {
160  if (‪$cacheDirectory[0] === '/') {
161  // Absolute path to cache directory.
162  $documentRoot = '';
163  }
165  if (!empty($documentRoot) && strpos(‪$cacheDirectory, $documentRoot) === 0) {
166  $documentRoot = '';
167  }
168  }
169  }
170  // After this point all paths have '/' as directory separator
171  if (‪$cacheDirectory[strlen(‪$cacheDirectory) - 1] !== '/') {
172  ‪$cacheDirectory .= '/';
173  }
174  $this->temporaryCacheDirectory = $documentRoot . ‪$cacheDirectory;
175  }
176 
183  protected function ‪createFinalCacheDirectory($finalCacheDirectory)
184  {
185  try {
186  GeneralUtility::mkdir_deep($finalCacheDirectory);
187  } catch (\RuntimeException $e) {
188  throw new Exception('The directory "' . $finalCacheDirectory . '" can not be created.', 1303669848, $e);
189  }
190  if (!is_writable($finalCacheDirectory)) {
191  throw new Exception('The directory "' . $finalCacheDirectory . '" is not writable.', 1203965200);
192  }
193  }
194 
200  public function ‪getCacheDirectory()
201  {
203  }
204 
216  public function set($entryIdentifier, $data, array $tags = [], $lifetime = null)
217  {
218  if (!is_string($data)) {
219  throw new InvalidDataException('The specified data is of type "' . gettype($data) . '" but a string is expected.', 1334756734);
220  }
221  if ($entryIdentifier !== ‪PathUtility::basename($entryIdentifier)) {
222  throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1334756735);
223  }
224  if ($entryIdentifier === '') {
225  throw new \InvalidArgumentException('The specified entry identifier must not be empty.', 1334756736);
226  }
227  $temporaryCacheEntryPathAndFilename = $this->cacheDirectory . ‪StringUtility::getUniqueId() . '.temp';
228  $result = file_put_contents($temporaryCacheEntryPathAndFilename, $data);
229  GeneralUtility::fixPermissions($temporaryCacheEntryPathAndFilename);
230  if ($result === false) {
231  throw new Exception('The temporary cache file "' . $temporaryCacheEntryPathAndFilename . '" could not be written.', 1334756737);
232  }
233  $cacheEntryPathAndFilename = $this->cacheDirectory . $entryIdentifier . ‪$this->cacheEntryFileExtension;
234  rename($temporaryCacheEntryPathAndFilename, $cacheEntryPathAndFilename);
235  if ($this->cacheEntryFileExtension === '.php') {
236  GeneralUtility::makeInstance(OpcodeCacheService::class)->clearAllActive($cacheEntryPathAndFilename);
237  }
238  }
239 
247  public function get($entryIdentifier)
248  {
249  if ($entryIdentifier !== ‪PathUtility::basename($entryIdentifier)) {
250  throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1334756877);
251  }
252  $pathAndFilename = $this->cacheDirectory . $entryIdentifier . ‪$this->cacheEntryFileExtension;
253  if (!file_exists($pathAndFilename)) {
254  return false;
255  }
256  return file_get_contents($pathAndFilename);
257  }
258 
266  public function ‪has($entryIdentifier)
267  {
268  if ($entryIdentifier !== ‪PathUtility::basename($entryIdentifier)) {
269  throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1334756878);
270  }
271  return file_exists($this->cacheDirectory . $entryIdentifier . $this->cacheEntryFileExtension);
272  }
273 
282  public function remove($entryIdentifier)
283  {
284  if ($entryIdentifier !== ‪PathUtility::basename($entryIdentifier)) {
285  throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1334756960);
286  }
287  if ($entryIdentifier === '') {
288  throw new \InvalidArgumentException('The specified entry identifier must not be empty.', 1334756961);
289  }
290  try {
291  unlink($this->cacheDirectory . $entryIdentifier . $this->cacheEntryFileExtension);
292  } catch (\Exception $e) {
293  return false;
294  }
295  return true;
296  }
297 
301  public function ‪flush()
302  {
303  GeneralUtility::flushDirectory($this->cacheDirectory, true);
304  }
305 
313  protected function ‪isCacheFileExpired($cacheEntryPathAndFilename)
314  {
315  return file_exists($cacheEntryPathAndFilename) === false;
316  }
317 
321  public function ‪collectGarbage()
322  {
323  }
324 
331  protected function ‪findCacheFilesByIdentifier($entryIdentifier)
332  {
333  $pathAndFilename = $this->cacheDirectory . $entryIdentifier . ‪$this->cacheEntryFileExtension;
334  return file_exists($pathAndFilename) ? [$pathAndFilename] : false;
335  }
336 
344  public function ‪requireOnce($entryIdentifier)
345  {
346  $pathAndFilename = $this->cacheDirectory . $entryIdentifier . ‪$this->cacheEntryFileExtension;
347  if ($entryIdentifier !== ‪PathUtility::basename($entryIdentifier)) {
348  throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1282073037);
349  }
350  return file_exists($pathAndFilename) ? require_once $pathAndFilename : false;
351  }
352 
360  public function require(string $entryIdentifier)
361  {
362  $pathAndFilename = $this->cacheDirectory . $entryIdentifier . ‪$this->cacheEntryFileExtension;
363  if ($entryIdentifier !== ‪PathUtility::basename($entryIdentifier)) {
364  throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1532528267);
365  }
366  return file_exists($pathAndFilename) ? require $pathAndFilename : false;
367  }
368 }
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\flush
‪flush()
Definition: SimpleFileBackend.php:296
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:23
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\$cacheEntryFileExtension
‪string $cacheEntryFileExtension
Definition: SimpleFileBackend.php:56
‪TYPO3\CMS\Core\Cache\Frontend\PhpFrontend
Definition: PhpFrontend.php:24
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\$cacheDirectory
‪string $cacheDirectory
Definition: SimpleFileBackend.php:41
‪TYPO3\CMS\Core\Core\Environment\isWindows
‪static bool isWindows()
Definition: Environment.php:266
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\has
‪bool has($entryIdentifier)
Definition: SimpleFileBackend.php:261
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\createFinalCacheDirectory
‪createFinalCacheDirectory($finalCacheDirectory)
Definition: SimpleFileBackend.php:178
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\findCacheFilesByIdentifier
‪mixed findCacheFilesByIdentifier($entryIdentifier)
Definition: SimpleFileBackend.php:326
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\$cacheEntryIdentifiers
‪array $cacheEntryIdentifiers
Definition: SimpleFileBackend.php:60
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\collectGarbage
‪collectGarbage()
Definition: SimpleFileBackend.php:316
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\setCacheDirectory
‪setCacheDirectory($cacheDirectory)
Definition: SimpleFileBackend.php:109
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\$temporaryCacheDirectory
‪string $temporaryCacheDirectory
Definition: SimpleFileBackend.php:50
‪TYPO3\CMS\Core\Utility\PathUtility\basename
‪static string basename($path)
Definition: PathUtility.php:164
‪TYPO3\CMS\Core\Cache\Backend\PhpCapableBackendInterface
Definition: PhpCapableBackendInterface.php:22
‪TYPO3\CMS\Core\Core\Environment\getProjectPath
‪static string getProjectPath()
Definition: Environment.php:142
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\setCache
‪setCache(FrontendInterface $cache)
Definition: SimpleFileBackend.php:73
‪TYPO3\CMS\Core\Cache\Exception
Definition: DuplicateIdentifierException.php:2
‪TYPO3\CMS\Core\Cache\Exception\InvalidDataException
Definition: InvalidDataException.php:21
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend
Definition: SimpleFileBackend.php:32
‪TYPO3\CMS\Core\Cache\Backend\AbstractBackend\$cache
‪TYPO3 CMS Core Cache Frontend FrontendInterface $cache
Definition: AbstractBackend.php:35
‪TYPO3\CMS\Core\Service\OpcodeCacheService
Definition: OpcodeCacheService.php:24
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\requireOnce
‪mixed requireOnce($entryIdentifier)
Definition: SimpleFileBackend.php:339
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\EXPIRYTIME_FORMAT
‪const EXPIRYTIME_FORMAT
Definition: SimpleFileBackend.php:34
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:21
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\DATASIZE_DIGITS
‪const DATASIZE_DIGITS
Definition: SimpleFileBackend.php:36
‪TYPO3\CMS\Core\Utility\StringUtility\getUniqueId
‪static string getUniqueId($prefix='')
Definition: StringUtility.php:91
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\EXPIRYTIME_LENGTH
‪const EXPIRYTIME_LENGTH
Definition: SimpleFileBackend.php:35
‪TYPO3\CMS\Core\Cache\Backend\AbstractBackend
Definition: AbstractBackend.php:26
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:39
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\getCacheDirectory
‪string getCacheDirectory()
Definition: SimpleFileBackend.php:195
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\SEPARATOR
‪const SEPARATOR
Definition: SimpleFileBackend.php:33
‪TYPO3\CMS\Core\Cache\Backend
Definition: AbstractBackend.php:2
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\isCacheFileExpired
‪bool isCacheFileExpired($cacheEntryPathAndFilename)
Definition: SimpleFileBackend.php:308
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:21
‪TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend\$frozen
‪bool $frozen
Definition: SimpleFileBackend.php:64
‪TYPO3\CMS\Core\Cache\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Core\Core\Environment\getVarPath
‪static string getVarPath()
Definition: Environment.php:165