blob: a9f1f466f528f550f36dd863c2225dae184aa102 [file] [log] [blame]
Matthias Andreas Benkard12a57352021-12-28 18:02:04 +01001<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Twig\Cache;
13
14/**
15 * Implements a cache on the filesystem.
16 *
17 * @author Andrew Tch <andrew@noop.lv>
18 */
19class FilesystemCache implements CacheInterface
20{
21 public const FORCE_BYTECODE_INVALIDATION = 1;
22
23 private $directory;
24 private $options;
25
26 public function __construct(string $directory, int $options = 0)
27 {
28 $this->directory = rtrim($directory, '\/').'/';
29 $this->options = $options;
30 }
31
32 public function generateKey(string $name, string $className): string
33 {
34 $hash = hash('sha256', $className);
35
36 return $this->directory.$hash[0].$hash[1].'/'.$hash.'.php';
37 }
38
39 public function load(string $key): void
40 {
41 if (is_file($key)) {
42 @include_once $key;
43 }
44 }
45
46 public function write(string $key, string $content): void
47 {
48 $dir = \dirname($key);
49 if (!is_dir($dir)) {
50 if (false === @mkdir($dir, 0777, true)) {
51 clearstatcache(true, $dir);
52 if (!is_dir($dir)) {
53 throw new \RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir));
54 }
55 }
56 } elseif (!is_writable($dir)) {
57 throw new \RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir));
58 }
59
60 $tmpFile = tempnam($dir, basename($key));
61 if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $key)) {
62 @chmod($key, 0666 & ~umask());
63
64 if (self::FORCE_BYTECODE_INVALIDATION == ($this->options & self::FORCE_BYTECODE_INVALIDATION)) {
65 // Compile cached file into bytecode cache
66 if (\function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN)) {
67 @opcache_invalidate($key, true);
68 } elseif (\function_exists('apc_compile_file')) {
69 apc_compile_file($key);
70 }
71 }
72
73 return;
74 }
75
76 throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $key));
77 }
78
79 public function getTimestamp(string $key): int
80 {
81 if (!is_file($key)) {
82 return 0;
83 }
84
85 return (int) @filemtime($key);
86 }
87}