-
Notifications
You must be signed in to change notification settings - Fork 428
/
FileCacheStorage.php
107 lines (90 loc) · 2.31 KB
/
FileCacheStorage.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<?php declare(strict_types = 1);
namespace PHPStan\Cache;
use Nette\Utils\Random;
class FileCacheStorage implements CacheStorage
{
/** @var string */
private $directory;
public function __construct(string $directory)
{
$this->directory = $directory;
}
private function makeDir(string $directory): void
{
if (is_dir($directory)) {
return;
}
$result = @mkdir($directory, 0777, true);
if ($result === false) {
clearstatcache();
if (is_dir($directory)) {
return;
}
$error = error_get_last();
throw new \InvalidArgumentException(sprintf('Failed to create directory "%s" (%s).', $this->directory, $error !== null ? $error['message'] : 'unknown cause'));
}
}
/**
* @param string $key
* @param string $variableKey
* @return mixed|null
*/
public function load(string $key, string $variableKey)
{
return (function (string $key, string $variableKey) {
$filePath = $this->getFilePath($key);
if (!is_file($filePath)) {
return null;
}
$cacheItem = require $filePath;
if (!$cacheItem instanceof CacheItem) {
return null;
}
if (!$cacheItem->isVariableKeyValid($variableKey)) {
return null;
}
return $cacheItem->getData();
})($key, $variableKey);
}
/**
* @param string $key
* @param string $variableKey
* @param mixed $data
* @return void
*/
public function save(string $key, string $variableKey, $data): void
{
$path = $this->getFilePath($key);
$this->makeDir(dirname($path));
$tmpPath = sprintf('%s/%s.tmp', $this->directory, Random::generate());
$tmpSuccess = @file_put_contents(
$tmpPath,
sprintf(
"<?php declare(strict_types = 1);\n\nreturn %s;",
var_export(new CacheItem($variableKey, $data), true)
)
);
if ($tmpSuccess === false) {
throw new \InvalidArgumentException(sprintf('Could not write data to cache file %s.', $tmpPath));
}
$renameSuccess = @rename($tmpPath, $path);
if ($renameSuccess) {
return;
}
@unlink($tmpPath);
if (DIRECTORY_SEPARATOR === '/' || !file_exists($path)) {
throw new \InvalidArgumentException(sprintf('Could not write data to cache file %s.', $path));
}
}
private function getFilePath(string $key): string
{
$keyHash = sha1($key);
return sprintf(
'%s/%s/%s/%s.php',
$this->directory,
substr($keyHash, 0, 2),
substr($keyHash, 2, 2),
$keyHash
);
}
}