Completed
Push — master ( 5b9f4a...16a679 )
by Westin
01:49
created

Cache::writeCache()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 37
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 37
ccs 17
cts 17
cp 1
rs 8.439
c 0
b 0
f 0
cc 6
eloc 19
nc 5
nop 0
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace WShafer\Expressive\Symfony\Router\Cache;
6
7
use Symfony\Component\Routing\Route;
8
use Symfony\Component\Routing\RouteCollection;
9
use WShafer\Expressive\Symfony\Router\Exception\InvalidCacheDirectoryException;
10
use WShafer\Expressive\Symfony\Router\Exception\InvalidCacheException;
11
use WShafer\Expressive\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 15
    public function __construct(array $config = null)
37
    {
38 15
        $this->cacheEnabled = $config[self::CONFIG_CACHE_ENABLED] ?? false;
39 15
        $this->cacheFile = $config[self::CONFIG_CACHE_FILE] ?? null;
40 15
    }
41
42 2
    public function populateCollectionFromCache(RouteCollection $collection) : RouteCollection
43
    {
44 2
        if (!$this->cacheEnabled) {
45 1
            return $collection;
46
        }
47
48 1
        $routes = $this->fetchCache();
49
50 1
        foreach ($routes as $name => $route) {
51 1
            $collection->add($name, $route);
52
        }
53
54 1
        return $collection;
55
    }
56
57 8
    public function add(string $name, Route $route): void
58
    {
59 8
        if (!$this->cacheEnabled) {
60 1
            return;
61
        }
62
63
        // Lets pre-compile this for caching
64 7
        $route->compile();
65 7
        $this->cache[$name] = $route;
66 7
        $this->cacheNeedsUpdates = true;
67 7
    }
68
69 8
    public function has($name)
70
    {
71 8
        return isset($this->cache[$name]);
72
    }
73
74 7
    public function writeCache() : bool
75
    {
76 7
        if (!$this->cacheEnabled
77 7
            || !$this->cacheNeedsUpdates
78
        ) {
79 1
            return true;
80
        }
81
82 6
        $cacheDir = dirname($this->cacheFile);
83
84 6
        if (!is_dir($cacheDir)) {
85 1
            throw new InvalidCacheDirectoryException(sprintf(
86 1
                'The cache directory "%s" does not exist',
87 1
                $cacheDir
88
            ));
89
        }
90
91 5
        if (!is_writable($cacheDir)) {
92 1
            throw new InvalidCacheDirectoryException(sprintf(
93 1
                'The cache directory "%s" is not writable',
94 1
                $cacheDir
95
            ));
96
        }
97
98 4
        $bytes = file_put_contents(
99 4
            $this->cacheFile,
100 4
            serialize($this->cache)
101
        );
102
103
        // @codeCoverageIgnoreStart
104
        if ($bytes === false) {
105
            throw new WriteCacheException('Unable to write cache file: '.$this->cacheFile);
106
        }
107
        // @codeCoverageIgnoreEnd
108
109 4
        return true;
110
    }
111
112 2
    public function invalidateCacheFile() : void
113
    {
114 2
        if (!$this->cacheEnabled
115 1
            || empty($this->cacheFile)
116 2
            || !is_file($this->cacheFile)
117
        ) {
118 1
            return;
119
        }
120
121 1
        unlink($this->cacheFile);
122 1
    }
123
124 1
    public function isCacheEnabled()
125
    {
126 1
        return $this->cacheEnabled;
127
    }
128
129 1
    public function getCacheFile()
130
    {
131 1
        return $this->cacheFile;
132
    }
133
134 7
    public function doesCacheNeedsUpdate()
135
    {
136 7
        return $this->cacheNeedsUpdates;
137
    }
138
139 4
    public function fetchCache()
140
    {
141 4
        if (!$this->cacheEnabled
142 3
            || empty($this->cacheFile)
143 4
            || !is_file($this->cacheFile)
144
        ) {
145 1
            return [];
146
        }
147
148 3
        $this->cache = unserialize(file_get_contents($this->cacheFile));
149
150 3
        if (empty($this->cache)) {
151 1
            throw new InvalidCacheException('Unable to load route cache');
152
        }
153
154 2
        return $this->cache;
155
    }
156
}
157