Passed
Push — master ( d95688...5c1276 )
by smiley
01:47
created

FileCacheDriver::getFilepath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Class FileCacheDriver
4
 *
5
 * @filesource   FileCacheDriver.php
6
 * @created      25.05.2017
7
 * @package      chillerlan\SimpleCache\Drivers
8
 * @author       Smiley <[email protected]>
9
 * @copyright    2017 Smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\SimpleCache\Drivers;
14
15
use chillerlan\SimpleCache\CacheException;
16
use chillerlan\Traits\ImmutableSettingsInterface;
17
use FilesystemIterator, RecursiveDirectoryIterator, RecursiveIteratorIterator, stdClass;
18
19
class FileCacheDriver extends CacheDriverAbstract{
20
21
	/**
22
	 * @var string
23
	 */
24
	protected $cachedir;
25
26
	/**
27
	 * FileCacheDriver constructor.
28
	 *
29
	 * @param \chillerlan\Traits\ImmutableSettingsInterface|null $options
30
	 *
31
	 * @throws \chillerlan\SimpleCache\CacheException
32
	 */
33
	public function __construct(ImmutableSettingsInterface $options = null){
34
		parent::__construct($options);
35
36
		$this->cachedir = rtrim($this->options->cacheFilestorage, '/\\').DIRECTORY_SEPARATOR;
37
38
		if(!is_dir($this->cachedir)){
39
			$msg = 'invalid cachedir "'.$this->cachedir.'"';
40
41
			$this->logger->error($msg);
42
			throw new CacheException($msg);
43
		}
44
45
		if(!is_writable($this->cachedir)){
46
			$msg = 'cachedir is read-only. permissions?';
47
48
			$this->logger->error($msg);
49
			throw new CacheException($msg);
50
		}
51
52
	}
53
54
	/** @inheritdoc */
55
	public function get(string $key, $default = null){
56
		$filename = $this->getFilepath($key);
57
58
		if(is_file($filename)){
59
			$content = file_get_contents($filename);
60
61
			if(!empty($content)){
62
				$data = unserialize($content);
63
64
				if($data->ttl === null || $data->ttl > time()){
65
					return $data->content;
66
				}
67
68
				unlink($filename);
69
			}
70
71
		}
72
73
		return $default;
74
	}
75
76
	/** @inheritdoc */
77
	public function set(string $key, $value, int $ttl = null):bool{
78
		$file = $this->getFilepath($key);
79
		$dir  = dirname($file);
80
81
		if(!is_dir($dir)){
82
			mkdir($dir, 0755, true);
83
		}
84
85
		$data          = new stdClass;
86
		$data->ttl     = null;
87
		$data->content = $value;
88
89
		if($ttl !== null){
90
			$data->ttl = time() + $ttl;
91
		}
92
93
		file_put_contents($file, serialize($data));
94
95
		if(is_file($file)){
96
			return true;
97
		}
98
99
		return false; // @codeCoverageIgnore
100
	}
101
102
	/** @inheritdoc */
103
	public function delete(string $key):bool{
104
		$filename = $this->getFilepath($key);
105
106
		if(is_file($filename)){
107
			return unlink($filename);
108
		}
109
110
		return false;
111
	}
112
113
	/** @inheritdoc */
114
	public function clear():bool{
115
		$iterator = new RecursiveDirectoryIterator($this->cachedir, FilesystemIterator::CURRENT_AS_PATHNAME|FilesystemIterator::SKIP_DOTS);
116
		$return   = [];
117
118
		foreach(new RecursiveIteratorIterator($iterator) as $path){
119
120
			// skip files the parent directory - cache files are only under /a/ab/[hash]
121
			if(strpos(str_replace($this->cachedir, '', $path), DIRECTORY_SEPARATOR) === false){
122
				continue;
123
			}
124
125
			$return[] = unlink($path);
126
		}
127
128
		return $this->checkReturn($return); // @codeCoverageIgnore
129
	}
130
131
	/**
132
	 * @param string $key
133
	 *
134
	 * @return string
135
	 */
136
	protected function getFilepath(string $key):string{
137
		$h = hash('sha256', $key);
138
139
		return $this->cachedir.$h[0].DIRECTORY_SEPARATOR.$h[0].$h[1].DIRECTORY_SEPARATOR.$h;
140
	}
141
142
}
143