Cache   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 145
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 25
eloc 58
dl 0
loc 145
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A invalidateCacheFile() 0 11 4
A getCacheFile() 0 3 1
A writeCache() 0 37 6
A __construct() 0 4 1
A populateCollectionFromCache() 0 13 3
A isCacheEnabled() 0 3 1
A fetchCache() 0 17 5
A has() 0 3 1
A doesCacheNeedsUpdate() 0 3 1
A add() 0 10 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace WShafer\Mezzio\Symfony\Router\Cache;
6
7
use Symfony\Component\Routing\Route;
8
use Symfony\Component\Routing\RouteCollection;
9
use WShafer\Mezzio\Symfony\Router\Exception\InvalidCacheDirectoryException;
10
use WShafer\Mezzio\Symfony\Router\Exception\InvalidCacheException;
11
use WShafer\Mezzio\Symfony\Router\Exception\WriteCacheException;
12
13
/**
14
 * @SuppressWarnings(PHPMD.LongVariable)
15
 */
16
class Cache
17
{
18
    /**
19
     * @const string Configuration key used to enable/disable fastroute caching
20
     */
21
    public const CONFIG_CACHE_ENABLED = 'cache_enabled';
22
23
    /**
24
     * @const string Configuration key used to set the cache file path
25
     */
26
    public const CONFIG_CACHE_FILE = 'cache_file';
27
28
    protected $cacheEnabled = false;
29
30
    protected $cacheFile = null;
31
32
    protected $cache = null;
33
34
    protected $cacheNeedsUpdates = false;
35
36
    public function __construct(array $config = null)
37
    {
38
        $this->cacheEnabled = $config[self::CONFIG_CACHE_ENABLED] ?? false;
39
        $this->cacheFile = $config[self::CONFIG_CACHE_FILE] ?? null;
40
    }
41
42
    /**
43
     * @throws InvalidCacheException
44
     */
45
    public function populateCollectionFromCache(RouteCollection $collection): RouteCollection
46
    {
47
        if (!$this->cacheEnabled) {
48
            return $collection;
49
        }
50
51
        $routes = $this->fetchCache();
52
53
        foreach ($routes as $name => $route) {
54
            $collection->add($name, $route);
55
        }
56
57
        return $collection;
58
    }
59
60
    public function add(string $name, Route $route): void
61
    {
62
        if (!$this->cacheEnabled) {
63
            return;
64
        }
65
66
        // Lets pre-compile this for caching
67
        $route->compile();
68
        $this->cache[$name] = $route;
69
        $this->cacheNeedsUpdates = true;
70
    }
71
72
    public function has($name)
73
    {
74
        return isset($this->cache[$name]);
75
    }
76
77
    public function writeCache(): bool
78
    {
79
        if (
80
            !$this->cacheEnabled
81
            || !$this->cacheNeedsUpdates
82
        ) {
83
            return true;
84
        }
85
86
        $cacheDir = dirname($this->cacheFile);
87
88
        if (!is_dir($cacheDir)) {
89
            throw new InvalidCacheDirectoryException(sprintf(
90
                'The cache directory "%s" does not exist',
91
                $cacheDir
92
            ));
93
        }
94
95
        if (!is_writable($cacheDir)) {
96
            throw new InvalidCacheDirectoryException(sprintf(
97
                'The cache directory "%s" is not writable',
98
                $cacheDir
99
            ));
100
        }
101
102
        $bytes = file_put_contents(
103
            $this->cacheFile,
104
            serialize($this->cache)
105
        );
106
107
        // @codeCoverageIgnoreStart
108
        if ($bytes === false) {
109
            throw new WriteCacheException('Unable to write cache file: ' . $this->cacheFile);
110
        }
111
        // @codeCoverageIgnoreEnd
112
113
        return true;
114
    }
115
116
    public function invalidateCacheFile(): void
117
    {
118
        if (
119
            !$this->cacheEnabled
120
            || empty($this->cacheFile)
121
            || !is_file($this->cacheFile)
122
        ) {
123
            return;
124
        }
125
126
        unlink($this->cacheFile);
127
    }
128
129
    public function isCacheEnabled()
130
    {
131
        return $this->cacheEnabled;
132
    }
133
134
    public function getCacheFile()
135
    {
136
        return $this->cacheFile;
137
    }
138
139
    public function doesCacheNeedsUpdate()
140
    {
141
        return $this->cacheNeedsUpdates;
142
    }
143
144
    public function fetchCache()
145
    {
146
        if (
147
            !$this->cacheEnabled
148
            || empty($this->cacheFile)
149
            || !is_file($this->cacheFile)
150
        ) {
151
            return [];
152
        }
153
154
        $this->cache = unserialize(file_get_contents($this->cacheFile));
155
156
        if (empty($this->cache)) {
157
            throw new InvalidCacheException('Unable to load route cache');
158
        }
159
160
        return $this->cache;
161
    }
162
}
163