Passed
Pull Request — master (#1013)
by lee
07:38
created

Cache   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 224
Duplicated Lines 0 %

Test Coverage

Coverage 60.27%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 67
c 2
b 0
f 0
dl 0
loc 224
ccs 44
cts 73
cp 0.6027
rs 10
wmc 23

15 Methods

Rating   Name   Duplication   Size   Complexity  
A prepareKey() 0 8 1
A createKeyFromAsset() 0 3 1
A delete() 0 13 2
A set() 0 18 2
A has() 0 8 2
A getFilePathname() 0 3 1
A getMultiple() 0 3 1
A createKeyFromValue() 0 3 1
A get() 0 12 2
A deleteMultiple() 0 3 1
A setMultiple() 0 3 1
A clear() 0 11 2
A createKeyFromFile() 0 5 2
A __construct() 0 6 1
A prune() 0 15 3
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\Collection\Page\Page;
15
use Cecil\Config;
16
use Cecil\Util;
17
use Exception;
18
use Psr\SimpleCache\CacheInterface;
19
20
class Cache implements CacheInterface
21
{
22
    /** @var Builder */
23
    protected $builder;
24
    /** @var Config */
25
    protected $config;
26
    /** @var string */
27
    protected $pool;
28
    /** @var string */
29
    protected $cacheDir;
30
31
    /**
32
     * @param Builder $builder
33
     * @param string  $pool
34
     */
35 1
    public function __construct(Builder $builder, string $pool)
36
    {
37 1
        $this->builder = $builder;
38 1
        $this->config = $builder->getConfig();
39 1
        $this->pool = $pool;
40 1
        $this->cacheDir = Util::joinFile($this->config->getCachePath(), $pool);
41 1
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46 1
    public function get($key, $default = null)
47
    {
48
        try {
49 1
            $key = $this->prepareKey($key);
50 1
            $data = unserialize(file_get_contents($this->getFilePathname($key)));
51
        } catch (Exception $e) {
52
            $this->builder->getLogger()->error($e->getMessage());
53
54
            return $default;
55
        }
56
57 1
        return $data['value'];
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 1
    public function set($key, $value, $ttl = null)
64
    {
65
        try {
66 1
            $key = $this->prepareKey($key);
67 1
            $data = serialize([
68 1
                'value'      => $value,
69 1
                'expiration' => time() + $ttl,
70
            ]);
71
72 1
            $this->prune($key);
73 1
            Util::getFS()->dumpFile($this->getFilePathname($key), $data);
74
        } catch (Exception $e) {
75
            $this->builder->getLogger()->error($e->getMessage());
76
77
            return false;
78
        }
79
80 1
        return true;
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86
    public function delete($key)
87
    {
88
        try {
89
            $key = $this->prepareKey($key);
90
            Util::getFS()->remove($this->getFilePathname($key));
91
            $this->prune($key);
92
        } catch (Exception $e) {
93
            $this->builder->getLogger()->error($e->getMessage());
94
95
            return false;
96
        }
97
98
        return true;
99
    }
100
101
    /**
102
     * {@inheritdoc}
103
     */
104
    public function clear()
105
    {
106
        try {
107
            Util::getFS()->remove($this->cacheDir);
108
        } catch (Exception $e) {
109
            $this->builder->getLogger()->error($e->getMessage());
110
111
            return false;
112
        }
113
114
        return true;
115
    }
116
117
    /**
118
     * {@inheritdoc}
119
     */
120
    public function getMultiple($keys, $default = null)
121
    {
122
        throw new Exception(sprintf('%s::%s not yet implemented.', __CLASS__, __FUNCTION__));
123
    }
124
125
    /**
126
     * {@inheritdoc}
127
     */
128
    public function setMultiple($values, $ttl = null)
129
    {
130
        throw new Exception(sprintf('%s::%s not yet implemented.', __CLASS__, __FUNCTION__));
131
    }
132
133
    /**
134
     * {@inheritdoc}
135
     */
136
    public function deleteMultiple($keys)
137
    {
138
        throw new Exception(sprintf('%s::%s not yet implemented.', __CLASS__, __FUNCTION__));
139
    }
140
141
    /**
142
     * {@inheritdoc}
143
     */
144 1
    public function has($key)
145
    {
146 1
        $key = $this->prepareKey($key);
147 1
        if (!Util::getFS()->exists($this->getFilePathname($key))) {
148 1
            return false;
149
        }
150
151 1
        return true;
152
    }
153
154
    /**
155
     * Creates a cache key from a value (MD5 hash).
156
     *
157
     * @param string $value
158
     *
159
     * @return string
160
     */
161 1
    public function createKeyFromValue(string $value): string
162
    {
163 1
        return hash('md5', $value);
164
    }
165
166
    /**
167
     * Creates a cache key from a file (with MD5 hash).
168
     *
169
     * @param string $file
170
     * @param string $path
171
     *
172
     * @return string
173
     */
174 1
    public function createKeyFromFile(string $file, string $path): string
175
    {
176 1
        $content = file_get_contents($file);
177
178 1
        return \sprintf('%s__%s', $path, $content !== false ? $this->createKeyFromValue($content) : '');
179
    }
180
181
    /**
182
     * Creates a cache key from an Asset (with MD5 hash).
183
     *
184
     * @param Asset $asset
185
     *
186
     * @return string
187
     */
188 1
    public function createKeyFromAsset(Asset $asset): string
189
    {
190 1
        return \sprintf('%s__%s', $asset['path'], $this->createKeyFromValue($asset['source'] ?? ''));
191
    }
192
193
    /**
194
     * Returns cache file pathname.
195
     *
196
     * @param string $key
197
     *
198
     * @return string
199
     */
200 1
    private function getFilePathname(string $key): string
201
    {
202 1
        return Util::joinFile($this->cacheDir, $key);
203
    }
204
205
    /**
206
     * Removes previous cache files.
207
     *
208
     * @param string $key
209
     *
210
     * @return bool
211
     */
212 1
    private function prune(string $key): bool
213
    {
214
        try {
215 1
            $key = $this->prepareKey($key);
216 1
            $pattern = Util::joinFile($this->cacheDir, explode('__', $key)[0]).'*';
217 1
            foreach (glob($pattern) as $filename) {
218 1
                Util::getFS()->remove($filename);
219
            }
220
        } catch (Exception $e) {
221
            $this->builder->getLogger()->error($e->getMessage());
222
223
            return false;
224
        }
225
226 1
        return true;
227
    }
228
229
    /**
230
     * $key must be a string.
231
     *
232
     * @param string $key
233
     *
234
     * @return string
235
     */
236 1
    private function prepareKey(string $key): string
237
    {
238 1
        $key = str_replace(['https://', 'http://'], '', $key);
239 1
        $key = Page::slugify($key);
240 1
        $key = trim($key, '/');
241 1
        $key = str_replace(['\\', '/'], ['-', '-'], $key);
242
243 1
        return $key;
244
    }
245
}
246