Passed
Pull Request — master (#178)
by
unknown
02:58
created

ViewCache::delete()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 5
rs 10
1
<?php
2
3
namespace Quantum\Libraries\ResourceCache;
4
5
use Quantum\Libraries\Storage\FileSystem;
6
use Quantum\Exceptions\DiException;
7
use ReflectionException;
8
use voku\helper\HtmlMin;
9
use Quantum\Di\Di;
10
use Exception;
11
12
class ViewCache
13
{
14
	/**
15
	 * @var string
16
	 */
17
	private $cacheDir;
18
19
	/**
20
	 * @var string
21
	 */
22
	private $mimeType = '.tmp';
23
24
	/**
25
	 * @var int
26
	 */
27
	private $ttl;
28
29
	/**
30
	 * @var object
31
	 */
32
	private $fs;
33
34
	/**
35
	 * @var ViewCache
36
	 */
37
	private static $instance = null;
38
39
	public static function getInstance(): ViewCache
40
	{
41
		if (self::$instance === null) {
42
			self::$instance = new self();
43
		}
44
45
		return self::$instance;
46
	}
47
48
	/**
49
	 * @throws DiException
50
	 * @throws ReflectionException
51
	 * @throws Exception
52
	 */
53
	public function __construct()
54
	{
55
		$this->fs = Di::get(FileSystem::class);
56
57
		if (!config()->has('view_cache')) {
58
			throw new Exception('The config "view_cache" does not exists.');
59
		}
60
61
		$this->cacheDir = $this->getCacheDir();
62
63
		$this->ttl = is_int(config()->get('view_cache.ttl')) ? config()->get('view_cache.ttl') : 300;
64
65
		if (!$this->fs->isDirectory($this->cacheDir)) {
66
			mkdir($this->cacheDir, 0777, true);
67
		}
68
	}
69
70
	/**
71
	 * @param string $key
72
	 * @param string $content
73
	 * @param string $sessionId
74
	 * @return ViewCache
75
	 */
76
	public function set(string $key, string $content, string $sessionId): ViewCache
77
	{
78
		if (config()->has('view_cache.minify')) {
79
			$content = $this->minify($content);
80
		}
81
82
		$cacheFile = $this->getCacheFile($key, $sessionId);
83
		$this->fs->put($cacheFile, $content);
84
85
		return $this;
86
	}
87
88
	/**
89
	 * @param string $key
90
	 * @param string $sessionId
91
	 * @param int $ttl
92
	 * @return mixed|null
93
	 */
94
	public function get(string $key, string $sessionId, int $ttl): ?string
0 ignored issues
show
Unused Code introduced by
The parameter $ttl is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

94
	public function get(string $key, string $sessionId, /** @scrutinizer ignore-unused */ int $ttl): ?string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
95
	{
96
		$cacheFile = $this->getCacheFile($key, $sessionId);
97
		if (!$this->fs->exists($cacheFile)) {
98
			return null;
99
		}
100
101
		return $this->fs->get($cacheFile);
102
	}
103
104
	/**
105
	 * @param string $key
106
	 * @param string $sessionId
107
	 * @return void
108
	 */
109
	public function delete(string $key, string $sessionId): void
110
	{
111
		$cacheFile = $this->getCacheFile($key, $sessionId);
112
		if ($this->fs->exists($cacheFile)) {
113
			$this->fs->remove($cacheFile);
114
		}
115
	}
116
117
	/**
118
	 * @param string $key
119
	 * @param string $sessionId
120
	 * @param int|null $ttl
121
	 * @return bool
122
	 */
123
	public function exists(string $key, string $sessionId, int $ttl = null): bool
124
	{
125
		if (!$ttl){
0 ignored issues
show
Bug Best Practice introduced by
The expression $ttl of type integer|null is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
126
			$ttl = $this->ttl;
127
		}
128
129
		$cacheFile = $this->getCacheFile($key, $sessionId);
130
131
		if (!$this->fs->exists($cacheFile) || $this->isExpired($cacheFile, $ttl)) {
132
			return false;
133
		}
134
135
		return true;
136
	}
137
138
	/**
139
	 * @param $cacheFile
140
	 * @param int|null $ttl
141
	 * @return bool
142
	 */
143
	public function isExpired($cacheFile, int $ttl = null): bool
144
	{
145
		if (!$ttl){
0 ignored issues
show
Bug Best Practice introduced by
The expression $ttl of type integer|null is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
146
			$ttl = $this->ttl;
147
		}
148
149
		if (time() > ($this->fs->lastModified($cacheFile) + $ttl)) {
150
			$this->fs->remove($cacheFile);
151
			return true;
152
		}
153
154
		return false;
155
	}
156
157
	/**
158
	 * @return bool
159
	 */
160
	public function isEnabled(): bool
161
	{
162
		return is_bool(config()->get('resource_cache')) ? config()->get('resource_cache') : false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return is_bool(config()-...esource_cache') : false could return the type null which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
163
	}
164
165
	/**
166
	 * @return int
167
	 */
168
	public function getTtl(): int
169
	{
170
		return $this->ttl;
171
	}
172
173
	/**
174
	 * @return string
175
	 */
176
	private function getCacheDir(): string
177
	{
178
		$configCacheDir = config()->get('view_cache.cache_dir', 'cache');
179
180
		$cacheDir = base_dir() . DS . $configCacheDir . DS . 'views' . DS;
181
182
		if ($module = current_module()) {
183
			$cacheDir = base_dir() . DS . $configCacheDir . DS . 'views' . DS . strtolower($module) . DS;
184
		}
185
186
		return $cacheDir;
187
	}
188
189
	/**
190
	 * @param string $key
191
	 * @param string $sessionId
192
	 * @return string
193
	 */
194
	private function getCacheFile(string $key, string $sessionId): string
195
	{
196
		return $this->cacheDir . md5($key . $sessionId) . $this->mimeType;
197
	}
198
199
	/**
200
	 * @param string $content
201
	 * @return string
202
	 */
203
	private function minify(string $content): string
204
	{
205
		return (new HtmlMin())->minify($content);
206
	}
207
}