FileBoundCache   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 76
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 9
eloc 29
c 1
b 0
f 0
dl 0
loc 76
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A get() 0 23 5
A __construct() 0 4 1
A set() 0 19 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace TheCodingMachine\CacheUtils;
6
7
use Psr\Cache\CacheItemPoolInterface;
8
use Psr\Cache\InvalidArgumentException;
9
use function filemtime;
10
use function str_replace;
11
12
class FileBoundCache implements FileBoundCacheInterface
13
{
14
    /** @var CacheItemPoolInterface */
15
    private $cache;
16
    /** @var string */
17
    private $cachePrefix;
18
19
    /**
20
     * @param CacheItemPoolInterface $cache The underlying PSR-6 cache system.
21
     * @param string $cachePrefix The prefix to add to the cache.
22
     */
23
    public function __construct(CacheItemPoolInterface $cache, string $cachePrefix = '')
24
    {
25
        $this->cache = $cache;
26
        $this->cachePrefix = str_replace(['\\', '{', '}', '(', ')', '/', '@', ':'], '_', $cachePrefix);
27
    }
28
29
    /**
30
     * Fetches an element from the cache by key.
31
     *
32
     * @param mixed $default
33
     *
34
     * @return mixed
35
     *
36
     * @throws InvalidArgumentException
37
     */
38
    public function get(string $key, $default = null)
39
    {
40
        $item = $this->cache->getItem($this->cachePrefix . str_replace(['\\', '{', '}', '(', ')', '/', '@', ':'], '_', $key));
41
        if ($item->isHit()) {
42
            [
43
                'files' => $files,
44
                'data' => $data,
45
            ] = $item->get();
46
47
            $expired = false;
48
            foreach ($files as $fileName => $fileMTime) {
49
                if ($fileMTime !== @filemtime($fileName)) {
50
                    $expired = true;
51
                    break;
52
                }
53
            }
54
55
            if (! $expired) {
56
                return $data;
57
            }
58
        }
59
60
        return $default;
61
    }
62
63
    /**
64
     * Stores an item in the cache.
65
     *
66
     * @param mixed $item The item must be serializable.
67
     * @param array<int, string> $fileNames If one of these files is touched, the cache item is invalidated.
68
     */
69
    public function set(string $key, $item, array $fileNames, ?int $ttl = null): void
70
    {
71
        $files = [];
72
        foreach ($fileNames as $fileName) {
73
            $fileMTime = @filemtime($fileName);
74
            if ($fileMTime === false) {
75
                throw FileAccessException::cannotAccessFileModificationTime($fileName);
76
            }
77
78
            $files[$fileName] = $fileMTime;
79
        }
80
81
        $cacheItem = $this->cache->getItem($this->cachePrefix . str_replace(['\\', '{', '}', '(', ')', '/', '@', ':'], '_', $key));
82
        $cacheItem->set([
83
            'files' => $files,
84
            'data' => $item,
85
        ]);
86
        $cacheItem->expiresAfter($ttl);
87
        $this->cache->save($cacheItem);
88
    }
89
}
90