Passed
Push — cache ( cdabb9 )
by Arnaud
10:51
created

Cache::set()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 6
c 1
b 0
f 0
nc 2
nop 3
dl 0
loc 15
rs 10
1
<?php
2
/**
3
 * This file is part of the Cecil/Cecil package.
4
 *
5
 * Copyright (c) Arnaud Ligny <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Cecil\Assets;
12
13
use Cecil\Builder;
14
use Cecil\Config;
15
use Cecil\Util;
16
use Exception;
17
use Psr\SimpleCache\CacheInterface;
18
19
class Cache implements CacheInterface
20
{
21
    /** @var Builder */
22
    protected $builder;
23
    /** @var Config */
24
    protected $config;
25
    /** @var string */
26
    protected $pool;
27
    /** @var string */
28
    protected $rootPath;
29
    /** @var string */
30
    protected $cacheDir;
31
32
    /**
33
     * @param Builder $builder
34
     * @param string  $pool
35
     * @param string  $rootPath
36
     */
37
    public function __construct(Builder $builder, string $pool, string $rootPath)
38
    {
39
        $this->builder = $builder;
40
        $this->config = $builder->getConfig();
41
        $this->pool = $pool;
42
        $this->rootPath = $rootPath;
43
        $this->cacheDir = Util::joinFile($this->config->getCachePath(), $pool);
44
    }
45
46
    /**
47
     * {@inheritdoc}
48
     */
49
    public function get($key, $default = null)
50
    {
51
        return file_get_contents($this->getValueFilePathname($key)) ?: $default;
52
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57
    public function set($key, $value, $ttl = null)
58
    {
59
        if ($ttl !== null) {
60
            throw new Exception(sprintf('%s\%s not yet implemented.', __CLASS__, __FUNCTION__));
61
        }
62
63
        // dumps value in a file
64
        Util::getFS()->dumpFile($this->getValueFilePathname($key), $value);
65
66
        // prunes hash files
67
        $this->pruneHashFiles($key);
68
69
        // creates hash file
70
        Util::getFS()->mkdir(Util::joinFile($this->cacheDir, 'hash'));
71
        Util::getFS()->touch($this->getHashFilePathname($key, $this->createHash($value)));
72
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77
    public function delete($key)
78
    {
79
        Util::getFS()->remove($this->getValueFilePathname($key));
80
        $this->pruneHashFiles($key);
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86
    public function clear()
87
    {
88
        Util::getFS()->remove($this->cacheDir);
89
    }
90
91
    /**
92
     * {@inheritdoc}
93
     */
94
    public function getMultiple($keys, $default = null)
95
    {
96
        throw new Exception(sprintf('%s\%s not yet implemented.', __CLASS__, __FUNCTION__));
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102
    public function setMultiple($values, $ttl = null)
103
    {
104
        throw new Exception(sprintf('%s\%s not yet implemented.', __CLASS__, __FUNCTION__));
105
    }
106
107
    /**
108
     * {@inheritdoc}
109
     */
110
    public function deleteMultiple($keys)
111
    {
112
        throw new Exception(sprintf('%s\%s not yet implemented.', __CLASS__, __FUNCTION__));
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118
    public function has($key)
119
    {
120
        if ($this->config->get('cache.enabled') === false) {
121
            return false;
122
        }
123
124
        if (!Util::getFS()->exists($this->getValueFilePathname($key))) {
125
            return false;
126
        }
127
128
        return true;
129
    }
130
131
    /**
132
     * Returns true if cache entry exists and hash matches.
133
     *
134
     * @param string $key
135
     * @param string $hash
136
     *
137
     * @return bool
138
     */
139
    public function hasHash(string $key, string $hash): bool
140
    {
141
        if (!$this->has($key) || !Util::getFS()->exists($this->getHashFilePathname($key, $hash))) {
142
            return false;
143
        }
144
145
        return true;
146
    }
147
148
    /**
149
     * Creates the hash (MD5) of a value.
150
     *
151
     * @param string $value
152
     *
153
     * @return string
154
     */
155
    private function createHash(string $value): string
156
    {
157
        return hash('md5', $value);
158
    }
159
160
    /**
161
     * Returns value file pathname.
162
     *
163
     * @param string $key
164
     *
165
     * @return string
166
     */
167
    private function getValueFilePathname(string $key): string
168
    {
169
        return Util::joinFile(
170
            $this->cacheDir,
171
            'files',
172
            $this->getRelativePathname($key)
173
        );
174
    }
175
176
    /**
177
     * Returns hash file pathname.
178
     *
179
     * @param string $key
180
     *
181
     * @return string
182
     */
183
    private function getHashFilePathname(string $key, string $hash): string
184
    {
185
        return Util::joinFile(
186
            $this->cacheDir,
187
            'hash',
188
            $this->preparesHashFile($this->getRelativePathname($key)).$hash
189
        );
190
    }
191
192
    /**
193
     * Returns relative path from the $rootPath.
194
     *
195
     * @param string $key
196
     *
197
     * @return string
198
     */
199
    private function getRelativePathname(string $key): string
200
    {
201
        $this->relativePath = trim(Util::getFS()->makePathRelative(dirname($key), $this->rootPath), './');
0 ignored issues
show
Bug Best Practice introduced by
The property relativePath does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
202
203
        return Util::joinFile($this->relativePath, basename($key));
204
    }
205
206
    /**
207
     * Prepares hash file path.
208
     *
209
     * @param string $path
210
     *
211
     * @return string
212
     */
213
    private function preparesHashFile(string $path): string
214
    {
215
        return str_replace(DIRECTORY_SEPARATOR, '-', $path).'_';
216
    }
217
218
    /**
219
     * Removes previous hash files.
220
     *
221
     * @param string $key
222
     *
223
     * @return void
224
     */
225
    private function pruneHashFiles(string $key): void
226
    {
227
        $path = $this->getRelativePathname($key);
228
        $pattern = Util::joinFile($this->cacheDir, 'hash', $this->preparesHashFile($path)).'*';
229
        foreach (glob($pattern) as $filename) {
230
            Util::getFS()->remove($filename);
231
        }
232
    }
233
}
234