This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php declare(strict_types=1); |
||
2 | |||
3 | namespace Compolomus\Cache; |
||
4 | |||
5 | use DateInterval; |
||
6 | use DateTime; |
||
7 | use FilesystemIterator; |
||
8 | use InvalidArgumentException; |
||
9 | use LogicException; |
||
10 | use RecursiveDirectoryIterator; |
||
11 | use RecursiveIteratorIterator; |
||
12 | use RuntimeException; |
||
13 | use SplFileObject; |
||
14 | |||
15 | class FileCache |
||
16 | { |
||
17 | |||
18 | private $cachePath; |
||
19 | |||
20 | /** |
||
21 | * FileCache constructor. |
||
22 | * @param null|string $cachePath |
||
23 | */ |
||
24 | 2 | public function __construct(?string $cachePath = null) |
|
25 | { |
||
26 | 2 | $this->cachePath = $cachePath ?? sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'cache'; |
|
27 | 2 | is_dir($this->cachePath) ?: mkdir($this->cachePath, 0775, true); |
|
28 | 2 | } |
|
29 | |||
30 | /** |
||
31 | * Clear cache directory |
||
32 | * |
||
33 | * @return bool |
||
34 | */ |
||
35 | 1 | public function clear(): bool |
|
36 | { |
||
37 | 1 | $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->cachePath, |
|
38 | 1 | FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST); |
|
39 | 1 | $iterator = iterator_count($iterator) ? $iterator : []; |
|
40 | |||
41 | 1 | foreach ($iterator as $item) { |
|
42 | 1 | $item->isDir() && !$item->isLink() ? rmdir($item->getPathname()) : unlink($item->getPathname()); |
|
43 | } |
||
44 | |||
45 | 1 | return rmdir($this->cachePath); |
|
46 | } |
||
47 | |||
48 | /** |
||
49 | * @param array $keys |
||
50 | * @param mixed $default |
||
51 | * @return array |
||
52 | * @throws LogicException |
||
53 | * @throws RuntimeException |
||
54 | * @throws InvalidArgumentException |
||
55 | */ |
||
56 | 1 | public function getMultiple(array $keys, $default = null): array |
|
57 | { |
||
58 | 1 | $values = []; |
|
59 | 1 | foreach ($keys as $key) { |
|
60 | 1 | $values[$key] = $this->get($key) ?: $default; |
|
61 | } |
||
62 | |||
63 | 1 | return $values; |
|
64 | } |
||
65 | |||
66 | /** |
||
67 | * @param string $key |
||
68 | * @param null $default |
||
69 | * @return mixed |
||
70 | * @throws LogicException |
||
71 | * @throws RuntimeException |
||
72 | * @throws InvalidArgumentException |
||
73 | */ |
||
74 | 2 | public function get(string $key, $default = null) |
|
75 | { |
||
76 | 2 | $keyFile = $this->getFilename($key); |
|
77 | 2 | $file = file_exists($keyFile) && $this->has($key) ? realpath($keyFile) : null; |
|
78 | |||
79 | 2 | return $file ? unserialize((new SplFileObject($file))->fread(filesize($file)), |
|
80 | 2 | ['allowed_classes' => false]) : $default; |
|
81 | } |
||
82 | |||
83 | /** |
||
84 | * @param string $key |
||
85 | * @return string |
||
86 | * @throws InvalidArgumentException |
||
87 | */ |
||
88 | 6 | private function getFilename(string $key): string |
|
89 | { |
||
90 | 6 | $this->validateKey($key); |
|
91 | 6 | $sha1 = sha1($key); |
|
92 | |||
93 | 6 | return $this->cachePath . DIRECTORY_SEPARATOR |
|
94 | 6 | . substr($sha1, 0, 2) . DIRECTORY_SEPARATOR |
|
95 | 6 | . substr($sha1, 2, 2) . DIRECTORY_SEPARATOR |
|
96 | 6 | . $sha1 . '.cache'; |
|
97 | } |
||
98 | |||
99 | /** |
||
100 | * @param $key |
||
101 | * @return bool |
||
102 | * @throws InvalidArgumentException |
||
103 | */ |
||
104 | 6 | private function validateKey(string $key): bool |
|
105 | { |
||
106 | 6 | if (preg_match('#[{}()/\\\@:]#', $key)) { |
|
107 | 1 | throw new InvalidArgumentException('Can\'t validate the specified key (' . $key . ')'); |
|
108 | } |
||
109 | |||
110 | 6 | return true; |
|
111 | } |
||
112 | |||
113 | /** |
||
114 | * Isset and life item |
||
115 | * |
||
116 | * @param string $key |
||
117 | * @return bool |
||
118 | * @throws InvalidArgumentException |
||
119 | */ |
||
120 | 3 | public function has(string $key): bool |
|
121 | { |
||
122 | 3 | $filename = $this->getFilename($key); |
|
123 | 3 | if (!file_exists($filename)) { |
|
124 | 1 | return false; |
|
125 | } |
||
126 | 3 | if ($this->isLife(filemtime($filename))) { |
|
127 | 1 | $this->delete($key); |
|
128 | 1 | return false; |
|
129 | } |
||
130 | |||
131 | 3 | return true; |
|
132 | } |
||
133 | |||
134 | /** |
||
135 | * @param $ttl int |
||
136 | * @return bool |
||
137 | */ |
||
138 | 3 | private function isLife($ttl): bool |
|
139 | { |
||
140 | 3 | return $ttl < time(); |
|
141 | } |
||
142 | |||
143 | /** |
||
144 | * @param string $key |
||
145 | * @return bool |
||
146 | * @throws InvalidArgumentException |
||
147 | */ |
||
148 | 2 | public function delete($key): bool |
|
149 | { |
||
150 | 2 | return @unlink($this->getFilename($key)); |
|
151 | } |
||
152 | |||
153 | /** |
||
154 | * @param array $keys |
||
155 | * @param int $ttl |
||
156 | * @throws InvalidArgumentException |
||
157 | * @throws LogicException |
||
158 | * @throws RuntimeException |
||
159 | * @return bool |
||
160 | */ |
||
161 | 1 | public function setMultiple(array $keys, $ttl = null): bool |
|
162 | { |
||
163 | 1 | $status = []; |
|
164 | 1 | foreach ($keys as $key => $value) { |
|
165 | 1 | $status[$key] = $this->set($key, $value, $ttl); |
|
166 | } |
||
167 | |||
168 | 1 | return !\in_array(false, $status, true); |
|
169 | } |
||
170 | |||
171 | /** |
||
172 | * @param string $key |
||
173 | * @param mixed $value |
||
174 | * @param null|int|\DateInterval $ttl |
||
175 | * @throws InvalidArgumentException |
||
176 | * @throws LogicException |
||
177 | * @throws RuntimeException |
||
178 | * @return bool |
||
179 | */ |
||
180 | 3 | public function set(string $key, $value, $ttl = null): bool |
|
181 | { |
||
182 | 3 | $file = $this->getFilename($key); |
|
183 | 3 | $dir = \dirname($file); |
|
184 | 3 | is_dir($dir) ?: mkdir($dir, 0775, true); |
|
185 | |||
186 | switch ($ttl) { |
||
187 | 3 | case (null === $ttl): |
|
188 | default: |
||
189 | // 1 Year |
||
190 | 1 | $ttl = time() + 31536000; |
|
191 | 1 | break; |
|
192 | 3 | case (\is_int($ttl) && $ttl > 0): |
|
0 ignored issues
–
show
|
|||
193 | 3 | $ttl += time(); |
|
194 | 3 | break; |
|
195 | 1 | case ($ttl instanceof DateInterval): |
|
196 | 1 | $ttl = (new DateTime())->add($ttl)->getTimestamp(); |
|
197 | } |
||
198 | |||
199 | 3 | $data = new SplFileObject($file, 'wb'); |
|
200 | 3 | $data->fwrite(serialize($value)); |
|
201 | 3 | return touch($file, $ttl); |
|
202 | } |
||
203 | |||
204 | /** |
||
205 | * @param array $keys |
||
206 | * @return bool |
||
207 | * @throws InvalidArgumentException |
||
208 | */ |
||
209 | 1 | public function deleteMultiple(array $keys): bool |
|
210 | { |
||
211 | 1 | $status = []; |
|
212 | 1 | foreach ($keys as $key) { |
|
213 | 1 | $status[] = $this->delete($key); |
|
214 | } |
||
215 | |||
216 | 1 | return !\in_array(false, $status, true); |
|
217 | } |
||
218 | } |
||
219 |
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return
,die
orexit
statements that have been added for debug purposes.In the above example, the last
return false
will never be executed, because a return statement has already been met in every possible execution path.